Completed
Push — master ( 9fc508...c7bf07 )
by Artem
04:15
created

AuthService   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 362
Duplicated Lines 0 %

Test Coverage

Coverage 77.38%

Importance

Changes 0
Metric Value
eloc 74
dl 0
loc 362
rs 9.84
c 0
b 0
f 0
ccs 65
cts 84
cp 0.7738
wmc 32

18 Methods

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