Failed Conditions
Push — master ( 4b5d02...3af7eb )
by Florent
04:35
created

AccessTokenByReferenceRepository::save()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2017 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\Bundle\Server\Model;
15
16
use OAuth2Framework\Bundle\Server\Service\RandomIdGenerator;
17
use OAuth2Framework\Component\Server\Model\AccessToken\AccessToken;
18
use OAuth2Framework\Component\Server\Model\AccessToken\AccessTokenId;
19
use OAuth2Framework\Component\Server\Model\AccessToken\AccessTokenRepositoryInterface;
20
use OAuth2Framework\Component\Server\Model\Client\ClientId;
21
use OAuth2Framework\Component\Server\Model\DataBag\DataBag;
22
use OAuth2Framework\Component\Server\Model\Event\Event;
23
use OAuth2Framework\Component\Server\Model\Event\EventStoreInterface;
24
use OAuth2Framework\Component\Server\Model\RefreshToken\RefreshTokenId;
25
use OAuth2Framework\Component\Server\Model\ResourceOwner\ResourceOwnerId;
26
use OAuth2Framework\Component\Server\Model\ResourceServer\ResourceServerId;
27
use SimpleBus\Message\Recorder\RecordsMessages;
28
use Symfony\Component\Cache\Adapter\AdapterInterface;
29
30
final class AccessTokenByReferenceRepository implements AccessTokenRepositoryInterface
31
{
32
    /**
33
     * @var int
34
     */
35
    private $lifetime;
36
37
    /**
38
     * @var int
39
     */
40
    private $minLength;
41
42
    /**
43
     * @var int
44
     */
45
    private $maxLength;
46
47
    /**
48
     * @var EventStoreInterface
49
     */
50
    private $eventStore;
51
52
    /**
53
     * @var RecordsMessages
54
     */
55
    private $eventRecorder;
56
57
    /**
58
     * @var AdapterInterface|null
59
     */
60
    private $cache;
61
62
    /**
63
     * AccessTokenByReferenceRepository constructor.
64
     *
65
     * @param int                 $minLength
66
     * @param int                 $maxLength
67
     * @param int                 $lifetime
68
     * @param EventStoreInterface $eventStore
69
     * @param RecordsMessages     $eventRecorder
70
     */
71
    public function __construct(int $minLength, int $maxLength, int $lifetime, EventStoreInterface $eventStore, RecordsMessages $eventRecorder)
72
    {
73
        $this->minLength = $minLength;
74
        $this->maxLength = $maxLength;
75
        $this->lifetime = $lifetime;
76
        $this->eventStore = $eventStore;
77
        $this->eventRecorder = $eventRecorder;
78
    }
79
80
    /**
81
     * @param AdapterInterface $cache
82
     */
83
    public function enableDomainObjectCaching(AdapterInterface $cache)
84
    {
85
        $this->cache = $cache;
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    public function find(AccessTokenId $accessTokenId)
92
    {
93
        $accessToken = $this->getFromCache($accessTokenId);
94
        if (null === $accessToken) {
95
            $events = $this->eventStore->getEvents($accessTokenId);
96
            if (!empty($events)) {
97
                $accessToken = $this->getFromEvents($events);
98
                $this->cacheObject($accessToken);
99
            }
100
        }
101
102
        return $accessToken;
103
    }
104
105
    /**
106
     * @param AccessToken $accessToken
107
     */
108
    public function save(AccessToken $accessToken)
109
    {
110
        $events = $accessToken->recordedMessages();
111
        foreach ($events as $event) {
112
            $this->eventStore->save($event);
113
            $this->eventRecorder->record($event);
114
        }
115
        $accessToken->eraseMessages();
116
        $this->cacheObject($accessToken);
117
    }
118
119
    /**
120
     * {@inheritdoc}
121
     */
122
    public function create(ResourceOwnerId $resourceOwnerId, ClientId $clientId, DataBag $parameters, DataBag $metadatas, array $scopes, ? RefreshTokenId $refreshTokenId, ? ResourceServerId $resourceServerId, ? \DateTimeImmutable $expiresAt): AccessToken
123
    {
124
        if (null === $expiresAt) {
125
            $expiresAt = new \DateTimeImmutable(sprintf('now +%u seconds', $this->lifetime));
126
        }
127
128
        $accessTokenId = AccessTokenId::create(RandomIdGenerator::generate($this->minLength, $this->maxLength));
129
        $accessToken = AccessToken::createEmpty();
130
        $accessToken = $accessToken->create($accessTokenId, $resourceOwnerId, $clientId, $parameters, $metadatas, $scopes, $expiresAt, $refreshTokenId, $resourceServerId);
131
132
        return $accessToken;
133
    }
134
135
    /**
136
     * @param Event[] $events
137
     *
138
     * @return AccessToken
139
     */
140
    private function getFromEvents(array $events): AccessToken
141
    {
142
        $accessToken = AccessToken::createEmpty();
143
        foreach ($events as $event) {
144
            $accessToken = $accessToken->apply($event);
145
        }
146
147
        return $accessToken;
148
    }
149
150
    /**
151
     * @param AccessTokenId $accessTokenId
152
     *
153
     * @return AccessToken|null
154
     */
155
    private function getFromCache(AccessTokenId $accessTokenId): ? AccessToken
156
    {
157
        if (null !== $this->cache) {
158
            $itemKey = sprintf('oauth2-access_token-%s', $accessTokenId->getValue());
159
            $item = $this->cache->getItem($itemKey);
160
            if ($item->isHit()) {
161
                return $item->get();
162
            }
163
        }
164
165
        return null;
166
    }
167
168
    /**
169
     * @param AccessToken $accessToken
170
     */
171
    private function cacheObject(AccessToken $accessToken)
172
    {
173
        if (null !== $this->cache) {
174
            $itemKey = sprintf('oauth2-access_token-%s', $accessToken->getTokenId()->getValue());
175
            $item = $this->cache->getItem($itemKey);
176
            $item->set($accessToken);
177
            $item->tag(['oauth2_server', 'access_token', $itemKey]);
178
            $this->cache->save($item);
179
        }
180
    }
181
}
182