Completed
Branch fix/scruitinizer (38ecac)
by Patrick
02:45
created

api/v1/class.UsersAPI.php (1 issue)

Severity

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