Completed
Push — master ( cef25e...758dfd )
by Hilmi Erdem
02:56
created

TemporaryAccessService::getNow()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 4
cp 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
namespace Erdemkeren\TemporaryAccess;
4
5
use Carbon\Carbon;
6
use Erdemkeren\TemporaryAccess\Token\TokenInterface;
7
use Erdemkeren\TemporaryAccess\Contracts\AccessTokenInterface;
8
use Erdemkeren\TemporaryAccess\Contracts\AccessTokenRepositoryInterface;
9
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
10
use Erdemkeren\TemporaryAccess\Token\TokenGenerator\TokenGeneratorInterface;
11
12
final class TemporaryAccessService
13
{
14
    /**
15
     * The access token repository implementation.
16
     *
17
     * @var AccessTokenRepositoryInterface
18
     */
19
    private $repository;
20
21
    /**
22
     * The token generator implementation.
23
     *
24
     * @var TokenGeneratorInterface
25
     */
26
    private $tokenGenerator;
27
28
    /**
29
     * TemporaryAccessService constructor.
30
     *
31
     * @param AccessTokenRepositoryInterface $repository     The access token repository implementation.
32
     * @param TokenGeneratorInterface        $tokenGenerator The token generator implementation.
33
     */
34
    public function __construct(AccessTokenRepositoryInterface $repository, TokenGeneratorInterface $tokenGenerator)
35
    {
36
        $this->repository = $repository;
37
        $this->tokenGenerator = $tokenGenerator;
38
    }
39
40
    /**
41
     * Retrieve an access token from the storage by the actual token.
42
     *
43
     * @param AuthenticatableContract $authenticatable The authenticatable who owns the token.
44
     * @param string|TokenInterface   $encryptedText   The token of the authenticatable.
45
     *
46
     * @return null|AccessTokenInterface
47
     */
48
    public function retrieve(AuthenticatableContract $authenticatable, $encryptedText)
49
    {
50
        $authenticatableIdentifier = $authenticatable->getAuthIdentifier();
51
52
        return $this->retrieveFromRepository($authenticatableIdentifier, (string) $encryptedText);
53
    }
54
55
    /**
56
     * Retrieve an access token from the storage by the plain token.
57
     *
58
     * @param AuthenticatableContract $authenticatable The authenticatable who owns the token.
59
     * @param string                  $plainText       The token of the authenticatable.
60
     *
61
     * @return null|AccessTokenInterface
62
     */
63
    public function retrieveUsingPlainText(AuthenticatableContract $authenticatable, $plainText)
64
    {
65
        if (! $plainText instanceof TokenInterface) {
66
            $plainText = $this->makeTokenFromPlainText($plainText);
67
        }
68
69
        return $this->retrieve($authenticatable, $plainText);
70
    }
71
72
    /**
73
     * Determine if an access token exists and is valid.
74
     *
75
     * @param  AuthenticatableContract $authenticatable The authenticatable who owns the token.
76
     * @param  string|TokenInterface   $encryptedText   The encrypted token of the authenticatable.
77
     *
78
     * @return bool
79
     */
80
    public function check(AuthenticatableContract $authenticatable, $encryptedText)
81
    {
82
        return (bool) $this->retrieve($authenticatable, $encryptedText);
83
    }
84
85
    /**
86
     * Determine if an access token exists and is valid.
87
     *
88
     * @param  AuthenticatableContract $authenticatable The authenticatable who owns the token.
89
     * @param  string                  $plainText       The plain token of the authenticatable.
90
     *
91
     * @return bool
92
     */
93
    public function checkUsingPlainText(AuthenticatableContract $authenticatable, $plainText)
94
    {
95
        $token = $this->makeTokenFromPlainText($plainText);
96
97
        return $this->check($authenticatable, $token);
98
    }
99
100
    /**
101
     * Determine if an access token record exists and prolong the expire date if so.
102
     * If no prolong time given, we will reset the original expire time.
103
     *
104
     * @param  AuthenticatableContract $authenticatable The authenticatable who owns the token.
105
     * @param  string|TokenInterface   $encryptedText   The token of the authenticatable.
106
     * @param  int|null                $prolong         The prolong time in minutes.
107
     *
108
     * @return bool|AccessTokenInterface
109
     */
110
    public function checkAndProlong(AuthenticatableContract $authenticatable, $encryptedText, $prolong = null)
111
    {
112
        if (! $accessToken = $this->retrieve($authenticatable, $encryptedText)) {
113
            return false;
114
        }
115
116
        return $this->prolongAndUpdateAccessToken($accessToken, $prolong);
117
    }
118
119
    /**
120
     * Determine if an access token record exists and prolong the expire date if so.
121
     * If no prolong time given, we will reset the original expire time.
122
     *
123
     * @param  AuthenticatableContract $authenticatable The authenticatable who owns the token.
124
     * @param  string                  $plainText       The token of the authenticatable.
125
     * @param  int|null                $prolong         The prolong time in minutes.
126
     *
127
     * @return bool|AccessTokenInterface
128
     */
129
    public function checkUsingPlainTextAndProlong(AuthenticatableContract $authenticatable, $plainText, $prolong = null)
130
    {
131
        $token = $this->makeTokenFromPlainText($plainText);
132
133
        return $this->checkAndProlong($authenticatable, $token, $prolong);
134
    }
135
136
    /**
137
     * Generate a new access token in the storage and get the token.
138
     *
139
     * @param  AuthenticatableContract $authenticatable The authenticatable who owns the token.
140
     * @param  Carbon|null             $expiresAt       The optional expire date of the access token.
141
     *
142
     * @return AccessTokenInterface
143
     */
144
    public function generate(AuthenticatableContract $authenticatable, Carbon $expiresAt = null)
145
    {
146
        $token = $this->tokenGenerator->generate();
147
        $authenticatableId = $authenticatable->getAuthIdentifier();
148
        $expiresAt = $expiresAt ? (string) $expiresAt : null;
149
150
        $payload = (array) $this->repository->store($authenticatableId, (string) $token, $expiresAt);
151
152
        return $this->makeAccessToken($token, $payload);
153
    }
154
155
    /**
156
     * Update an access token in the storage.
157
     *
158
     * @param  AccessTokenInterface $accessToken The access token to be updated.
159
     *
160
     * @return bool
161
     */
162
    public function update(AccessTokenInterface $accessToken)
163
    {
164
        $token = (string) $accessToken;
165
        $expiresAt = (string) $accessToken->expiresAt();
166
        $authenticatableId = $accessToken->authenticatableId();
167
168
        return $this->repository->update($authenticatableId, $token, $expiresAt);
169
    }
170
171
    /**
172
     * Revive an token from the given plain text.
173
     *
174
     * @param  string $plainText The plain text to be converted back to token instance.
175
     *
176
     * @return TokenInterface
177
     */
178
    public function makeTokenFromPlainText($plainText)
179
    {
180
        return $this->tokenGenerator->fromPlain($plainText);
181
    }
182
183
    /**
184
     * Revive an token from the given plain text.
185
     *
186
     * @param  string $encryptedText The encrypted token to be converted back to token instance.
187
     *
188
     * @return TokenInterface
189
     */
190
    public function makeTokenFromEncryptedText($encryptedText)
191
    {
192
        return $this->tokenGenerator->fromEncrypted($encryptedText);
193
    }
194
195
    /**
196
     * Retrieve the first resource by the given attributes.
197
     *
198
     * @param  array $queryParams The key - value pairs to match.
199
     * @param  array $attributes  The attributes to be returned from the storage.
200
     *
201
     * @return AccessTokenInterface|null
202
     */
203
    public function retrieveByAttributes(array $queryParams, array $attributes = ['*'])
204
    {
205
        if (! $attributes = $this->repository->retrieveByAttributes($queryParams, $attributes)) {
206
            return;
207
        }
208
209
        return $attributes ? $this->makeAccessToken((array) $attributes) : null;
210
    }
211
212
    /**
213
     * Delete the given access token from the storage.
214
     *
215
     * @param  AccessTokenInterface|string $accessToken The access token or the encrypted text to be deleted.
216
     *
217
     * @return bool
218
     */
219
    public function delete($accessToken)
220
    {
221
        return (bool) $this->repository->delete((string) $accessToken);
222
    }
223
224
    /**
225
     * Delete the expired access tokens from the storage.
226
     *
227
     * @return void
228
     */
229
    public function deleteExpired()
230
    {
231
        $this->repository->deleteExpired();
232
    }
233
234
    /**
235
     * Retrieve an access token from the storage.
236
     *
237
     * @param  int    $authenticatableId
238
     * @param  string $encryptedText
239
     *
240
     * @return GenericAccessToken|null
241
     */
242
    private function retrieveFromRepository($authenticatableId, $encryptedText)
243
    {
244
        if (! $attributes = $this->repository->retrieve($authenticatableId, $encryptedText)) {
245
            return;
246
        }
247
248
        return $this->makeAccessToken((array) $attributes);
249
    }
250
251
    /**
252
     * Prolong the access token then update it in the storage.
253
     *
254
     * @param  AccessTokenInterface $accessToken
255
     * @param  int|null             $prolong
256
     *
257
     * @return bool|AccessTokenInterface
258
     */
259
    private function prolongAndUpdateAccessToken(AccessTokenInterface $accessToken, $prolong = null)
260
    {
261
        $accessToken = $this->prolongAccessToken($accessToken, $prolong);
262
263
        if ($this->update($accessToken)) {
264
            return $accessToken;
265
        }
266
267
        return false;
268
    }
269
270
    /**
271
     * Prolong an access token.
272
     *
273
     * @param AccessTokenInterface $accessToken
274
     * @param int|null             $prolong
275
     *
276
     * @return AccessTokenInterface
277
     */
278
    private function prolongAccessToken(AccessTokenInterface $accessToken, $prolong = null)
279
    {
280
        $prolong = $prolong ? $prolong * 60 : $this->getNow()->diffInSeconds($accessToken->createdAt());
281
282
        return $accessToken->prolong($prolong);
283
    }
284
285
    /**
286
     * Get a new access token instance with the given attributes.
287
     *
288
     * @param array|TokenInterface $token
289
     * @param array                $attributes
290
     *
291
     * @return GenericAccessToken
292
     */
293
    private function makeAccessToken($token, array $attributes = [])
294
    {
295
        if (! $token instanceof TokenInterface) {
296
            $attributes = $token;
297
298
            $token = $this->makeTokenFromEncryptedText(array_pull($attributes, 'token'));
299
        }
300
301
        return new GenericAccessToken($token, $attributes);
302
    }
303
304
    /**
305
     * Get the current UNIX timestamp.
306
     *
307
     * @return Carbon
308
     */
309
    private function getNow()
310
    {
311
        return Carbon::now();
312
    }
313
}
314