Completed
Push — master ( 047121...54c8bf )
by Patrick
02:58 queued 01:25
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
require_once('class.UIDForgotEmail.php');
3
require_once('class.PasswordResetEmail.php');
4
5
class UsersAPI extends ProfilesAdminAPI
6
{
7
    public function setup($app)
8
    {
9
        $app->get('[/]', array($this, 'listUsers'));
10
        $app->post('[/]', array($this, 'createUser'));
11
        $app->get('/{uid}[/]', array($this, 'showUser'));
12
        $app->patch('/{uid}[/]', array($this, 'editUser'));
13
        $app->delete('/{uid}[/]', array($this, 'deleteUser'));
14
        $app->get('/{uid}/groups[/]', array($this, 'listGroupsForUser'));
15
        $app->post('/{uid}/Actions/link[/]', array($this, 'linkUser'));
16
        $app->post('/{uid}/Actions/reset_pass[/]', array($this, 'resetUserPassword'));
17
        $app->post('/{uid}/Actions/ClearPosition[/]', array($this, 'clearPosition'));
18
        $app->post('/me/Actions/RemoveEmail[/]', array($this, 'removeEmail'));
19
        $app->post('/Actions/check_email_available[/]', array($this, 'checkEmailAvailable'));
20
        $app->post('/Actions/check_uid_available[/]', array($this, 'checkUidAvailable'));
21
        $app->post('/Actions/remind_uid[/]', array($this, 'remindUid'));
22
    }
23
24
    public function listUsers($request, $response)
25
    {
26
        $odata = $request->getAttribute('odata', new \ODataParams(array()));
27
        if($this->validateIsAdmin($request, true) === false)
28
        {
29
            $users = array($this->user);
30
            $users = $odata->filterArrayPerSelect($users);
31
        }
32
        else
33
        {
34
            $auth = AuthProvider::getInstance();
35
            $users = $auth->getUsersByFilter($odata->filter, $odata->select, $odata->top, $odata->skip, 
36
                                             $odata->orderby);
37
        }
38
        return $response->withJson($users);
39
    }
40
41
    protected function validateCanCreateUser($proposedUser, $auth, &$message)
42
    {
43
        $user = $auth->getUsersByFilter(new \Data\Filter('mail eq '.$proposedUser['mail']));
44 View Code Duplication
        if($user !== false && isset($user[0]))
45
        {
46
            $message = 'Email already exists!';
47
            return false;
48
        }
49
        $user = $auth->getUsersByFilter(new \Data\Filter('uid eq '.$proposedUser['uid']));
50 View Code Duplication
        if($user !== false && isset($user[0]))
51
        {
52
            $message = 'Username already exists!';
53
            return false;
54
        }
55
        return true;
56
    }
57
58
    protected function validEmail($email)
59
    {
60
        if(filter_var($email) === false)
61
        {
62
            return false;
63
        }
64
        $pos = strpos($email, '@');
65
        if($pos === false)
66
        {
67
            return false;
68
        }
69
        $domain = substr($email, $pos + 1);
70
        if(checkdnsrr($domain, 'MX') === false)
71
        {
72
            return false;
73
        }
74
        return true;
75
    }
76
77
    protected function getFailArray($message)
78
    {
79
        return array('res'=>false, 'message'=>$message);
80
    }
81
82
    public function createUser($request, $response)
83
    {
84
        $this->user = $request->getAttribute('user');
85
        //This one is different. If they are logged in fail...
86
        if($this->user !== false)
87
        {
88
            return $response->withStatus(404);
89
        }
90
        $obj = $request->getParsedBody();
91
        if(!isset($obj['captcha']))
92
        {
93
            return $response->withStatus(401);
94
        }
95
        $captcha = FlipSession::getVar('captcha');
96
        if($captcha === false)
97
        {
98
            return $response->withStatus(401);
99
        }
100
        if(!$captcha->is_answer_right($obj['captcha']))
101
        {
102
            return $response->withJson($this->getFailArray('Incorrect answer to CAPTCHA!'), 412);
103
        }
104
        $auth = AuthProvider::getInstance();
105
        $message = false;
106
        if($this->validateCanCreateUser($obj, $auth, $message) === false)
107
        {
108
            return $response->withJson($this->getFailArray($message), 412);
109
        }
110
        else if($this->validEmail($obj['mail']) === false)
111
        {
112
            return $response->withJson($this->getFailArray('Invalid Email Address!'));
113
        }
114
        $ret = $auth->createPendingUser($obj);
115
        if($ret == false)
116
        {
117
            return $response->withJson($this->getFailArray('Failed to save user registration!'), 500);
118
        }
119
        return $response->withJson($ret);
120
    }
121
122
    protected function userIsMe($request, $uid)
123
    {
124
        $this->user = $request->getAttribute('user');
125
        return ($uid === 'me' || ($this->user !== false && $uid === $this->user->uid));
126
    }
127
128
    protected function hasLeadAccess()
129
    {
130
        return ($this->user->isInGroupNamed('Leads') || $this->user->isInGroupNamed('CC') || $this->user->isInGroupNamed('AFs'));
131
    }
132
133 View Code Duplication
    protected function getUserByUIDReadOnly($request, $uid)
134
    {
135
        if($this->userIsMe($request, $uid))
136
        {
137
            return $this->user;
138
        }
139
        if($this->user->isInGroupNamed('LDAPAdmins') || $this->hasLeadAccess())
140
        {
141
            $auth = \AuthProvider::getInstance();
142
            $filter = new \Data\Filter("uid eq $uid");
143
            $users = $auth->getUsersByFilter($filter);
144
            if(!empty($users))
145
            {
146
                return $users[0];
147
            }
148
        }
149
        return false;
150
    }
151
152 View Code Duplication
    protected function getUserByUID($request, $uid)
153
    {
154
        if($this->userIsMe($request, $uid))
155
        {
156
            return $this->user;
157
        }
158
        if($this->user->isInGroupNamed('LDAPAdmins'))
159
        {
160
            $auth = \AuthProvider::getInstance();
161
            $filter = new \Data\Filter("uid eq $uid");
162
            $users = $auth->getUsersByFilter($filter);
163
            if(!empty($users))
164
            {
165
                return $users[0];
166
            }
167
        }
168
        return false;
169
    }
170
171
    public function showUser($request, $response, $args)
172
    {
173
        $uid = $args['uid'];
174
        $user = $request->getAttribute('user');
175
        if($user === false)
176
        {
177
            if($_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR'])
178
            {
179
                $user = \AuthProvider::getInstance()->getUsersByFilter(new \Data\Filter("uid eq $uid"));
180
                if(empty($user))
181
                {
182
                    return $response->withStatus(404);
183
                }
184
                return $response->withJson($user[0]);
185
            } 
186
            return $response->withStatus(401);
187
        }
188
        $user = $this->getUserByUIDReadOnly($request, $uid);
189
        if($user === false)
190
        {
191
            return $response->withStatus(404);
192
        }
193
        if(!is_object($user) && isset($user[0]))
194
        {
195
            $user = $user[0];
196
        }
197
        if($request->getAttribute('format') === 'vcard')
198
        {
199
            $response = $response->withHeader('Content-Type', 'text/x-vCard');
200
            $response->getBody()->write($user->getVcard());
201
            return $response;
202
        }
203
        return $response->withJson($user);
204
    }
205
206
    protected function sendPasswordResetEmail($user)
207
    {
208
        $forwardedFor = false;
209
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
210
        {
211
            $forwardedFor = $_SERVER['HTTP_X_FORWARDED_FOR'];
212
        }
213
        $emailMsg = new PasswordHasBeenResetEmail($user, $_SERVER['REMOTE_ADDR'], $forwardedFor);
214
        $emailProvider = EmailProvider::getInstance();
215
        if($emailProvider->sendEmail($emailMsg) === false)
216
        {
217
            throw new \Exception('Unable to send password reset email!');
218
        }
219
    }
220
221
    protected function exceptionCodeToHttpCode($e)
222
    {
223
        if($e->getCode() === 3)
224
        {
225
            return 401;
226
        }
227
        return 500;
228
    }
229
230
    protected function getUser($request, $uid, $payload)
231
    {
232
        $this->user = $request->getAttribute('user');
233
        if($this->user === false)
234
        {
235
            if(isset($payload['hash']))
236
            {
237
                $auth = AuthProvider::getInstance();
238
                $this->user = $auth->getUserByResetHash($payload['hash']);
239
                return $this->user;
240
            }
241
            return false;
242
        }
243
        return $this->getUserByUID($request, $uid);
244
    }
245
246
    public function editUser($request, $response, $args)
247
    {
248
        $uid = 'me';
249
        if(isset($args['uid']))
250
        {
251
            $uid = $args['uid'];
252
        }
253
        $obj = $request->getParsedBody();
254
        $user = $this->getUser($request, $uid, $obj);
255
        if($user === false)
256
        {
257
            return $response->withStatus(404);
258
        }
259
        try
260
        {
261
            if(isset($obj['old_uid']))
262
            {
263
                unset($obj['old_uid']);
264
            }
265
            unset($obj['uid']);
266
            if(isset($obj['password']))
267
            {
268
                $obj['userPassword'] = $obj['password'];
269
                unset($obj['password']);
270
            }
271
            $user->editUser($obj);
272
        }
273
        catch(\Exception $e)
274
        {
275
            return $response->withJson(array('error'=>array('msg'=>$e->getMessage(), 'stack'=>$e->getTraceAsString())), $this->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
        if(!empty($user))
377
        {
378
            $pending = false;
379
            return $user[0];
380
        }
381
        $user = $auth->getPendingUsersByFilter($filter);
382
        if(!empty($user))
383
        {
384
            $pending = true;
385
            return $user[0];
386
        }
387
        return false;
388
    }
389
390
    public function checkEmailAvailable($request, $response)
391
    {
392
        $params = $request->getQueryParams();
393
        $email = false;
394
        if(isset($params['email']))
395
        {
396
            $email = $params['email'];
397
        }
398 View Code Duplication
        if($email === false)
399
        {
400
            $params = $request->getParsedBody();
401
            if(isset($params['email']))
402
            {
403
                $email = $params['email'];
404
            }
405
            if($email === false)
406
            {
407
                return $response->withStatus(400);
408
            }
409
        }
410
        if(filter_var($email, FILTER_VALIDATE_EMAIL) === false || strpos($email, '@') === false)
411
        {
412
            return $response->withJson(false);
413
        }
414
        if(strstr($email, '+') !== false)
415
        {
416
            //Remove everything between the + and the @
417
            $begining = strpos($email, '+');
418
            $end = strpos($email, '@');
419
            $to_delete = substr($email, $begining, $end - $begining);
420
            $email = str_replace($to_delete, '', $email);
421
        }
422
        $filter = new \Data\Filter('mail eq '.$email);
423
        $pending = false;
424
        $user = $this->getAllUsersByFilter($filter, $pending);
425
        if($user === false)
426
        {
427
            return $response->withJson(true);
428
        }
429
        return $response->withJson(array('res'=>false, 'email'=>$user->mail, 'pending'=>$pending));
430
    }
431
432
    public function checkUidAvailable($request, $response)
433
    {
434
        $params = $request->getQueryParams();
435
        $uid = false;
436
        if(isset($params['uid']))
437
        {
438
            $uid = $params['uid'];
439
        }
440 View Code Duplication
        if($uid === false)
441
        {
442
            $params = $request->getParsedBody();
443
            if(isset($params['uid']))
444
            {
445
                $uid = $params['uid'];
446
            }
447
            if($uid === false)
448
            {
449
                return $response->withStatus(400);
450
            }
451
        }
452
        if(strpos($uid, '=') !== false || strpos($uid, ',') !== false)
453
        {
454
            return $response->withJson(false);
455
        }
456
        $filter = new \Data\Filter('uid eq '.$uid);
457
        $pending = false;
458
        $user = $this->getAllUsersByFilter($filter, $pending);
459
        if($user === false)
460
        {
461
            return $response->withJson(true);
462
        }
463
        return $response->withJson(array('res'=>false, 'uid'=>$user->uid, 'pending'=>$pending));
464
    }
465
466
    public function resetUserPassword($request, $response, $args)
467
    {
468
        $uid = false;
469
        if(isset($args['uid']))
470
        {
471
            $uid = $args['uid'];
472
        }
473
        else
474
        {
475
            return $response->withStatus(400);
476
        }
477
        $auth = AuthProvider::getInstance();
478
        $users = $auth->getUsersByFilter(new \Data\Filter('uid eq '.$uid));
479
        if(empty($users))
480
        {
481
            return $response->withStatus(404);
482
        }
483
        $email_msg = new PasswordResetEmail($users[0]);
484
        $email_provider = EmailProvider::getInstance();
485
        if($email_provider->sendEmail($email_msg) === false)
486
        {
487
            throw new \Exception('Unable to send email!');
488
        }
489
        return $response->withJson(true);
490
    }
491
492
    public function clearPosition($request, $response, $args)
493
    {
494
        $this->validateLoggedIn($request);
495
        if(!$this->user->isInGroupNamed('LDAPAdmins'))
496
        {
497
            return $response->withStatus(401);
498
        }
499
        $uid = $args['uid'];
500
        $auth = \AuthProvider::getInstance();
501
        $filter = new \Data\Filter("uid eq $uid");
502
        $users = $auth->getUsersByFilter($filter);
503
        if(empty($users))
504
        {
505
            return $response->withStatus(404);
506
        }
507
        $users[0]->editUser(array('title'=>null, 'ou'=>null));
508
        return $response->withStatus(204);
509
    }
510
511
    public function removeEmail($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...
512
    {
513
        $this->validateLoggedIn($request);
514
        $obj = $request->getParsedBody();
515
        if(!$this->userIsMe($request, 'me'))
516
        {
517
            return $response->withStatus(401);
518
        }
519
        if(!isset($this->user->allMail))
520
        {
521
            return $response->withJSON(array('error' => 'User does not have multiple email addresses'), 409);
522
        }
523
        $email = $obj['email'];
524
        if(!in_array($email, $this->user->allMail))
525
        {
526
            return $response->withJSON(array('error' => 'User does not have email address '.$email), 409);
527
        }
528
        $res = $this->user->removeEmail($email);
529
        if($res)
530
        {
531
            return $response->withStatus(204);
532
        }
533
        else
534
        {
535
            return $response->withStatus(500);
536
        }
537
    }
538
539
    public function remindUid($request, $response, $args)
540
    {
541
        $params = $request->getQueryParams();
542
        $email = false;
543
        if(isset($params['email']))
544
        {
545
            $email = $params['email'];
546
        }
547 View Code Duplication
        if($email === false)
548
        {
549
            $params = $request->getParsedBody();
550
            if(isset($params['email']))
551
            {
552
                $email = $params['email'];
553
            }
554
            if($email === false)
555
            {
556
                return $response->withStatus(400);
557
            }
558
        }
559
        if(filter_var($email, FILTER_VALIDATE_EMAIL) === false)
560
        {
561
            return $response->withStatus(400);
562
        }
563
        $auth = AuthProvider::getInstance();
564
        $users = $auth->getUsersByFilter(new \Data\Filter('mail eq '.$email));
565
        if(empty($users))
566
        {
567
            return $response->withStatus(404);
568
        }
569
        $email_msg = new UIDForgotEmail($users[0]);
570
        $email_provider = EmailProvider::getInstance();
571
        if($email_provider->sendEmail($email_msg) === false)
572
        {
573
            throw new \Exception('Unable to send email!');
574
        }
575
    }
576
}
577
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
578