Passed
Pull Request — master (#5)
by Artem
05:27
created

AuthService::userCache()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 6
c 0
b 0
f 0
nc 3
nop 3
dl 0
loc 13
rs 10
ccs 0
cts 7
cp 0
crap 12
1
<?php
2
3
namespace Slides\Connector\Auth;
4
5
use Illuminate\Support\Facades\DB;
6
use Illuminate\Contracts\Auth\Guard as GuardContract;
7
use Slides\Connector\Auth\Sync\User as RemoteUser;
8
9
/**
10
 * Class AuthService
11
 *
12
 * @package Slides\Connector\Auth
13
 */
14
class AuthService
15
{
16
    const HANDLER_USER_CREATE      = 'create';
17
    const HANDLER_USER_UPDATE      = 'update';
18
    const HANDLER_USER_DELETE      = 'delete';
19
    const HANDLER_USER_SYNC_CREATE = 'sync.create';
20
    const HANDLER_USER_SYNC_UPDATE = 'sync.update';
21
    const HANDLER_USER_SYNC_DELETE = 'sync.delete';
22
23
    /**
24
     * The class with handler methods
25
     *
26
     * @var object
27
     */
28
    protected $handlersContainer;
29
30
    /**
31
     * HTTP Client
32
     *
33
     * @var Client
34
     */
35
    protected $client;
36
37
    /**
38
     * The authentication guard.
39
     *
40
     * @var TokenGuard
41
     */
42
    protected $guard;
43
44
    /**
45
     * The fallback authentication guard.
46
     *
47
     * @var GuardContract
48
     */
49
    protected $fallbackGuard;
50
51
    /**
52
     * Checks whether a service is disabled
53
     *
54
     * @return bool
55
     */
56 10
    public function disabled(): bool
57
    {
58 10
        return !config('connector.auth.enabled', true);
59
    }
60
61
    /**
62
     * AuthService constructor.
63
     *
64
     * @param Client $client
65
     */
66 17
    public function __construct(Client $client)
67
    {
68 17
        $this->client = $client;
69 17
    }
70
71
    /**
72
     * Authenticate a user.
73
     *
74
     * @param string $email
75
     * @param string $password
76
     * @param bool $remember
77
     *
78
     * @return mixed
79
     *
80
     * @throws
81
     */
82 4
    public function login(string $email, string $password, bool $remember = false)
83
    {
84 4
        if($this->disabled()) {
85
            return $this->handleFallback('login', compact('email', 'password', 'remember'));
86
        }
87
88 4
        return $this->guard->login($email, $password, $remember);
89
    }
90
91
    /**
92
     * Authenticate a user without the password.
93
     *
94
     * Warning! This method has implemented temporarily to make able to login users
95
     * who use Social Auth on 24Templates. MUST NOT be used in any other cases.
96
     *
97
     * @param string $email
98
     * @param bool $remember
99
     *
100
     * @return mixed
101
     *
102
     * @throws
103
     */
104 2
    public function unsafeLogin(string $email, bool $remember = false)
105
    {
106 2
        if($this->disabled()) {
107
            return $this->handleFallback('unsafeLogin', compact('email', 'remember'));
108
        }
109
110 2
        return $this->guard->unsafeLogin($email, $remember);
111
    }
112
113
    /**
114
     * Logout a user.
115
     *
116
     * @return mixed
117
     *
118
     * @throws
119
     */
120
    public function logout()
121
    {
122
        if($this->disabled()) {
123
            return $this->handleFallback('logout');
124
        }
125
126
        $this->guard->logout();
127
128
        return null;
129
    }
130
131
    /**
132
     * Create a remote user.
133
     *
134
     * @param int $userId
135
     * @param string $name
136
     * @param string $email
137
     * @param string $password
138
     * @param string $country
139
     *
140
     * @return array
141
     */
142 2
    public function register(int $userId, string $name, string $email, string $password, string $country)
143
    {
144 2
        if($this->disabled()) {
145
            return [];
146
        }
147
148 2
        return $this->client->request('register', compact('userId', 'name', 'email', 'password', 'country'));
149
    }
150
151
    /**
152
     * Send an email with a password resetting link
153
     *
154
     * @param string $email
155
     *
156
     * @return bool
157
     *
158
     * @throws
159
     */
160 2
    public function forgot(string $email)
161
    {
162 2
        if($this->disabled()) {
163
            return $this->handleFallback('forgot', compact('email'));
164
        }
165
166 2
        $this->client->request('forgot', compact('email'));
167
168 2
        return $this->client->success(true);
169
    }
170
171
    /**
172
     * Checks whether password reset token is valid
173
     *
174
     * @param string $token
175
     * @param string $email
176
     *
177
     * @return string|false
178
     *
179
     * @throws
180
     */
181 2
    public function validatePasswordResetToken(string $token, string $email)
182
    {
183 2
        if($this->disabled()) {
184
            return $this->handleFallback('validateReset', compact('token', 'email'));
185
        }
186
187 2
        $response = $this->client->request('validateReset', compact('token', 'email'));
188
189 2
        if(!$this->client->success(true)) {
190 1
            return false;
191
        }
192
193 1
        return array_get($response, 'user.email');
194
    }
195
196
    /**
197
     * Checks whether password reset token is valid
198
     *
199
     * @param string $token
200
     * @param string $email
201
     * @param string $password
202
     * @param string $confirmation
203
     *
204
     * @return array|false
205
     *
206
     * @throws
207
     */
208 2
    public function resetPassword(string $token, string $email, string $password, string $confirmation)
209
    {
210 2
        $parameters = compact('token', 'email', 'password', 'confirmation');
211
212 2
        if($this->disabled()) {
213
            return $this->handleFallback('resetPassword', $parameters);
214
        }
215
216 2
        $response = $this->client->request('reset', $parameters);
217
218 2
        if(!$this->client->success(true)) {
219 1
            return false;
220
        }
221
222 1
        return $response;
223
    }
224
225
    /**
226
     * Update a remote user
227
     *
228
     * @param int $id Local user ID
229
     * @param string|null $name
230
     * @param string|null $email
231
     * @param string|null $password Raw password, in case if changed
232
     * @param string|null $country Two-letter country code.
233
     *
234
     * @return array|false
235
     */
236 2
    public function update(int $id, ?string $name, ?string $email, ?string $password, ?string $country)
237
    {
238 2
        if($this->disabled()) {
239
            return false;
240
        }
241
242 2
        $attributes = array_filter(compact('id', 'name', 'email', 'password', 'country'));
243
244 2
        $response = $this->client->request('update', compact('id', 'attributes'));
245
246 2
        if(!$this->client->success(true)) {
247 1
            return false;
248
        }
249
250 1
        return $response;
251
    }
252
253
    /**
254
     * Safely delete a remote user.
255
     *
256
     * @param int $id Remote user ID.
257
     *
258
     * @return array|false
259
     */
260
    public function delete(int $id)
261
    {
262
        if($this->disabled()) {
263
            return false;
264
        }
265
266
        $response = $this->client->request('delete', compact('id'));
267
268
        if(!$this->client->success(true)) {
269
            return false;
270
        }
271
272
        return $response;
273
    }
274
275
    /**
276
     * Restore a remote user.
277
     *
278
     * @param int $id Remote user ID.
279
     *
280
     * @return array|false
281
     */
282
    public function restore(int $id)
283
    {
284
        if($this->disabled()) {
285
            return false;
286
        }
287
288
        $response = $this->client->request('restore', compact('id'));
289
290
        if(!$this->client->success(true)) {
291
            return false;
292
        }
293
294
        return $response;
295
    }
296
297
    /**
298
     * Retrieve a remote user
299
     *
300
     * @return RemoteUser|null
301
     */
302
    public function retrieveByToken()
303
    {
304
        if($this->disabled()) {
305
            return null;
306
        }
307
308
        try {
309
            $response = $this->client->request('me');
310
        }
311
        catch(\Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException $e) {
312
            return null;
313
        }
314
315
        if(!$this->client->success(true)) {
316
            return null;
317
        }
318
319
        return RemoteUser::createFromResponse($response);
320
    }
321
322
    /**
323
     * Load handlers from the given container.
324
     *
325
     * @param $container
326
     *
327
     * @return void
328
     */
329 17
    public function loadHandlers($container)
330
    {
331 17
        $this->handlersContainer = $container;
332 17
    }
333
334
    /**
335
     * Run a handler
336
     *
337
     * @param string $key
338
     * @param array $parameters
339
     * @param \Closure|null $fallback
340
     *
341
     * @return mixed
342
     *
343
     * @throws \Exception
344
     */
345 7
    public function handle(string $key, array $parameters = [], \Closure $fallback = null)
346
    {
347 7
        $handler = camel_case(str_replace('.', ' ', $key));
348
349 7
        if(!method_exists($this->handlersContainer, $handler)) {
350 1
            throw new \InvalidArgumentException("Handler `{$handler}` cannot be found");
351
        }
352
353
        return $this->ensure(function() use ($handler, $parameters) {
354 6
            return call_user_func_array([$this->handlersContainer, $handler], $parameters);
355 6
        }, $fallback);
356
    }
357
358
    /**
359
     * Run a fallback handler.
360
     *
361
     * @param string $key
362
     * @param array $parameters
363
     * @param \Closure|null $fallback
364
     *
365
     * @return mixed
366
     *
367
     * @throws \Exception
368
     */
369 2
    public function handleFallback(string $key, array $parameters = [], \Closure $fallback = null)
370
    {
371 2
        $key = 'fallback' . studly_case($key);
372 2
        $parameters = array_merge(['guard' => $this->fallbackGuard], $parameters);
373
374 2
        return $this->handle($key, $parameters, $fallback);
375
    }
376
377
    /**
378
     * Store/retrieve a parameter from the cache.
379
     *
380
     * @param string $key
381
     * @param mixed $value
382
     *
383
     * @return Cache|void
384
     */
385
    public function cache(string $key = null, $value = null)
386
    {
387
        $cache = new Cache();
388
389
        if(!func_num_args()) {
390
            return $cache;
391
        }
392
393
        if(func_num_args() === 1) {
394
            return $cache->get($key);
0 ignored issues
show
Bug introduced by
It seems like $key can also be of type null; however, parameter $key of Slides\Connector\Auth\Cache::get() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

394
            return $cache->get(/** @scrutinizer ignore-type */ $key);
Loading history...
395
        }
396
397
        $cache->set($key, null, $value);
0 ignored issues
show
Bug introduced by
It seems like $key can also be of type null; however, parameter $key of Slides\Connector\Auth\Cache::set() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

397
        $cache->set(/** @scrutinizer ignore-type */ $key, null, $value);
Loading history...
398
    }
399
400
    /**
401
     * Store/retrieve a user's parameter from the cache.
402
     *
403
     * @param int $remoteId The remote user ID.
404
     * @param string|null $key
405
     * @param mixed $value
406
     *
407
     * @return Cache|mixed|void
408
     */
409
    public function userCache(int $remoteId, string $key = null, $value = null)
410
    {
411
        $cache = new Cache();
412
413
        if(func_num_args() === 1) {
414
            return $cache->getUserParams($remoteId);
415
        }
416
417
        if(func_num_args() === 2) {
418
            return $cache->getUserParam($remoteId, $key);
0 ignored issues
show
Bug introduced by
It seems like $key can also be of type null; however, parameter $key of Slides\Connector\Auth\Cache::getUserParam() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

418
            return $cache->getUserParam($remoteId, /** @scrutinizer ignore-type */ $key);
Loading history...
419
        }
420
421
        $cache->setUserParam($remoteId, $key, $value);
0 ignored issues
show
Bug introduced by
It seems like $key can also be of type null; however, parameter $key of Slides\Connector\Auth\Cache::setUserParam() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

421
        $cache->setUserParam($remoteId, /** @scrutinizer ignore-type */ $key, $value);
Loading history...
422
    }
423
424
    /**
425
     * Performs a callback logic within database transaction.
426
     *
427
     * @param \Closure $callback
428
     * @param \Closure|null $fallback The callback which should fired when exception throws.
429
     *
430
     * @return mixed
431
     *
432
     * @throws \Exception
433
     */
434 6
    protected function ensure(\Closure $callback, \Closure $fallback = null)
435
    {
436 6
        DB::beginTransaction();
437
438
        try {
439 6
            $output = $callback();
440
        }
441 3
        catch(\Exception $e) {
442 2
            DB::rollBack();
443
444 2
            if(is_null($fallback)) {
445
                throw $e;
446
            }
447
448 2
            $output = $fallback($e);
449
        }
450
451 5
        DB::commit();
452
453 5
        return $output;
454
    }
455
456
    /**
457
     * Set authentication guard.
458
     *
459
     * @param \Slides\Connector\Auth\TokenGuard $guard
460
     */
461 17
    public function setGuard(TokenGuard $guard): void
462
    {
463 17
        $this->guard = $guard;
464 17
    }
465
466
    /**
467
     * Set fallback authentication guard.
468
     *
469
     * @param GuardContract $guard
470
     */
471
    public function setFallbackGuard(GuardContract $guard): void
472
    {
473
        $this->fallbackGuard = $guard;
474
    }
475
476
    /**
477
     * Set HTTP Client.
478
     *
479
     * @param Client $client
480
     */
481
    public function setClient(Client $client): void
482
    {
483
        $this->client = $client;
484
    }
485
486
    /**
487
     * Get HTTP client.
488
     *
489
     * @return Client
490
     */
491 17
    public function getClient(): Client
492
    {
493 17
        return $this->client;
494
    }
495
}