Completed
Push — master ( 26ea5b...d16af1 )
by Patrick
01:54
created

UsersAPI::getFailArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
require_once('class.UIDForgotEmail.php');
3
4
class UsersAPI extends Http\Rest\RestAPI
5
{
6
    public function setup($app)
7
    {
8
        $app->get('[/]', array($this, 'listUsers'));
9
        $app->post('[/]', array($this, 'createUser'));
10
        $app->get('/{uid}[/]', array($this, 'showUser'));
11
        $app->patch('/{uid}[/]', array($this, 'editUser'));
12
        $app->delete('/{uid}[/]', array($this, 'deleteUser'));
13
        $app->get('/{uid}/groups[/]', array($this, 'listGroupsForUser'));
14
        $app->post('/{uid}/Actions/link[/]', array($this, 'linkUser'));
15
        $app->post('/{uid}/Actions/reset_pass[/]', array($this, 'resetUserPassword'));
16
        $app->post('/Actions/check_email_available[/]', array($this, 'checkEmailAvailable'));
17
        $app->post('/Actions/check_uid_available[/]', array($this, 'checkUidAvailable'));
18
        $app->post('/Actions/remind_uid[/]', array($this, 'remindUid'));
19
    }
20
21
    public function listUsers($request, $response)
22
    {
23
        $odata = $request->getAttribute('odata', new \ODataParams(array()));
24
        if($this->validateIsAdmin($request, true) === false)
0 ignored issues
show
Bug introduced by
The method validateIsAdmin() does not seem to exist on object<UsersAPI>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
25
        {
26
            $users = array($this->user);
0 ignored issues
show
Bug introduced by
The property user does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
27
            $users = $odata->filterArrayPerSelect($users);
28
        }
29
        else
30
        {
31
            $auth = AuthProvider::getInstance();
32
            $users = $auth->getUsersByFilter($odata->filter, $odata->select, $odata->top, $odata->skip, 
33
                                             $odata->orderby);
34
        }
35
        return $response->withJson($users);
36
    }
37
38
    protected function validateCanCreateUser($proposedUser, $auth, &$message)
39
    {
40
        $user = $auth->getUsersByFilter(new \Data\Filter('mail eq '.$proposedUser['mail']));
41 View Code Duplication
        if($user !== false && isset($user[0]))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
42
        {
43
            $message = 'Email already exists!';
44
            return false;
45
        }
46
        $user = $auth->getUsersByFilter(new \Data\Filter('uid eq '.$proposedUser['uid']));
47 View Code Duplication
        if($user !== false && isset($user[0]))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
48
        {
49
            $message = 'Username already exists!';
50
            return false;
51
        }
52
        return true;
53
    }
54
55
    protected function validEmail($email)
56
    {
57
        if(filter_var($email) === false)
58
        {
59
            return false;
60
        }
61
        $pos = strpos($email, '@');
62
        if($pos === false)
63
        {
64
            return false;
65
        }
66
        $domain = substr($email, $pos + 1);
67
        if(checkdnsrr($domain, 'MX') === false)
68
        {
69
            return false;
70
        }
71
        return true;
72
    }
73
74
    protected function getFailArray($message)
75
    {
76
        return array('res'=>false, 'message'=>$message);
77
    }
78
79
    public function createUser($request, $response)
80
    {
81
        $this->user = $request->getAttribute('user');
82
        //This one is different. If they are logged in fail...
83
        if($this->user !== false)
84
        {
85
            return $response->withStatus(404);
86
        }
87
        $obj = $request->getParsedBody();
88
        if(!isset($obj['captcha']))
89
        {
90
            return $response->withStatus(401);
91
        }
92
        $captcha = FlipSession::getVar('captcha');
93
        if($captcha === false)
94
        {
95
            return $response->withStatus(401);
96
        }
97
        if(!$captcha->is_answer_right($obj['captcha']))
98
        {
99
            return $response->withJson($this->getFailArray('Incorrect answer to CAPTCHA!'), 412);
100
        }
101
        $auth = AuthProvider::getInstance();
102
        $message = false;
103
        if($this->validateCanCreateUser($obj, $auth, $message) === false)
104
        {
105
            return $response->withJson($this->getFailArray($message), 412);
106
        }
107
        else if($this->validEmail($obj['mail']) === false)
108
        {
109
            return $response->withJson($this->getFailArray('Invalid Email Address!'));
110
        }
111
        $ret = $auth->createPendingUser($obj);
112
        if($ret == false)
113
        {
114
            return $response->withJson($this->getFailArray('Failed to save user registration!'), 500);
115
        }
116
        return $response->withJson($ret);
117
    }
118
119
    protected function userIsMe($request, $uid)
120
    {
121
        $this->user = $request->getAttribute('user');
122
        return ($uid === 'me' || ($this->user !== false && $uid === $this->user->uid));
123
    }
124
125
    protected function hasLeadAccess()
126
    {
127
        return ($this->user->isInGroupNamed('Leads') || $this->user->isInGroupNamed('CC') || $this->user->isInGroupNamed('AFs'));
128
    }
129
130 View Code Duplication
    protected function getUserByUIDReadOnly($request, $uid)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
131
    {
132
        if($this->userIsMe($request, $uid))
133
        {
134
            return $this->user;
135
        }
136
        if($this->user->isInGroupNamed('LDAPAdmins') || $this->hasLeadAccess())
137
        {
138
            $auth = \AuthProvider::getInstance();
139
            $filter = new \Data\Filter("uid eq $uid");
140
            $users = $auth->getUsersByFilter($filter);
141
            if(!empty($users))
142
            {
143
                return $users[0];
144
            }
145
        }
146
        return false;
147
    }
148
149 View Code Duplication
    protected function getUserByUID($request, $uid)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
150
    {
151
        if($this->userIsMe($request, $uid))
152
        {
153
            return $this->user;
154
        }
155
        if($this->user->isInGroupNamed('LDAPAdmins'))
156
        {
157
            $auth = \AuthProvider::getInstance();
158
            $filter = new \Data\Filter("uid eq $uid");
159
            $users = $auth->getUsersByFilter($filter);
160
            if(!empty($users))
161
            {
162
                return $users[0];
163
            }
164
        }
165
        return false;
166
    }
167
168
    public function showUser($request, $response, $args)
169
    {
170
        $uid = $args['uid'];
171
        $user = $request->getAttribute('user');
172
        if($user === false)
173
        {
174
            if($_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR'])
175
            {
176
                $user = \AuthProvider::getInstance()->getUsersByFilter(new \Data\Filter("uid eq $uid"));
177
                if(empty($user))
178
                {
179
                    return $response->withStatus(404);
180
                }
181
                return $response->withJson($user[0]);
182
            } 
183
            return $response->withStatus(401);
184
        }
185
        $user = $this->getUserByUIDReadOnly($request, $uid);
186
        if($user === false)
187
        {
188
            return $response->withStatus(404);
189
        }
190
        if(!is_object($user) && isset($user[0]))
191
        {
192
            $user = $user[0];
193
        }
194
        if($request->getAttribute('format') === 'vcard')
195
        {
196
            $response = $response->withHeader('Content-Type', 'text/x-vCard');
197
            $response->getBody()->write($user->getVcard());
198
            return $response;
199
        }
200
        return $response->withJson($user);
201
    }
202
203
    protected function sendPasswordResetEmail($user)
204
    {
205
        $forwardedFor = false;
206
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
207
        {
208
            $forwardedFor = $_SERVER['HTTP_X_FORWARDED_FOR'];
209
        }
210
        $emailMsg = new PasswordHasBeenResetEmail($user, $_SERVER['REMOTE_ADDR'], $forwardedFor);
211
        $emailProvider = EmailProvider::getInstance();
212
        if($emailProvider->sendEmail($emailMsg) === false)
213
        {
214
            throw new \Exception('Unable to send password reset email!');
215
        }
216
    }
217
218
    protected function exceptionCodeToHttpCode($e)
219
    {
220
        if($e->getCode() === 3)
221
        {
222
            return 401;
223
        }
224
        return 500;
225
    }
226
227
    protected function getUser($request, $uid, $payload)
228
    {
229
        $this->user = $request->getAttribute('user');
230
        if($this->user === false)
231
        {
232
            if(isset($payload->hash))
233
            {
234
                $auth = AuthProvider::getInstance();
235
                $this->user = $auth->getUserByResetHash($payload->hash);
236
                return $this->user;
237
            }
238
            return false;
239
        }
240
        return $this->getUserByUID($request, $uid);
241
    }
242
243
    public function editUser($request, $response, $args)
244
    {
245
        $uid = 'me';
246
        if(isset($args['uid']))
247
        {
248
            $uid = $args['uid'];
249
        }
250
        $obj = $request->getParsedBody();
251
        $user = $this->getUser($request, $uid, $obj);
252
        if($user === false)
253
        {
254
            return $response->withStatus(404);
255
        }
256
        try
257
        {
258
            if(isset($obj['old_uid']))
259
            {
260
                unset($obj['old_uid']);
261
            }
262
            unset($obj['uid']);
263
            $user->editUser($obj);
264
        }
265
        catch(\Exception $e)
266
        {
267
            return $response->withJson(array('error'=>array('msg'=>$e->getMessage(), 'stack'=>$e->getTraceAsString())), $this->exceptionCodeToHttpCode($e));
268
        }
269
        if($this->userIsMe($request, $uid))
270
        {
271
            \FlipSession::setUser($user);
272
        }
273
        if(isset($obj->password))
274
        {
275
            $this->sendPasswordResetEmail($user);
276
        }
277
        return $response->withJson(array('success'=>true));
278
    }
279
280
    public function deleteUser($request, $response, $args)
281
    {
282
        $uid = 'me';
283
        if(isset($args['uid']))
284
        {
285
            $uid = $args['uid'];
286
        }
287
        $user = false;
0 ignored issues
show
Unused Code introduced by
$user is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
288
        if($this->validateIsAdmin($request, true) === false && $this->userIsMe($request, $uid))
0 ignored issues
show
Bug introduced by
The method validateIsAdmin() does not seem to exist on object<UsersAPI>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
289
        {
290
            $user = $this->user;
291
        }
292
        else
293
        {
294
            $auth = AuthProvider::getInstance();
295
            $filter = new \Data\Filter("uid eq $uid");
296
            $user = $auth->getUsersByFilter($filter);
297
            if(empty($user))
298
            {
299
                $user = false;
300
            }
301
            else
302
            {
303
                $user = $user[0];
304
            }
305
        }
306
        if($user === false)
307
        {
308
            return $response->withStatus(404);
309
        }
310
        return $response->withJson($user->delete());
311
    }
312
313
    public function listGroupsForUser($request, $response, $args)
314
    {
315
        $uid = 'me';
316
        if(isset($args['uid']))
317
        {
318
            $uid = $args['uid'];
319
        }
320
        $this->validateLoggedIn($request);
321
        $user = $this->getUserByUID($request, $uid);
322
        if($user === false)
323
        {
324
            return $response->withStatus(404);
325
        }
326
        $groups = $user->getGroups();
327
        if($groups === false)
328
        {
329
            $groups = array();
330
        }
331
        return $response->withJson($groups);
332
    }
333
334
    public function linkUser($request, $response, $args)
335
    {
336
        $uid = 'me';
337
        if(isset($args['uid']))
338
        {
339
            $uid = $args['uid'];
340
        }
341
        $this->validateLoggedIn($request);
342
        $obj = $request->getParsedBody();
343
        if($this->userIsMe($request, $uid))
344
        {
345
            $this->user->addLoginProvider($obj->provider);
346
            AuthProvider::getInstance()->impersonateUser($this->user);
347
        }
348
        else if($this->user->isInGroupNamed("LDAPAdmins"))
349
        {
350
            $user = AuthProvider::getInstance()->getUser($uid);
351
            if($user === false)
352
            {
353
                return $response->withStatus(404);
354
            }
355
            $user->addLoginProvider($obj->provider);
356
        }
357
        else
358
        {
359
            return $response->withStatus(404);
360
        }
361
        return $response->withJson(array('success'=>true));
362
    }
363
364
    protected function getAllUsersByFilter($filter, &$pending)
365
    {
366
        $auth = AuthProvider::getInstance();
367
        $user = $auth->getUsersByFilter($filter);
368
        if(!empty($user))
369
        {
370
            $pending = false;
371
            return $user[0];
372
        }
373
        $user = $auth->getPendingUsersByFilter($filter);
374
        if(!empty($user))
375
        {
376
            $pending = true;
377
            return $user[0];
378
        }
379
        return false;
380
    }
381
382
    public function checkEmailAvailable($request, $response)
383
    {
384
        $params = $request->getQueryParams();
385
        $email = false;
386
        if(isset($params['email']))
387
        {
388
            $email = $params['email'];
389
        }
390 View Code Duplication
        if($email === false)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
391
        {
392
            $params = $request->getParsedBody();
393
            if(isset($params['email']))
394
            {
395
                $email = $params['email'];
396
            }
397
            if($email === false)
398
            {
399
                return $response->withStatus(400);
400
            }
401
        }
402
        if(filter_var($email, FILTER_VALIDATE_EMAIL) === false || strpos($email, '@') === false)
403
        {
404
            return $response->withJson(false);
405
        }
406
        if(strstr($email, '+') !== false)
407
        {
408
            //Remove everything between the + and the @
409
            $begining = strpos($email, '+');
410
            $end = strpos($email, '@');
411
            $to_delete = substr($email, $begining, $end - $begining);
412
            $email = str_replace($to_delete, '', $email);
413
        }
414
        $filter = new \Data\Filter('mail eq '.$email);
415
        $pending = false;
416
        $user = $this->getAllUsersByFilter($filter, $pending);
417
        if($user === false)
418
        {
419
            return $response->withJson(true);
420
        }
421
        return $response->withJson(array('res'=>false, 'email'=>$user->mail, 'pending'=>$pending));
422
    }
423
424
    public function checkUidAvailable($request, $response)
425
    {
426
        $params = $request->getQueryParams();
427
        $uid = false;
428
        if(isset($params['uid']))
429
        {
430
            $uid = $params['uid'];
431
        }
432 View Code Duplication
        if($uid === false)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
433
        {
434
            $params = $request->getParsedBody();
435
            if(isset($params['uid']))
436
            {
437
                $uid = $params['uid'];
438
            }
439
            if($uid === false)
440
            {
441
                return $response->withStatus(400);
442
            }
443
        }
444
        if(strpos($uid, '=') !== false || strpos($uid, ',') !== false)
445
        {
446
            return $response->withJson(false);
447
        }
448
        $filter = new \Data\Filter('uid eq '.$uid);
449
        $pending = false;
450
        $user = $this->getAllUsersByFilter($filter, $pending);
451
        if($user === false)
452
        {
453
            return $response->withJson(true);
454
        }
455
        return $response->withJson(array('res'=>false, 'uidl'=>$user->uid, 'pending'=>$pending));
456
    }
457
458
    public function resetUserPassword($request, $response, $args)
459
    {
460
        $uid = false;
0 ignored issues
show
Unused Code introduced by
$uid is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
461
        if(isset($args['uid']))
462
        {
463
            $uid = $args['uid'];
464
        }
465
        else
466
        {
467
            return $response->withStatus(400);
468
        }
469
        $auth = AuthProvider::getInstance();
470
        $users = $auth->getUsersByFilter(new \Data\Filter('uid eq '.$uid));
471
        if(empty($users))
472
        {
473
            return $response->withStatus(404);
474
        }
475
        $email_msg = new PasswordResetEmail($users[0]);
476
        $email_provider = EmailProvider::getInstance();
477
        if($email_provider->sendEmail($email_msg) === false)
478
        {
479
            throw new \Exception('Unable to send email!');
480
        }
481
        return $response->withJson(true);
482
    }
483
484
    public function remindUid($request, $response, $args)
0 ignored issues
show
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
485
    {
486
        $params = $request->getQueryParams();
487
        $email = false;
488
        if(isset($params['email']))
489
        {
490
            $email = $params['email'];
491
        }
492 View Code Duplication
        if($email === false)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
493
        {
494
            $params = $request->getParsedBody();
495
            if(isset($params['email']))
496
            {
497
                $email = $params['email'];
498
            }
499
            if($email === false)
500
            {
501
                return $response->withStatus(400);
502
            }
503
        }
504
        if(filter_var($email, FILTER_VALIDATE_EMAIL) === false)
505
        {
506
            return $response->withStatus(400);
507
        }
508
        $auth = AuthProvider::getInstance();
509
        $users = $auth->getUsersByFilter(new \Data\Filter('mail eq '.$email));
510
        if(empty($users))
511
        {
512
            return $response->withStatus(404);
513
        }
514
        $email_msg = new UIDForgotEmail($users[0]);
515
        $email_provider = EmailProvider::getInstance();
516
        if($email_provider->sendEmail($email_msg) === false)
517
        {
518
            throw new \Exception('Unable to send email!');
519
        }
520
    }
521
}
522
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
523