Completed
Push — master ( e89277...1caf4d )
by Patrick
03:08
created

class.AuthProvider.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * AuthProvider class
4
 *
5
 * This file describes the AuthProvider Singleton
6
 *
7
 * PHP version 5 and 7
8
 *
9
 * @author Patrick Boyd / [email protected]
10
 * @copyright Copyright (c) 2015, Austin Artistic Reconstruction
11
 * @license http://www.apache.org/licenses/ Apache 2.0 License
12
 */
13
14
/**
15
 * Allow other classes to be loaded as needed
16
 */
17
require_once('Autoload.php');
18
/**
19
 * Require the FlipsideSettings file
20
 */
21
require_once '/var/www/secure_settings/class.FlipsideSettings.php';
22
23
/**
24
 * A Singleton class to abstract access to the authentication providers.
25
 *
26
 * This class is the primary method to access user data, login, and other authenication information.
27
 */
28
class AuthProvider extends Singleton
29
{
30
    /** The authentication methods loaded by the provider */
31
    protected $methods;
32
33
    /**
34
     * Load the authentrication providers specified in the FlipsideSettings::$authProviders array
35
     */
36 View Code Duplication
    protected function __construct()
37
    {
38
        $this->methods = array();
39
        if(isset(FlipsideSettings::$authProviders))
40
        {
41
            $keys = array_keys(FlipsideSettings::$authProviders);
42
            $count = count($keys);
43
            for($i = 0; $i < $count; $i++)
44
            {
45
                $class = $keys[$i];
46
                array_push($this->methods, new $class(FlipsideSettings::$authProviders[$keys[$i]]));
47
            }
48
        }
49
    }
50
51
    /**
52
     * Get the Authenticator class instance by name
53
     *
54
     * @param string $methodName The class name of the Authenticator to get the instance for
55
     *
56
     * @return Auth\Authenticator|false The specified Authenticator class instance or false if it is not loaded
57
     */
58 View Code Duplication
    public function getAuthenticator($methodName)
59
    {
60
        $count = count($this->methods);
61
        for($i = 0; $i < $count; $i++)
62
        {
63
            if(strcasecmp(get_class($this->methods[$i]), $methodName) === 0)
64
            {
65
                return $this->methods[$i];
66
            }
67
        }
68
        return false;
69
    }
70
71
    /**
72
     * Get the Auth\User class instance for the specified login
73
     *
74
     * Unlike the AuthProvider::login() function. This function will not impact the SESSION
75
     *
76
     * @param string $username The username of the User
77
     * @param string $password The password of the User
78
     *
79
     * @return Auth\User|false The User with the specified credentials or false if the credentials are not valid
80
     */
81
    public function getUserByLogin($username, $password)
82
    {
83
        $res = false;
84
        $count = count($this->methods);
85
        for($i = 0; $i < $count; $i++)
86
        {
87
            $res = $this->methods[$i]->login($username, $password);
88
            if($res !== false)
89
            {
90
                return $this->methods[$i]->getUser($res);
91
            }
92
        }
93
        return $res;
94
    }
95
96
    /**
97
     * Use the provided credetials to log the user on
98
     *
99
     * @param string $username The username of the User
100
     * @param string $password The password of the User
101
     *
102
     * @return true|false true if the login was successful, false otherwise
103
     */
104
    public function login($username, $password)
105
    {
106
        $res = false;
107
        $count = count($this->methods);
108
        for($i = 0; $i < $count; $i++)
109
        {
110
            $res = $this->methods[$i]->login($username, $password);
111
            if($res !== false)
112
            {
113
                FlipSession::setVar('AuthMethod', get_class($this->methods[$i]));
114
                FlipSession::setVar('AuthData', $res);
115
                break;
116
            }
117
        }
118
        return $res;
119
    }
120
121
    /**
122
     * Determine if the user is still logged on from the session data
123
     *
124
     * @param stdClass $data The AuthData from the session
125
     * @param string $methodName The AuthMethod from the session
126
     *
127
     * @return true|false true if user is logged on, false otherwise
128
     */
129
    public function isLoggedIn($data, $methodName)
130
    {
131
        $auth = $this->getAuthenticator($methodName);
132
        return $auth->isLoggedIn($data);
133
    }
134
135
    /**
136
     * Obtain the currently logged in user from the session data
137
     *
138
     * @param stdClass $data The AuthData from the session
139
     * @param string $methodName The AuthMethod from the session
140
     *
141
     * @return Auth\User|false The User instance if user is logged on, false otherwise
142
     */
143
    public function getUser($data, $methodName)
144
    {
145
        $auth = $this->getAuthenticator($methodName);
146
        return $auth->getUser($data);
147
    }
148
149
    /**
150
     * Merge or set the returnValue as appropriate
151
     *
152
     * @param false|Auth\Group|Auth\User $returnValue The value to merge to
153
     * @param Auth\Group|Auth\User $res The value to merge from
154
     *
155
     * @return Auth\Group|false The merged returnValue
156
     */
157
    private function mergeResult(&$returnValue, $res)
158
    {
159
        if($res === false)
160
        {
161
            return;
162
        }
163
        if($returnValue === false)
164
        {
165
            $returnValue = $res;
166
            return;
167
        }
168
        $returnValue->merge($res);
169
    }
170
171
    /**
172
     * Calls the indicated function on each Authenticator and merges the result
173
     *
174
     * @param string $functionName The function to call
175
     * @param array $args The arguments for the function
176
     * @param string $checkField A field to check if it is set a certain way before calling the function
177
     * @param mixed $checkValue The value that field should be set to to not call the function
178
     *
179
     * @return Auth\Group|Auth\User|false The merged returnValue
180
     */
181 View Code Duplication
    private function callOnEach($functionName, $args, $checkField = false, $checkValue = false)
182
    {
183
        $ret = false;
184
        $count = count($this->methods);
185
        for($i = 0; $i < $count; $i++)
186
        {
187
            if($checkField)
188
            {
189
                if($this->methods[$i]->{$checkField} === $checkValue)
190
                {
191
                    continue;
192
                }
193
            }
194
            $res = call_user_func_array(array($this->methods[$i], $functionName), $args);
195
            $this->mergeResult($ret, $res);
196
        }
197
        return $ret;
198
    }
199
200
    /**
201
     * Calls the indicated function on each Authenticator and add the result
202
     *
203
     * @param string $functionName The function to call
204
     * @param string $checkField A field to check if it is set a certain way before calling the function
205
     * @param mixed $checkValue The value that field should be set to to not call the function
206
     *
207
     * @return integer|false The added returnValue
208
     */
209 View Code Duplication
    private function addFromEach($functionName, $checkField = false, $checkValue = false)
210
    {
211
        $retCount = 0;
212
        $count = count($this->methods);
213
        for($i = 0; $i < $count; $i++)
214
        {
215
            if($checkField)
216
            {
217
                if($this->methods[$i]->{$checkField} === $checkValue)
218
                {
219
                    continue;
220
                }
221
            }
222
            $res = call_user_func(array($this->methods[$i], $functionName));
223
            $retCount += $res;
224
        }
225
        return $retCount;
226
    }
227
228
    /**
229
     * Get an Auth\Group by its name
230
     *
231
     * @param string $name The name of the group
232
     * @param string $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
233
     *
234
     * @return Auth\Group|false The Group instance if a group with that name exists, false otherwise
235
     */
236
    public function getGroupByName($name, $methodName = false)
237
    {
238
        if($methodName === false)
239
        {
240
            return $this->callOnEach('getGroupByName', array($name));
241
        }
242
        $auth = $this->getAuthenticator($methodName);
243
        return $auth->getGroupByName($name);
244
    }
245
246
    /**
247
     * Get an array of Auth\User from a filtered set
248
     *
249
     * @param Data\Filter|false $filter The filter conditions or false to retreive all
250
     * @param array|false $methodName The user fields to obtain or false to obtain all
251
     * @param integer|false $top The number of users to obtain or false to obtain all
252
     * @param integer|false $skip The number of users to skip or false to skip none
253
     * @param array|false $orderby The field to sort by and the method to sort or false to not sort
254
     * @param string|false $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
255
     *
256
     * @return array|false An array of Auth\User objects or false if no users were found
257
     */
258 View Code Duplication
    public function getUsersByFilter($filter, $select=false, $top=false, $skip=false, $orderby=false, $methodName = false)
259
    {
260
        if($methodName === false)
261
        {
262
            return $this->callOnEach('getUsersByFilter', array($filter, $select, $top, $skip, $orderby), 'current');
263
        }
264
        $auth = $this->getAuthenticator($methodName);
265
        return $auth->getUsersByFilter($filter, $select, $top, $skip, $orderby);
266
    }
267
268
    /**
269
     * Get an array of Auth\PendingUser from a filtered set
270
     *
271
     * @param Data\Filter|false $filter The filter conditions or false to retreive all
272
     * @param array|false $methodName The user fields to obtain or false to obtain all
273
     * @param integer|false $top The number of users to obtain or false to obtain all
274
     * @param integer|false $skip The number of users to skip or false to skip none
275
     * @param array|false $orderby The field to sort by and the method to sort or false to not sort
276
     * @param string|false $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
277
     *
278
     * @return array|false An array of Auth\PendingUser objects or false if no pending users were found
279
     */
280 View Code Duplication
    public function getPendingUsersByFilter($filter, $select=false, $top=false, $skip=false, $orderby=false, $methodName = false)
281
    {
282
        if($methodName === false)
283
        {
284
            return $this->callOnEach('getPendingUsersByFilter', array($filter, $select, $top, $skip, $orderby), 'pending');
285
        }
286
        $auth = $this->getAuthenticator($methodName);
287
        return $auth->getPendingUsersByFilter($filter, $select, $top, $skip, $orderby);
288
    }
289
290
    /**
291
     * Get an array of Auth\Group from a filtered set
292
     *
293
     * @param Data\Filter|false $filter The filter conditions or false to retreive all
294
     * @param array|false $methodName The group fields to obtain or false to obtain all
295
     * @param integer|false $top The number of groups to obtain or false to obtain all
296
     * @param integer|false $skip The number of groups to skip or false to skip none
297
     * @param array|false $orderby The field to sort by and the method to sort or false to not sort
298
     * @param string|false $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
299
     *
300
     * @return array|false An array of Auth\Group objects or false if no pending users were found
301
     */
302 View Code Duplication
    public function getGroupsByFilter($filter, $select=false, $top=false, $skip=false, $orderby=false, $methodName = false)
303
    {
304
        if($methodName === false)
305
        {
306
            return $this->callOnEach('getGroupsByFilter', array($filter, $select, $top, $skip, $orderby), 'current');
307
        }
308
        $auth = $this->getAuthenticator($methodName);
309
        return $auth->getGroupsByFilter($filter, $select, $top, $skip, $orderby);
310
    }
311
312
    /**
313
     * Get the number of currently active users on the system
314
     *
315
     * @param string|false $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
316
     *
317
     * @return integer The number of currently active users on the system
318
     */
319
    public function getActiveUserCount($methodName = false)
320
    {
321
        if($methodName === false)
322
        {
323
            return $this->addFromEach('getActiveUserCount', 'current');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->addFromEach('getA...UserCount', 'current'); of type integer|false adds false to the return on line 323 which is incompatible with the return type documented by AuthProvider::getActiveUserCount of type integer. It seems like you forgot to handle an error condition.
Loading history...
324
        }
325
        $auth = $this->getAuthenticator($methodName);
326
        return $auth->getActiveUserCount();
327
    }
328
329
    /**
330
     * Get the number of currently pending users on the system
331
     *
332
     * @param string|false $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
333
     *
334
     * @return integer The number of currently pending users on the system
335
     */
336
    public function getPendingUserCount($methodName = false)
337
    {
338
        if($methodName === false)
339
        {
340
            return $this->addFromEach('getPendingUserCount', 'pending');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->addFromEach('getP...UserCount', 'pending'); of type integer|false adds false to the return on line 340 which is incompatible with the return type documented by AuthProvider::getPendingUserCount of type integer. It seems like you forgot to handle an error condition.
Loading history...
341
        }
342
        $auth = $this->getAuthenticator($methodName);
343
        return $auth->getPendingUserCount();
344
    }
345
346
    /**
347
     * Get the number of current groups on the system
348
     *
349
     * @param string|false $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
350
     *
351
     * @return integer The number of current groups on the system
352
     */
353
    public function getGroupCount($methodName = false)
354
    {
355
        if($methodName === false)
356
        {
357
            return $this->addFromEach('getGroupCount', 'current');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->addFromEach('getGroupCount', 'current'); of type integer|false adds false to the return on line 357 which is incompatible with the return type documented by AuthProvider::getGroupCount of type integer. It seems like you forgot to handle an error condition.
Loading history...
358
        }
359
        $auth = $this->getAuthenticator($methodName);
360
        return $auth->getGroupCount();
361
    }
362
363
    /**
364
     * Get the login links for all supplementary Authenitcation mechanisms
365
     *
366
     * This will return an array of links to any supplementary authentication mechanims. For example, Goodle is 
367
     * a supplementary authentication mechanism.
368
     *
369
     * @return array An array of suppmentary authentication mechanism links
370
     */
371
    public function getSupplementaryLinks()
372
    {
373
        $ret = array();
374
        $count = count($this->methods);
375 View Code Duplication
        for($i = 0; $i < $count; $i++)
376
        {
377
            if($this->methods[$i]->supplement === false) continue;
378
379
            array_push($ret, $this->methods[$i]->getSupplementLink());
380
        }
381
        return $ret;
382
    }
383
384
    /**
385
     * Impersonate the user specified
386
     *
387
     * This will replace the user in the session with the specified user. In order
388
     * to undo this operation a user must logout.
389
     *
390
     * @param array|Auth\User $userArray Data representing the user
391
     */
392
    public function impersonateUser($userArray)
393
    {
394
        if(!is_object($userArray))
395
        {
396
            $user = new $userArray['class']($userArray);
397
        }
398
        \FlipSession::setUser($user);
399
    }
400
401
    /**
402
     * Get the pending user reresented by the supplied hash
403
     *
404
     * @param string $hash The hash value representing the Penging User
405
     * @param string|false $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
406
     *
407
     * @return Auth\PendingUser|false The Auth\PendingUser instance or false if no user is matched by the provided hash
408
     */
409
    public function getTempUserByHash($hash, $methodName = false)
410
    {
411
        if($methodName === false)
412
        {
413
            $count = count($this->methods);
414
            for($i = 0; $i < $count; $i++)
415
            {
416
                if($this->methods[$i]->pending === false) continue;
417
418
                $ret = $this->methods[$i]->getTempUserByHash($hash);
419
                if($ret !== false)
420
                {
421
                    return $ret;
422
                }
423
            }
424
            return false;
425
        }
426
        $auth = $this->getAuthenticator($methodName);
427
        return $auth->getTempUserByHash($hash);
428
    }
429
430
    /**
431
     * Create a pending user
432
     *
433
     * @param array $user An array of information about the user to create
434
     * @param string|false $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
435
     *
436
     * @return true|false true if the user was successfully created. Otherwise false.
437
     */
438
    public function createPendingUser($user, $methodName = false)
439
    {
440
        if($methodName === false)
441
        {
442
            $count = count($this->methods);
443
            for($i = 0; $i < $count; $i++)
444
            {
445
                if($this->methods[$i]->pending === false) continue;
446
447
                $ret = $this->methods[$i]->createPendingUser($user);
448
                if($ret !== false)
449
                {
450
                    return true;
451
                }
452
            }
453
            return false;
454
        }
455
        $auth = $this->getAuthenticator($methodName);
456
        return $auth->createPendingUser($user);
457
    }
458
459
    /**
460
     * Convert a Auth\PendingUser into an Auth\User
461
     *
462
     * This will allow a previously pending user the ability to log on in the future as an active user. It will also
463
     * have the side effect of logging the user on now.
464
     *
465
     * @param Auth\PendingUser $user The user to turn into a current user
466
     * @param string|false $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
467
     *
468
     * @return true|false true if the user was successfully created. Otherwise false.
469
     */
470 View Code Duplication
    public function activatePendingUser($user, $methodName = false)
471
    {
472
        if($methodName === false)
473
        {
474
            $count = count($this->methods);
475
            for($i = 0; $i < $count; $i++)
476
            {
477
                if($this->methods[$i]->current === false) continue;
478
479
                $ret = $this->methods[$i]->activatePendingUser($user);
480
                if($ret !== false)
481
                {
482
                    $this->impersonateUser($ret);
483
                    return true;
484
                }
485
            }
486
            return false;
487
        }
488
        $auth = $this->getAuthenticator($methodName);
489
        return $auth->activatePendingUser($user);
490
    }
491
492
    /**
493
     * Get a current user by a password reset hash
494
     *
495
     * @param string $hash The current password reset hash for the user
496
     * @param string|false $methodName The AuthMethod if information is desired only from a particular Auth\Authenticator
497
     *
498
     * @return Auth\User|false The user if the password reset hash is valid. Otherwise false.
499
     */
500 View Code Duplication
    public function getUserByResetHash($hash, $methodName = false)
501
    {
502
        if($methodName === false)
503
        {
504
            $count = count($this->methods);
505
            for($i = 0; $i < $count; $i++)
506
            {
507
                if($this->methods[$i]->current === false) continue;
508
509
                $ret = $this->methods[$i]->getUserByResetHash($hash);
510
                if($ret !== false)
511
                {
512
                    return $ret;
513
                }
514
            }
515
            return false;
516
        }
517
        $auth = $this->getAuthenticator($methodName);
518
        if($auth === false)
519
        {
520
            return $this->getUserByResetHash($hash, false);
521
        }
522
        return $auth->getUserByResetHash($hash);
523
    }
524
525
    /**
526
     * Get the Auth\Authenticator by host name
527
     *
528
     * @param string $host The host name used by the supplemental authentication mechanism
529
     *
530
     * @return Auth\Authenticator|false The Authenticator if the host is supported by a loaded Authenticator. Otherwise false.
531
     */
532
    public function getSuplementalProviderByHost($host)
533
    {
534
        $count = count($this->methods);
535 View Code Duplication
        for($i = 0; $i < $count; $i++)
536
        {
537
            if($this->methods[$i]->supplement === false) continue;
538
539
            if($this->methods[$i]->getHostName() === $host)
540
            {
541
                return $this->methods[$i];
542
            }
543
        }
544
        return false;
545
    }
546
547
    public function deletePendingUsersByFilter($filter, $methodName=false)
548
    {
549
        $users = $this->getPendingUsersByFilter($filter, false, false, false, false, $methodName);
550
        if($users === false)
551
        {
552
            return false;
553
        }
554
        $count = count($users);
555
        for($i = 0; $i < $count; $i++)
556
        {
557
            $users[$i]->delete();
558
        }
559
        return true;
560
    }
561
}
562
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
563
?>
564