Completed
Push — master ( a5ab4a...93e8b1 )
by Patrick
03:07
created

User::checkForUnsettableElements()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 4
eloc 8
nc 4
nop 1
dl 0
loc 16
rs 9.2
c 4
b 0
f 0
1
<?php
2
/**
3
 * User class
4
 *
5
 * This file describes the User classes
6
 *
7
 * PHP version 5 and 7
8
 *
9
 * @author Patrick Boyd / [email protected]
10
 * @copyright Copyright (c) 2015, Austin Artistic Reconstruction
11
 * @license http://www.apache.org/licenses/ Apache 2.0 License
12
 */
13
14
namespace Auth;
15
16
/**
17
 * A class to abstract access to Users regardless of the Authentication type used.
18
 *
19
 * This class is the primary method to access user information.
20
 * 
21
 * @property string $uid The user's ID or name
22
 * @property string $mail The user's email address
23
 * @property string $sn The user's surname (last name)
24
 * @property string $givenName The user's given name (first name)
25
 * @property string $cn The user's nick name
26
 * @property string $displayName The user's display name
27
 * @property string $postalAddress The user's mailing address
28
 * @property string $postalCode The user's postal or zip code
29
 * @property string $l The user's city
30
 * @property string $st The user's state or province
31
 * @property string $c The user's country
32
 * @property string $mobile The user's phone number
33
 * @property string $jpegPhoto The user's profile photo
34
 * @property array $host The service's the user can use to login
35
 * @property array $title The user's titles in the organization
36
 * @property string $o The user's organization
37
 * @property array $ou The user's units or areas within the organization
38
 */
39
class User extends \SerializableObject
40
{
41
    /**
42
     * An array to cache the title to string mappings so that they don't need to be pulled from the database
43
     * everytime
44
     */ 
45
    public static $titlenames = null;
46
47
    /**
48
     * An array of properties that cannot be set on a user
49
     */
50
    protected $unsettableElements = array(
51
        'uid',
52
        'email'
53
    );
54
55
    /**
56
     * Is this user in the Group or a child of that group?
57
     *
58
     * @param string $name The name of the group to check if the user is in
59
     *
60
     * @return boolean True if the user is in the group, false otherwise
61
     */
62
    public function isInGroupNamed($name)
63
    {
64
        return false;
65
    }
66
67
    public function __get($propName)
68
    {
69
        return false;
70
    }
71
72
    public function __set($propName, $value)
73
    {
74
    }
75
76
    public function __isset($propName)
77
    {
78
        return false;
79
    }
80
81
    /**
82
     * The list of titles for the user
83
     *
84
     * @return boolean|array The user's title(s) in user friendly strings
85
     *
86
     * @SuppressWarnings("StaticAccess")
87
     */
88
    public function getTitleNames()
89
    {
90
        $titles = $this->title;
91
        if($titles === false)
92
        {
93
            return false;
94
        }
95
        if(self::$titlenames === null)
96
        {
97
            $dataSet = \DataSetFactory::getDataSetByName('profiles');
98
            $dataTable = $dataSet['position'];
99
            $titlenames = $dataTable->read();
100
            self::$titlenames = array();
101
            $count = count($titlenames);
102
            for($i = 0; $i < $count; $i++)
103
            {
104
                self::$titlenames[$titlenames[$i]['short_name']] = $titlenames[$i];
105
            }
106
        }
107
        $count = count($titles);
108
        for($i = 0; $i < $count; $i++)
109
        {
110
            if(isset(self::$titlenames[$titles[$i]]))
111
            {
112
                $title = self::$titlenames[$titles[$i]];
113
                $titles[$i] = $title['name'];
114
            }
115
        }
116
        return $titles;
117
    }
118
119
    /**
120
     * The groups the user is a part of
121
     *
122
     * @return boolean|array The user's Auth\Group structures
123
     */
124
    public function getGroups()
125
    {
126
        return false;
127
    }
128
129
    /**
130
     * Add a supplemental login type that the user can use to login
131
     *
132
     * @param string $provider The hostname for the provider
133
     */
134
    public function addLoginProvider($provider)
135
    {
136
        if(isset($this->host))
137
        {
138
            $tmp = $this->host;
139
            $tmp[] = $provider;
140
            $this->host = $tmp;
141
        }
142
        else
143
        {
144
            $this->host = array($provider);
145
        }
146
    }
147
148
    /**
149
     * Can the user login with this provider?
150
     *
151
     * @param string $provider The hostname for the provider
152
     *
153
     * @return boolean true if they can login with the provider, false otherwise
154
     */
155
    public function canLoginWith($provider)
156
    {
157
        $hosts = $this->host;
158
        if($hosts === false)
159
        {
160
            return false;
161
        }
162
        $count = count($hosts);
163
        for($i = 0; $i < $count; $i++)
164
        {
165
            if(strcasecmp($hosts[$i], $provider) === 0)
166
            {
167
                return true;
168
            }
169
        }
170
        return false;
171
    }
172
173
    /**
174
     * Set the user's password without verifying the current password
175
     *
176
     * @param string $password The new user password
177
     *
178
     * @return boolean true if the user's password was changed, false otherwise
179
     */
180
    protected function setPass($password)
181
    {
182
        return false;
183
    }
184
185
    /**
186
     * Has the user completely filled out their user profile?
187
     *
188
     * @return boolean true if the user's profile is complete, false otherwise
189
     */
190
    public function isProfileComplete()
191
    {
192
        if($this->c === false || $this->postalAddress === false ||
193
           $this->postalCode === false || $this->l === false ||
194
           $this->st === false || $this->mobile === false)
195
        {
196
            return false;
197
        }
198
        return true;
199
    }
200
201
    /**
202
     * Validate that the user's password is the specified password
203
     *
204
     * @param string $password The user's current password
205
     *
206
     * @return boolean true if the user's password is correct, false otherwise
207
     *
208
     * @SuppressWarnings("UnusedFormalParameter")
209
     */
210
    public function validate_password($password)
211
    {
212
        return false;
213
    }
214
215
    /**
216
     * Validate that the user's reset hash is the sepcified hash
217
     *
218
     * @param string $hash The user's reset hash
219
     *
220
     * @return boolean true if the user's hash is correct, false otherwise
221
     *
222
     * @SuppressWarnings("UnusedFormalParameter")
223
     */
224
    public function validate_reset_hash($hash)
225
    {
226
        return false;
227
    }
228
229
    /**
230
     * Change the user's password, validating the old password or reset hash
231
     *
232
     * @param string $oldpass The user's original password or reset hash if $isHash is true
233
     * @param string $newpass The user's new password
234
     * @param boolean $isHash Is $old_pass a password or a hash
235
     *
236
     * @return boolean true if the user's password was changed, false otherwise
237
     */
238
    public function change_pass($oldpass, $newpass, $isHash = false)
239
    {
240
        if($isHash === false && $this->validate_password($oldpass) === false)
241
        {
242
            throw new \Exception('Invalid Password!', 3);
243
        }
244
        if($isHash === true && $this->validate_reset_hash($oldpass) === false)
245
        {
246
            throw new \Exception('Invalid Reset Hash!', 3);
247
        }
248
        if($this->setPass($newpass) === false)
249
        {
250
            throw new \Exception('Unable to set password!', 6);
251
        }
252
        return true;
253
    }
254
255
    /**
256
     * Allow write for the user
257
     */
258
    protected function enableReadWrite()
259
    {
260
        //Make sure we are bound in write mode
261
        $auth = \AuthProvider::getInstance();
262
        $ldap = $auth->getMethodByName('Auth\LDAPAuthenticator');
263
        if($ldap !== false)
264
        {
265
            $ldap->get_and_bind_server(true);
266
        }
267
    }
268
269
    /**
270
     * Update the user password if required
271
     */
272
    private function editUserPassword($data)
273
    {
274
        if(isset($data->password))
275
        {
276
            if(isset($data->oldpass))
277
            {
278
                $this->change_pass($data->oldpass, $data->password);
279
                unset($data->oldpass);
280
            }
281
            else if(isset($data->hash))
282
            {
283
                $this->change_pass($data->hash, $data->password, true);
284
                unset($data->hash);
285
            }
286
            unset($data->password);
287
        }
288
    }
289
290
    private function editNames($data)
291
    {
292
        if(isset($data->displayName))
293
        {
294
            $this->displayName = $data->displayName;
295
            unset($data->displayName);
296
        }
297
        if(isset($data->givenName))
298
        {
299
            $this->givenName = $data->givenName;
300
            unset($data->givenName);
301
        }
302
        if(isset($data->sn))
303
        {
304
            $this->sn = $data->sn;
305
            unset($data->sn);
306
        }
307
        if(isset($data->cn))
308
        {
309
            $this->cn = $data->cn;
310
            unset($data->cn);
311
        }
312
    }
313
314
    private function checkForUnsettableElements($data)
315
    {
316
        $count = count($this->unsettableElements);
317
        for($i = 0; $i < $count; $i++)
318
        {
319
            $propName = $this->unsettableElements[$i];
320
            if(isset($data->{$propName}))
321
            {
322
                if($data{$propName} !== $this->{$propName})
323
                {
324
                    throw new \Exception('Unable to change '.$propName.'!');
325
                }
326
                unset($data->{$propName});
327
            }
328
        }
329
    }
330
331
    private function editAddressElements($data)
332
    {
333
        if(isset($data->postalAddress))
334
        {
335
            $this->postalAddress = $data->postalAddress;
336
            unset($data->postalAddress);
337
        }
338
        if(isset($data->l))
339
        {
340
            $this->l = $data->l;
341
            unset($data->l);
342
        }
343
        if(isset($data->st))
344
        {
345
            $this->st = $data->st;
346
            unset($data->st);
347
        }
348
        if(isset($data->postalCode))
349
        {
350
            $this->postalCode = $data->postalCode;
351
            unset($data->postalCode);
352
        }
353
        if(isset($data->c))
354
        {
355
            $this->c = $data->c;
356
            unset($data->c);
357
        }
358
    }
359
360
    private function editOrganizationElements($data)
361
    {
362
        if(isset($data->o))
363
        {
364
            $this->o = $data->o;
365
            unset($data->o);
366
        }
367
        if(isset($data->title))
368
        {
369
            $this->title = $data->title;
370
            unset($data->title);
371
        }
372
        if(isset($data->ou))
373
        {
374
            $this->ou = $data->ou;
375
            unset($data->ou);
376
        }
377
    }
378
379
    /**
380
     * Modify the user given the provided data object
381
     *
382
     * @param stdClass $data The user's new data
383
     *
384
     * @return boolean true if the user's data was changed, false otherwise
385
     */
386
    public function editUser($data)
387
    {
388
        $this->enableReadWrite();
389
390
        $this->checkForUnsettableElements($data);
391
        $this->editUserPassword($data);
392
        $this->editNames($data);
393
        $this->editAddressElements($data);
394
        $this->editOrganizationElements($data);
395
396
        if(isset($data->jpegPhoto))
397
        {
398
            $this->jpegPhoto = base64_decode($data->jpegPhoto);
399
            unset($data->jpegPhoto);
400
        }
401
        if(isset($data->mobile))
402
        {
403
            $this->mobile = $data->mobile;
404
            unset($data->mobile);
405
        }
406
    }
407
408
    /**
409
     * Obtain the user's password reset hash
410
     *
411
     * @return string|false A hash if available, false otherwise
412
     */
413
    public function getPasswordResetHash()
414
    {
415
        return false;
416
    }
417
418
    /**
419
     * Serialize the user data into a format usable by the json_encode method
420
     *
421
     * @return array A simple keyed array representing the user
422
     */
423
    public function jsonSerialize()
424
    {
425
        $user = array();
426
        $user['displayName'] = $this->displayName;
427
        $user['givenName'] = $this->givenName;
428
        $user['jpegPhoto'] = base64_encode($this->jpegPhoto);
429
        $user['mail'] = $this->mail;
430
        $user['mobile'] = $this->mobile;
431
        $user['uid'] = $this->uid;
432
        $user['o'] = $this->o;
433
        $user['title'] = $this->title;
434
        $user['titlenames'] = $this->getTitleNames();
435
        $user['st'] = $this->st;
436
        $user['l'] = $this->l;
437
        $user['sn'] = $this->sn;
438
        $user['cn'] = $this->cn;
439
        $user['postalAddress'] = $this->postalAddress;
440
        $user['postalCode'] = $this->postalCode;
441
        $user['c'] = $this->c;
442
        $user['ou'] = $this->ou;
443
        $user['host'] = $this->host;
444
        $user['class'] = get_class($this);
445
        return $user;
446
    }
447
448
    /**
449
     * Serialize the user data into a VCARD 2.1 format
450
     *
451
     * @return string The VCARD for the user
452
     */
453
    public function getVcard()
454
    {
455
        $ret = "BEGIN:VCARD\nVERSION:2.1\n";
456
        $ret .= 'N:'.$this->sn.';'.$this->givenName."\n";
457
        $ret .= 'FN:'.$this->givenName."\n";
458
        $titles = $this->title;
459
        if($titles !== false)
460
        {
461
            $ret .= 'TITLE:'.implode(',', $titles)."\n";
462
        }
463
        $ret .= "ORG: Austin Artistic Reconstruction\n";
464
        $ret .= 'TEL;TYPE=MOBILE,VOICE:'.$this->mobile."\n";
465
        $ret .= 'EMAIL;TYPE=PREF,INTERNET:'.$this->mail."\n";
466
        $ret .= "END:VCARD\n";
467
        return $ret;
468
    }
469
}
470
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
471