Completed
Pull Request — develop (#51)
by Patrick
02:39
created

UsersAPI::validateIsAdmin()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 9

Duplication

Lines 17
Ratio 100 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 4
nop 2
dl 17
loc 17
rs 9.2
c 0
b 0
f 0
1
<?php
2
class UsersAPI extends ProfilesAdminAPI
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
    public function listUsers($request, $response)
20
    {
21
        $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...
22
        $odata = $request->getAttribute('odata', new \ODataParams(array()));
23
        if($this->validateIsAdmin($request, true) === false)
24
        {
25
            $users = array($this->user);
26
            $users = $odata->filterArrayPerSelect($users);
27
        }
28
        else
29
        {
30
            $auth = AuthProvider::getInstance();
31
            $users = $auth->getUsersByFilter($odata->filter, $odata->select, $odata->top, $odata->skip, 
32
                                             $odata->orderby);
33
        }
34
        return $response->withJson($users);
35
    }
36
37
    protected function validateCanCreateUser($proposedUser, $auth, &$message)
38
    {
39
        $user = $auth->getUsersByFilter(new \Data\Filter('mail eq '.$proposedUser->mail));
40 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...
41
        {
42
            $message = 'Email already exists!';
43
            return false;
44
        }
45
        $user = $auth->getUsersByFilter(new \Data\Filter('uid eq '.$proposedUser->uid));
46 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...
47
        {
48
            $message = 'Username already exists!';
49
            return false;
50
        }
51
        return true;
52
    }
53
54
    protected function validEmail($email)
55
    {
56
        if(filter_var($email) === false)
57
        {
58
            return false;
59
        }
60
        $pos = strpos($email, '@');
61
        if($pos === false)
62
        {
63
            return false;
64
        }
65
        $domain = substr($email, $pos + 1);
66
        if(checkdnsrr($domain, 'MX') === false)
67
        {
68
            return false;
69
        }
70
        return true;
71
    }
72
73
    public function createUser($request, $response)
74
    {
75
        $this->user = $request->getAttribute('user');
76
        //This one is different. If they are logged in fail...
77
        if($this->user !== false)
78
        {
79
            return $response->withStatus(404);
80
        }
81
        $obj = $request->getParsedBody();
82
        if(!isset($obj->captcha))
83
        {
84
            return $response->withStatus(401);
85
        }
86
        $captcha = FlipSession::getVar('captcha');
87
        if($captcha === false)
88
        {
89
            return $response->withStatus(401);
90
        }
91
        if(!$captcha->is_answer_right($obj->captcha))
92
        {
93
            return $response->withJson(array('res'=>false, 'message'=>'Incorrect answer to CAPTCHA!'), 412);
94
        }
95
        $auth = AuthProvider::getInstance();
96
        $message = false;
97
        if($this->validateCanCreateUser($obj, $auth, $message) === false)
98
        {
99
            return $response->withJson(array('res'=>false, 'message'=>$message), 412);
100
        }
101 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...
102
        {
103
            return $response->withJson(array('res'=>false, 'message'=>'Invalid Email Address!'));
104
        }
105
        $ret = $auth->createPendingUser($obj);
106 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...
107
        {
108
            return $response->withJson(array('res'=>false, 'message'=>'Failed to save user registration!'), 500);
109
        }
110
        return $response->withJson($ret);
111
    }
112
113
    protected function userIsMe($request, $uid)
114
    {
115
        $this->user = $request->getAttribute('user');
116
        return ($uid === 'me' || ($this->user !== false && $uid === $this->user->uid));
117
    }
118
119 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...
120
    {
121
        if($this->userIsMe($request, $uid))
122
        {
123
            return $this->user;
124
        }
125
        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...
126
        {
127
            $auth = \AuthProvider::getInstance();
128
            $filter = new \Data\Filter("uid eq $uid");
129
            $users = $auth->getUsersByFilter($filter);
130
            if($users !== false && isset($users[0]))
131
            {
132
                return $users[0];
133
            }
134
        }
135
        return false;
136
    }
137
138 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...
139
    {
140
        if($this->userIsMe($request, $uid))
141
        {
142
            return $this->user;
143
        }
144
        if($this->user->isInGroupNamed('LDAPAdmins'))
145
        {
146
            $auth = \AuthProvider::getInstance();
147
            $filter = new \Data\Filter("uid eq $uid");
148
            $users = $auth->getUsersByFilter($filter);
149
            if($users !== false && isset($users[0]))
150
            {
151
                return $users[0];
152
            }
153
        }
154
        return false;
155
    }
156
157
    public function showUser($request, $response, $args)
158
    {
159
        $uid = $args['uid'];
160
        $user = $request->getAttribute('user');
161
        if($user === false)
162
        {
163
            if($_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR'])
164
            {
165
                $user = \AuthProvider::getInstance()->getUsersByFilter(new \Data\Filter("uid eq $uid"));
166
                if($user === false || !isset($user[0]))
167
                {
168
                    return $response->withStatus(404);
169
                }
170
                return $response->withJson($user[0]);
171
            } 
172
            return $response->withStatus(401);
173
        }
174
        $user = $this->getUserByUIDReadOnly($request, $uid);
175
        if($user === false)
176
        {
177
            return $response->withStatus(404);
178
        }
179
        if(!is_object($user) && isset($user[0]))
180
        {
181
            $user = $user[0];
182
        }
183
        if($request->getAttribute('format') === 'vcard')
184
        {
185
            $response = $response->withHeader('Content-Type', 'text/x-vCard');
186
            $response->getBody()->write($user->getVcard());
187
            return $response;
188
        }
189
        return $response->withJson($user);
190
    }
191
192
    protected function sendPasswordResetEmail($user)
193
    {
194
        $forwardedFor = false;
195
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
196
        {
197
            $forwardedFor = $_SERVER['HTTP_X_FORWARDED_FOR'];
198
        }
199
        $emailMsg = new PasswordHasBeenResetEmail($user, $_SERVER['REMOTE_ADDR'], $forwardedFor);
200
        $emailProvider = EmailProvider::getInstance();
201
        if($emailProvider->sendEmail($emailMsg) === false)
202
        {
203
            throw new \Exception('Unable to send password reset email!');
204
        }
205
    }
206
207
    protected function exceptionCodeToHttpCode($e)
208
    {
209
        if($e->getCode() === 3)
210
        {
211
            return 401;
212
        }
213
        return 500;
214
    }
215
216
    protected function getUser($request, $uid, $payload)
217
    {
218
        $this->user = $request->getAttribute('user');
219
        if($this->user === false)
220
        {
221
            if(isset($payload->hash))
222
            {
223
                $auth = AuthProvider::getInstance();
224
                $this->user = $auth->getUserByResetHash($payload->hash);
225
                return $this->user;
226
            }
227
            return false;
228
        }
229
        return $this->getUserByUID($request, $uid);
230
    }
231
232
    public function editUser($request, $response, $args)
233
    {
234
        $uid = 'me';
235
        if(isset($args['uid']))
236
        {
237
            $uid = $args['uid'];
238
        }
239
        $obj = $request->getParsedBody();
240
        $user = $this->getUser($request, $uid, $obj);
241
        if($user === false)
242
        {
243
            return $response->withStatus(404);
244
        }
245
        try
246
        {
247
            if(isset($obj->old_uid))
248
            {
249
                unset($obj->old_uid);
250
            }
251
            $user->editUser($obj);
252
        }
253
        catch(\Exception $e)
254
        {
255
            return $response->withJson($e, exceptionCodeToHttpCode($e));
256
        }
257
        if($this->userIsMe($request, $uid))
258
        {
259
            \FlipSession::setUser($user);
260
        }
261
        if(isset($obj->password))
262
        {
263
            $this->sendPasswordResetEmail($user);
264
        }
265
        return $response->withJson(array('success'=>true));
266
    }
267
268
    public function deleteUser($request, $response, $args)
269
    {
270
        $uid = 'me';
271
        if(isset($args['uid']))
272
        {
273
            $uid = $args['uid'];
274
        }
275
        $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...
276
        if($this->validateIsAdmin($request, true) === false && $this->userIsMe($request, $uid))
277
        {
278
            $user = $this->user;
279
        }
280
        else
281
        {
282
            $auth = AuthProvider::getInstance();
283
            $filter = new \Data\Filter("uid eq $uid");
284
            $user = $auth->getUsersByFilter($filter);
285
            if(empty($user))
286
            {
287
                $user = false;
288
            }
289
            else
290
            {
291
                $user = $user[0];
292
            }
293
        }
294
        if($user === false)
295
        {
296
            return $response->withStatus(404);
297
        }
298
        return $response->withJson($user->delete());
299
    }
300
301
    public function listGroupsForUser($request, $response, $args)
302
    {
303
        $uid = 'me';
304
        if(isset($args['uid']))
305
        {
306
            $uid = $args['uid'];
307
        }
308
        $this->validateLoggedIn($request);
309
        $user = $this->getUserByUID($request, $uid);
310
        if($user === false)
311
        {
312
            return $response->withStatus(404);
313
        }
314
        $groups = $user->getGroups();
315
        if($groups === false)
316
        {
317
            $groups = array();
318
        }
319
        return $response->withJson($groups);
320
    }
321
322
    public function linkUser($request, $response, $args)
323
    {
324
        $uid = 'me';
325
        if(isset($args['uid']))
326
        {
327
            $uid = $args['uid'];
328
        }
329
        $this->validateLoggedIn($request);
330
        $obj = $request->getParsedBody();
331
        if($this->userIsMe($request, $uid))
332
        {
333
            $this->user->addLoginProvider($obj->provider);
334
            AuthProvider::getInstance()->impersonateUser($this->user);
335
        }
336
        else if($this->user->isInGroupNamed("LDAPAdmins"))
337
        {
338
            $user = AuthProvider::getInstance()->getUser($uid);
339
            if($user === false)
340
            {
341
                return $response->withStatus(404);
342
            }
343
            $user->addLoginProvider($obj->provider);
344
        }
345
        else
346
        {
347
            return $response->withStatus(404);
348
        }
349
        return $response->withJson(array('success'=>true));
350
    }
351
352
    protected function getAllUsersByFilter($filter, &$pending)
353
    {
354
        $auth = AuthProvider::getInstance();
355
        $user = $auth->getUsersByFilter($filter);
356 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...
357
        {
358
            $pending = false;
359
            return $user[0];
360
        }
361
        $user = $auth->getPendingUsersByFilter($filter);
362 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...
363
        {
364
            $pending = true;
365
            return $user[0];
366
        }
367
        return false;
368
    }
369
370
    public function checkEmailAvailable($request, $response)
371
    {
372
        $params = $request->getQueryParams();
373
        $email = false;
374
        if(isset($params['email']))
375
        {
376
            $email = $params['email'];
377
        }
378
        if($email === false)
379
        {
380
            return $response->withStatus(400);
381
        }
382
        if(filter_var($email, FILTER_VALIDATE_EMAIL) === false || strpos($email, '@') === false)
383
        {
384
            return $response->withJson(false);
385
        }
386
        if(strstr($email, '+') !== false)
387
        {
388
            //Remove everything between the + and the @
389
            $begining = strpos($email, '+');
390
            $end = strpos($email, '@');
391
            $to_delete = substr($email, $begining, $end - $begining);
392
            $email = str_replace($to_delete, '', $email);
393
        }
394
        $filter = new \Data\Filter('mail eq '.$email);
395
        $pending = false;
396
        $user = $this->getAllUsersByFilter($filter, $pending);
397
        if($user === false)
398
        {
399
            return $response->withJson(true);
400
        }
401
        return $response->withJson(array('res'=>false, 'email'=>$user->mail, 'pending'=>$pending));
402
    }
403
404
    public function checkUidAvailable($request, $response)
405
    {
406
        $params = $request->getQueryParams();
407
        $uid = false;
408
        if(isset($params['uid']))
409
        {
410
            $uid = $params['uid'];
411
        }
412
        if($uid === false)
413
        {
414
            return $response->withStatus(400);
415
        }
416
        if(strpos($uid, '=') !== false || strpos($uid, ',') !== false)
417
        {
418
            return $response->withJson(false);
419
        }
420
        $filter = new \Data\Filter('uid eq '.$uid);
421
        $pending = false;
422
        $user = $this->getAllUsersByFilter($filter, $pending);
423
        if($user === false)
424
        {
425
            return $response->withJson(true);
426
        }
427
        return $response->withJson(array('res'=>false, 'uidl'=>$user->uid, 'pending'=>$pending));
428
    }
429
430
    public function resetUserPassword($request, $response, $args)
431
    {
432
        $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...
433
        if(isset($args['uid']))
434
        {
435
            $uid = $args['uid'];
436
        }
437
        else
438
        {
439
            return $response->withStatus(400);
440
        }
441
        $auth = AuthProvider::getInstance();
442
        $users = $auth->getUsersByFilter(new \Data\Filter('uid eq '.$uid));
443
        if($users === false || !isset($users[0]))
444
        {
445
            return $response->withStatus(404);
446
        }
447
        $email_msg = new PasswordResetEmail($users[0]);
448
        $email_provider = EmailProvider::getInstance();
449
        if($email_provider->sendEmail($email_msg) === false)
450
        {
451
            throw new \Exception('Unable to send email!');
452
        }
453
        return $response->withJson(true);
454
    }
455
456
    public function remindUid($request, $response)
457
    {
458
        $params = $request->getQueryParams();
459
        $email = false;
460
        if(isset($params['email']))
461
        {
462
            $email = $params['email'];
463
        }
464
        if($email === false)
465
        {
466
            return $response->withStatus(400);
467
        }
468
        if(filter_var($email, FILTER_VALIDATE_EMAIL) === false)
469
        {
470
            return $response->withStatus(400);
471
        }
472
        $auth = AuthProvider::getInstance();
473
        $users = $auth->getUsersByFilter(new \Data\Filter('mail eq '.$email));
474
        if($users === false || !isset($users[0]))
475
        {
476
            return $response->withStatus(404);
477
        }
478
        $email_msg = new UIDForgotEmail($users[0]);
479
        $email_provider = EmailProvider::getInstance();
480
        if($email_provider->sendEmail($email_msg) === false)
481
        {
482
            throw new \Exception('Unable to send email!');
483
        }
484
    }
485
}
486
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
487