Passed
Push — master ( cf4fbb...361e7c )
by Artem
02:40
created

AuthService::retrieveByToken()   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
nc 3
nop 0
dl 0
loc 13
rs 10
c 0
b 0
f 0
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
     *
139
     * @return array
140
     */
141 2
    public function register(int $userId, string $name, string $email, string $password)
142
    {
143 2
        if($this->disabled()) {
144
            return [];
145
        }
146
147 2
        return $this->client->request('register', compact('userId', 'name', 'email', 'password'));
148
    }
149
150
    /**
151
     * Send an email with a password resetting link
152
     *
153
     * @param string $email
154
     *
155
     * @return bool
156
     *
157
     * @throws
158
     */
159 2
    public function forgot(string $email)
160
    {
161 2
        if($this->disabled()) {
162
            return $this->handleFallback('forgot', compact('email'));
163
        }
164
165 2
        $this->client->request('forgot', compact('email'));
166
167 2
        return $this->client->success(true);
168
    }
169
170
    /**
171
     * Checks whether password reset token is valid
172
     *
173
     * @param string $token
174
     * @param string $email
175
     *
176
     * @return string|false
177
     *
178
     * @throws
179
     */
180 2
    public function validatePasswordResetToken(string $token, string $email)
181
    {
182 2
        if($this->disabled()) {
183
            return $this->handleFallback('validateReset', compact('token', 'email'));
184
        }
185
186 2
        $response = $this->client->request('validateReset', compact('token', 'email'));
187
188 2
        if(!$this->client->success(true)) {
189 1
            return false;
190
        }
191
192 1
        return array_get($response, 'user.email');
193
    }
194
195
    /**
196
     * Checks whether password reset token is valid
197
     *
198
     * @param string $token
199
     * @param string $email
200
     * @param string $password
201
     * @param string $confirmation
202
     *
203
     * @return array|false
204
     *
205
     * @throws
206
     */
207 2
    public function resetPassword(string $token, string $email, string $password, string $confirmation)
208
    {
209 2
        $parameters = compact('token', 'email', 'password', 'confirmation');
210
211 2
        if($this->disabled()) {
212
            return $this->handleFallback('resetPassword', $parameters);
213
        }
214
215 2
        $response = $this->client->request('reset', $parameters);
216
217 2
        if(!$this->client->success(true)) {
218 1
            return false;
219
        }
220
221 1
        return $response;
222
    }
223
224
    /**
225
     * Update a remote user
226
     *
227
     * @param int $id Local user ID
228
     * @param string|null $name
229
     * @param string|null $email
230
     * @param string|null $password Raw password, in case if changed
231
     *
232
     * @return array|false
233
     */
234 2
    public function update(int $id, ?string $name, ?string $email, ?string $password)
235
    {
236 2
        if($this->disabled()) {
237
            return false;
238
        }
239
240 2
        $attributes = array_filter(compact('id', 'name', 'email', 'password'));
241
242 2
        $response = $this->client->request('update', compact('id', 'attributes'));
243
244 2
        if(!$this->client->success(true)) {
245 1
            return false;
246
        }
247
248 1
        return $response;
249
    }
250
251
    /**
252
     * Retrieve a remote user
253
     *
254
     * @return RemoteUser|null
255
     */
256
    public function retrieveByToken()
257
    {
258
        if($this->disabled()) {
259
            return null;
260
        }
261
262
        $response = $this->client->request('me');
263
264
        if(!$this->client->success(true)) {
265
            return null;
266
        }
267
268
        return RemoteUser::createFromResponse($response);
269
    }
270
271
    /**
272
     * Load handlers from the given container.
273
     *
274
     * @param $container
275
     *
276
     * @return void
277
     */
278 17
    public function loadHandlers($container)
279
    {
280 17
        $this->handlersContainer = $container;
281 17
    }
282
283
    /**
284
     * Run a handler
285
     *
286
     * @param string $key
287
     * @param array $parameters
288
     * @param \Closure|null $fallback
289
     *
290
     * @return mixed
291
     *
292
     * @throws \Exception
293
     */
294 7
    public function handle(string $key, array $parameters = [], \Closure $fallback = null)
295
    {
296 7
        $handler = camel_case(str_replace('.', ' ', $key));
297
298 7
        if(!method_exists($this->handlersContainer, $handler)) {
299 1
            throw new \InvalidArgumentException("Handler `{$handler}` cannot be found");
300
        }
301
302
        return $this->ensure(function() use ($handler, $parameters) {
303 6
            return call_user_func_array([$this->handlersContainer, $handler], $parameters);
304 6
        }, $fallback);
305
    }
306
307
    /**
308
     * Run a fallback handler
309
     *
310
     * @param string $key
311
     * @param array $parameters
312
     * @param \Closure|null $fallback
313
     *
314
     * @return mixed
315
     *
316
     * @throws \Exception
317
     */
318 2
    public function handleFallback(string $key, array $parameters = [], \Closure $fallback = null)
319
    {
320 2
        $key = 'fallback' . studly_case($key);
321 2
        $parameters = array_merge(['guard' => $this->fallbackGuard], $parameters);
322
323 2
        return $this->handle($key, $parameters, $fallback);
324
    }
325
326
    /**
327
     * Performs a callback logic within database transaction.
328
     *
329
     * @param \Closure $callback
330
     * @param \Closure|null $fallback The callback which should fired when exception throws.
331
     *
332
     * @return mixed
333
     *
334
     * @throws \Exception
335
     */
336 6
    protected function ensure(\Closure $callback, \Closure $fallback = null)
337
    {
338 6
        DB::beginTransaction();
339
340
        try {
341 6
            $output = $callback();
342
        }
343 3
        catch(\Exception $e) {
344 2
            DB::rollBack();
345
346 2
            if(is_null($fallback)) {
347
                throw $e;
348
            }
349
350 2
            $output = $fallback($e);
351
        }
352
353 5
        DB::commit();
354
355 5
        return $output;
356
    }
357
358
    /**
359
     * Set authentication guard.
360
     *
361
     * @param \Slides\Connector\Auth\TokenGuard $guard
362
     */
363 17
    public function setGuard(TokenGuard $guard): void
364
    {
365 17
        $this->guard = $guard;
366 17
    }
367
368
    /**
369
     * Set fallback authentication guard.
370
     *
371
     * @param GuardContract $guard
372
     */
373
    public function setFallbackGuard(GuardContract $guard): void
374
    {
375
        $this->fallbackGuard = $guard;
376
    }
377
378
    /**
379
     * Set HTTP Client.
380
     *
381
     * @param Client $client
382
     */
383
    public function setClient(Client $client): void
384
    {
385
        $this->client = $client;
386
    }
387
388
    /**
389
     * Get HTTP client.
390
     *
391
     * @return Client
392
     */
393 17
    public function getClient(): Client
394
    {
395 17
        return $this->client;
396
    }
397
}