Completed
Push — master ( bf23bc...4f23d4 )
by Patrick
06:42
created

UsersAPI::deleteUser()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 32
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 18
nc 12
nop 3
dl 0
loc 32
rs 8.439
c 0
b 0
f 0
1
<?php
2
class UsersAPI extends Http\Rest\RestAPI
3
{
4
    public function setup($app)
5
    {
6
        $app->get('[/]', array($this, 'listUsers'));
7
        $app->post('[/]', array($this, 'createUser'));
8
        $app->get('/{uid}[/]', array($this, 'showUser'));
9
        $app->patch('/{uid}[/]', array($this, 'editUser'));
10
        $app->delete('/{uid}[/]', array($this, 'deleteUser'));
11
        $app->get('/{uid}/groups[/]', array($this, 'listGroupsForUser'));
12
        $app->post('/{uid}/Actions/link[/]', array($this, 'linkUser'));
13
        $app->post('/{uid}/Actions/reset_pass[/]', array($this, 'resetUserPassword'));
14
        $app->post('/Actions/check_email_available[/]', array($this, 'checkEmailAvailable'));
15
        $app->post('/Actions/check_uid_available[/]', array($this, 'checkUidAvailable'));
16
        $app->post('/Actions/remind_uid[/]', array($this, 'remindUid'));
17
    }
18
19 View Code Duplication
    public function validateIsAdmin($request, $nonFatal = false)
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...
20
    {
21
        $this->user = $request->getAttribute('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...
22
        if($this->user === false)
23
        {
24
            throw new Exception('Must be logged in', \Http\Rest\ACCESS_DENIED);
25
        }
26
        if(!$this->user->isInGroupNamed('LDAPAdmins'))
27
        {
28
            if($nonFatal)
29
            {
30
                return false;
31
            }
32
            throw new Exception('Must be Admin', \Http\Rest\ACCESS_DENIED);
33
        }
34
        return true;
35
    }
36
37
    public function listUsers($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...
38
    {
39
        $users = false;
0 ignored issues
show
Unused Code introduced by
$users 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...
40
        $odata = $request->getAttribute('odata', new \ODataParams(array()));
41
        if($this->validateIsAdmin($request, true) === false)
42
        {
43
            $users = array($this->user);
44
            $users = $odata->filterArrayPerSelect($users);
45
        }
46
        else
47
        {
48
            $auth = AuthProvider::getInstance();
49
            $users = $auth->getUsersByFilter($odata->filter, $odata->select, $odata->top, $odata->skip, 
50
                                             $odata->orderby);
51
        }
52
        return $response->withJson($users);
53
    }
54
55
    protected function validateCanCreateUser($proposedUser, $auth, &$message)
56
    {
57
        $user = $auth->getUsersByFilter(new \Data\Filter('mail eq '.$proposedUser->mail));
58 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...
59
        {
60
            $message = 'Email already exists!';
61
            return false;
62
        }
63
        $user = $auth->getUsersByFilter(new \Data\Filter('uid eq '.$proposedUser->uid));
64 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...
65
        {
66
            $message = 'Username already exists!';
67
            return false;
68
        }
69
        return true;
70
    }
71
72 View Code Duplication
    protected function validEmail($email)
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...
73
    {
74
        if(filter_var($email) === false)
75
        {
76
            return false;
77
        }
78
        $pos = strpos($email, '@');
79
        if($pos === false)
80
        {
81
            return false;
82
        }
83
        $domain = substr($email, $pos+1);
84
        if(checkdnsrr($domain, 'MX') === false)
85
        {
86
            return false;
87
        }
88
        return true;
89
    }
90
91
    public function createUser($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...
92
    {
93
        $this->user = $request->getAttribute('user');
94
        //This one is different. If they are logged in fail...
95
        if($this->user !== false)
96
        {
97
            return $response->withStatus(404);
98
        }
99
        $obj = $request->getParsedBody();
100
        if(!isset($obj->captcha))
101
        {
102
            return $response->withStatus(401);
103
        }
104
        $captcha = FlipSession::getVar('captcha');
105
        if($captcha === false)
106
        {
107
            return $response->withStatus(401);
108
        }
109
        if(!$captcha->is_answer_right($obj->captcha))
110
        {
111
            return $response->withJson(array('res'=>false, 'message'=>'Incorrect answer to CAPTCHA!'), 412);
112
        }
113
        $auth = AuthProvider::getInstance();
114
        $message = false;
115
        if($this->validateCanCreateUser($obj, $auth, $message) === false)
116
        {
117
            return $response->withJson(array('res'=>false, 'message'=>$message), 412);
118
        }
119 View Code Duplication
        else if($this->validEmail($obj->mail) === 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...
120
        {
121
            return $response->withJson(array('res'=>false, 'message'=>'Invalid Email Address!'));
122
        }
123
        $ret = $auth->createPendingUser($obj);
124 View Code Duplication
        if($ret == 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...
125
        {
126
            return $response->withJson(array('res'=>false, 'message'=>'Failed to save user registration!'), 500);
127
        }
128
        return $response->withJson($ret);
129
    }
130
131
    protected function userIsMe($request, $uid)
132
    {
133
        $this->user = $request->getAttribute('user');
134
        return ($uid === 'me' || ($this->user !== false && $uid === $this->user->uid));
135
    }
136
137 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...
138
    {
139
        if($this->userIsMe($request, $uid))
140
        {
141
            return $this->user;
142
        }
143
        if($this->user->isInGroupNamed('LDAPAdmins') || $this->hasLeadAccess($request))
0 ignored issues
show
Bug introduced by
The method hasLeadAccess() 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...
144
        {
145
            $auth = \AuthProvider::getInstance();
146
            $filter = new \Data\Filter("uid eq $uid");
147
            $users = $auth->getUsersByFilter($filter);
148
            if($users !== false && isset($users[0]))
149
            {
150
                return $users[0];
151
            }
152
        }
153
        return false;
154
    }
155
156 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...
157
    {
158
        if($this->userIsMe($request, $uid))
159
        {
160
            return $this->user;
161
        }
162
        if($this->user->isInGroupNamed('LDAPAdmins'))
163
        {
164
            $auth = \AuthProvider::getInstance();
165
            $filter = new \Data\Filter("uid eq $uid");
166
            $users = $auth->getUsersByFilter($filter);
167
            if($users !== false && isset($users[0]))
168
            {
169
                return $users[0];
170
            }
171
        }
172
        return false;
173
    }
174
175
    public function showUser($request, $response, $args)
176
    {
177
        $uid = $args['uid'];
178
        $user = $request->getAttribute('user');
179
        if($user === false)
180
        {
181
            if($_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR'])
182
            {
183
                $user = \AuthProvider::getInstance()->getUsersByFilter(new \Data\Filter("uid eq $uid"));
184
                if($user === false || !isset($user[0]))
185
                {
186
                    return $response->withStatus(404);
187
                }
188
                return $response->withJson($user[0]);
189
            } 
190
            return $response->withStatus(401);
191
        }
192
        $user = $this->getUserByUIDReadOnly($request, $uid);
193
        if($user === false)
194
        {
195
            return $response->withStatus(404);
196
        }
197
        if(!is_object($user) && isset($user[0]))
198
        {
199
            $user = $user[0];
200
        }
201
        if($request->getAttribute('format') === 'vcard')
202
        {
203
            $response = $response->withHeader('Content-Type', 'text/x-vCard');
204
            $response->getBody()->write($user->getVcard());
205
            return $response;
206
        }
207
        return $response->withJson($user);
208
    }
209
210
    protected function sendPasswordResetEmail($user)
211
    {
212
        $forwardedFor = false;
213
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
214
        {
215
            $forwardedFor = $_SERVER['HTTP_X_FORWARDED_FOR'];
216
        }
217
        $emailMsg = new PasswordHasBeenResetEmail($user, $_SERVER['REMOTE_ADDR'], $forwardedFor);
218
        $emailProvider = EmailProvider::getInstance();
219
        if($emailProvider->sendEmail($emailMsg) === false)
220
        {
221
            throw new \Exception('Unable to send password reset email!');
222
        }
223
    }
224
225
    protected function exceptionCodeToHttpCode($e)
226
    {
227
        if($e->getCode() === 3)
228
        {
229
            return 401;
230
        }
231
        return 500;
232
    }
233
234
    protected function getUser($request, $uid, $payload)
235
    {
236
        $this->user = $request->getAttribute('user');
237
        if($this->user === false)
238
        {
239
            if(isset($payload->hash))
240
            {
241
                $auth = AuthProvider::getInstance();
242
                $this->user = $auth->getUserByResetHash($payload->hash);
243
                return $this->user;
244
            }
245
            return false;
246
        }
247
        return $this->getUserByUID($request, $uid);
248
    }
249
250
    public function editUser($request, $response, $args)
251
    {
252
        $uid = 'me';
253
        if(isset($args['uid']))
254
        {
255
            $uid = $args['uid'];
256
        }
257
        $obj = $request->getParsedBody();
258
        $user = $this->getUser($request, $uid, $obj);
259
        if($user === false)
260
        {
261
            return $response->withStatus(404);
262
        }
263
        try
264
        {
265
            if(isset($obj['old_uid']))
266
            {
267
                unset($obj['old_uid']);
268
            }
269
            unset($obj['uid']);
270
            $user->editUser($obj);
271
        }
272
        catch(\Exception $e)
273
        {
274
            return $response->withJson(array('error'=>array('msg'=>$e->getMessage(), 'stack'=>$e->getTraceAsString())), $this->exceptionCodeToHttpCode($e));
275
        }
276
        if($this->userIsMe($request, $uid))
277
        {
278
            \FlipSession::setUser($user);
279
        }
280
        if(isset($obj->password))
281
        {
282
            $this->sendPasswordResetEmail($user);
283
        }
284
        return $response->withJson(array('success'=>true));
285
    }
286
287
    public function deleteUser($request, $response, $args)
288
    {
289
        $uid = 'me';
290
        if(isset($args['uid']))
291
        {
292
            $uid = $args['uid'];
293
        }
294
        $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...
295
        if($this->validateIsAdmin($request, true) === false && $this->userIsMe($request, $uid))
296
        {
297
            $user = $this->user;
298
        }
299
        else
300
        {
301
            $auth = AuthProvider::getInstance();
302
            $filter = new \Data\Filter("uid eq $uid");
303
            $user = $auth->getUsersByFilter($filter);
304
            if(empty($user))
305
            {
306
                $user = false;
307
            }
308
            else
309
            {
310
                $user = $user[0];
311
            }
312
        }
313
        if($user === false)
314
        {
315
            return $response->withStatus(404);
316
        }
317
        return $response->withJson($user->delete());
318
    }
319
320
    public function listGroupsForUser($request, $response, $args)
321
    {
322
        $uid = 'me';
323
        if(isset($args['uid']))
324
        {
325
            $uid = $args['uid'];
326
        }
327
        $this->validateLoggedIn($request);
328
        $user = $this->getUserByUID($request, $uid);
329
        if($user === false)
330
        {
331
            return $response->withStatus(404);
332
        }
333
        $groups = $user->getGroups();
334
        if($groups === false)
335
        {
336
            $groups = array();
337
        }
338
        return $response->withJson($groups);
339
    }
340
341
    public function linkUser($request, $response, $args)
342
    {
343
        $uid = 'me';
344
        if(isset($args['uid']))
345
        {
346
            $uid = $args['uid'];
347
        }
348
        $this->validateLoggedIn($request);
349
        $obj = $request->getParsedBody();
350
        if($this->userIsMe($request, $uid))
351
        {
352
            $this->user->addLoginProvider($obj->provider);
353
            AuthProvider::getInstance()->impersonateUser($app->user);
0 ignored issues
show
Bug introduced by
The variable $app does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
354
        }
355
        else if($this->user->isInGroupNamed("LDAPAdmins"))
356
        {
357
            $user = AuthProvider::getInstance()->getUser($uid);
358
            if($user === false)
359
            {
360
                return $response->withStatus(404);
361
            }
362
            $user->addLoginProvider($obj->provider);
363
        }
364
        else
365
        {
366
            return $response->withStatus(404);
367
        }
368
        return $response->withJson(array('success'=>true));
369
    }
370
371
    protected function getAllUsersByFilter($filter, &$pending)
372
    {
373
        $auth = AuthProvider::getInstance();
374
        $user = $auth->getUsersByFilter($filter);
375 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...
376
        {
377
            $pending = false;
378
            return $user[0];
379
        }
380
        $user = $auth->getPendingUsersByFilter($filter);
381 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...
382
        {
383
            $pending = true;
384
            return $user[0];
385
        }
386
        return false;
387
    }
388
389
    public function checkEmailAvailable($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...
390
    {
391
        $params = $request->getQueryParams();
392
        $email = false;
393
        if(isset($params['email']))
394
        {
395
            $email = $params['email'];
396
        }
397
        if($email === false)
398
        {
399
            $params = $request->getParsedBody();
400
            if(isset($params['email']))
401
            {
402
                $email = $params['email'];
403
            }
404
            if($email === false)
405
            {
406
                return $response->withStatus(400);
407
            }
408
        }
409
        if(filter_var($email, FILTER_VALIDATE_EMAIL) === false || strpos($email, '@') === false)
410
        {
411
            return $response->withJson(false);
412
        }
413
        if(strstr($email, '+') !== false)
414
        {
415
            //Remove everything between the + and the @
416
            $begining = strpos($email, '+');
417
            $end = strpos($email, '@');
418
            $to_delete = substr($email, $begining, $end - $begining);
419
            $email = str_replace($to_delete, '', $email);
420
        }
421
        $filter = new \Data\Filter('mail eq '.$email);
422
        $pending = false;
423
        $user = $this->getAllUsersByFilter($filter, $pending);
424
        if($user === false)
425
        {
426
            return $response->withJson(true);
427
        }
428
        return $response->withJson(array('res'=>false, 'email'=>$user->mail, 'pending'=>$pending));
429
    }
430
431
    public function checkUidAvailable($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...
432
    {
433
        $params = $request->getQueryParams();
434
        $uid = false;
435
        if(isset($params['uid']))
436
        {
437
            $uid = $params['uid'];
438
        }
439
        if($uid === false)
440
        {
441
            return $response->withStatus(400);
442
        }
443
        if(strpos($uid, '=') !== false || strpos($uid, ',') !== false)
444
        {
445
            return $response->withJson(false);
446
        }
447
        $filter = new \Data\Filter('uid eq '.$uid);
448
        $pending = false;
449
        $user = $this->getAllUsersByFilter($filter, $pending);
450
        if($user === false)
451
        {
452
            return $response->withJson(true);
453
        }
454
        return $response->withJson(array('res'=>false, 'uidl'=>$user->uid, 'pending'=>$pending));
455
    }
456
457
    public function resetUserPassword($request, $response, $args)
458
    {
459
        $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...
460
        if(isset($args['uid']))
461
        {
462
            $uid = $args['uid'];
463
        }
464
        else
465
        {
466
            return $response->withStatus(400);
467
        }
468
        $auth = AuthProvider::getInstance();
469
        $users = $auth->getUsersByFilter(new \Data\Filter('uid eq '.$uid));
470
        if($users === false || !isset($users[0]))
471
        {
472
            return $response->withStatus(404);
473
        }
474
        $email_msg = new PasswordResetEmail($users[0]);
475
        $email_provider = EmailProvider::getInstance();
476
        if($email_provider->sendEmail($email_msg) === false)
477
        {
478
            throw new \Exception('Unable to send email!');
479
        }
480
        return $response->withJson(true);
481
    }
482
483
    public function remindUid()
484
    {
485
        $params = $request->getQueryParams();
0 ignored issues
show
Bug introduced by
The variable $request does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
486
        $email = false;
487
        if(isset($params['email']))
488
        {
489
            $email = $params['email'];
490
        }
491
        if($email === false)
492
        {
493
            return $response->withStatus(400);
0 ignored issues
show
Bug introduced by
The variable $response does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

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