Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
user.inc
1 <?php
18 require_once SQ_INCLUDE_PATH.'/asset.inc';
19 require_once SQ_INCLUDE_PATH.'/general_occasional.inc';
20 require_once SQ_INCLUDE_PATH.'/password_rules_config.inc';
21 
37 class User extends Asset
38 {
39 
40 
46  function User($assetid=0)
47  {
48  $this->_ser_attrs = TRUE;
49  $this->Asset($assetid);
50 
51  }//end constructor
52 
53 
64  protected function _preCreateCheck(Array &$link)
65  {
66  if (!parent::_preCreateCheck($link)) return FALSE;
67 
68  if(SQ_CONF_FORCE_LOWERCASE_USERNAME && in_array(get_class($this), Array('User', 'Simple_Edit_User', 'Backend_User', 'System_User')))
69  $this->setAttrValue('username', strtolower($this->attr('username')));
70 
71  $username = trim($this->attr('username'));
72  $password = $this->attr('password');
73 
74  if (!$this->_catchBlankUserNamePass($username, $password)) {
75  if (!array_get_index($this->_tmp, 'username_set') || !array_get_index($this->_tmp, 'password_set')) {
76  // in this case they have tried to create without even trying to set the username or password, so
77  // we error here. Otherwise errors have already been thrown so we don't throw them now.
78  trigger_localised_error('CORE0084', E_USER_WARNING, $GLOBALS['SQ_SYSTEM']->am->getTypeInfo($this->type(), 'name'));
79  }
80  return FALSE;
81  }
82 
83  return TRUE;
84 
85  }//end _preCreateCheck()
86 
87 
98  protected function _createAdditional(Array &$link)
99  {
100  if (!parent::_createAdditional($link)) return FALSE;
101 
102  if (!$this->makeAndSaveInitialWebPath(strtolower($this->attr('username')), $link)) {
103  trigger_localised_error('CORE0019', E_USER_WARNING, $this->name);
104  return FALSE;
105  }
106 
107  // Ensure that the current user can perform the following permissions change regardless of their own permissions on the parent
108  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
109 
110  // give the user admin access to him/herself
111  if (!$GLOBALS['SQ_SYSTEM']->am->setPermission($this->id, $this->id, SQ_PERMISSION_ADMIN, TRUE)) {
112  trigger_localised_error('CORE0015', E_USER_WARNING, $this->name);
113  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
114 
115  return FALSE;
116  }
117 
118  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
119 
120  $user_link = Array('asset' => &$this, 'link_type' => SQ_LINK_TYPE_2, 'is_dependant' => 1, 'is_exclusive' => 1);
121 
122  // create an inbox
123  $GLOBALS['SQ_SYSTEM']->am->includeAsset('inbox');
124  $inbox = new Inbox();
125  if (!$inbox->create($user_link)) return FALSE;
126 
127  // create a workspace
128  $GLOBALS['SQ_SYSTEM']->am->includeAsset('workspace');
129  $workspace = new Workspace();
130  $workspace->setAttrValue('name', 'Workspace');
131  if (!$workspace->create($user_link)) return FALSE;
132 
133  return TRUE;
134 
135  }//end _createAdditional()
136 
137 
144  function reload()
145  {
146  parent::reload();
147  unset($_SESSION['sq_user_groups'][$this->id]);
148 
149  }//end reload()
150 
151 
159  public function _getAllowedLinks()
160  {
161  $allowed = parent::_getAllowedLinks();
162  // Allow any type of asset to be linked underneath
163  $allowed[SQ_LINK_TYPE_1]['asset'] = Array('card' => 'M', 'exclusive' => FALSE);
164  $allowed[SQ_LINK_TYPE_2]['asset'] = Array('card' => 'M', 'exclusive' => FALSE);
165  $allowed[SQ_LINK_TYPE_3]['asset'] = Array('card' => 'M', 'exclusive' => FALSE);
166  $allowed[SQ_LINK_NOTICE]['asset'] = Array('card' => 'M', 'exclusive' => FALSE);
167 
168  // Restrict the inbox and workspace to exclusive links
169  $allowed[SQ_LINK_TYPE_2]['inbox'] = Array('card' => 1, 'exclusive' => TRUE);
170  $allowed[SQ_LINK_TYPE_2]['workspace'] = Array('card' => 1, 'exclusive' => TRUE);
171  return $allowed;
172 
173  }//end _getAllowedLinks()
174 
175 
188  function setAttrValue($name, $value)
189  {
190  // if this is the password, encrypt it
191  if ($name == 'password') {
192  $this->_tmp['password_set'] = TRUE; // so we know at create time whether to throw an extra error
193  if ($GLOBALS['SQ_SYSTEM']->runLevelEnables(SQ_SECURITY_PASSWORD_VALIDATION)) {
194  if (!$this->validatePassword($value)) return FALSE;
195  }
196  // Make sure password doesn't get re-hashed while reverting to system version
197  $value = $GLOBALS['SQ_REVERT_TO_SYSTEM_VERSION'] ? $value : crypt($value); // let salt be generated
198  } else if ($name == 'username') {
199  $this->_tmp['username_set'] = TRUE; // so we know at create time whether to throw an extra error
200  if (!$this->_catchBlankSetUserName(trim($value))) {
201  trigger_localised_error('CORE0110', E_USER_WARNING);
202  return FALSE;
203  }
204 
205  if(SQ_CONF_FORCE_LOWERCASE_USERNAME && in_array(get_class($this), Array('User', 'Simple_Edit_User', 'Backend_User', 'System_User')))
206  $value = strtolower($value);
207  }
208 
209  if (!parent::setAttrValue($name, $value)) return FALSE;
210 
211  // tell the workspace (or anyone else listening) that the username has been updated
212  if ($name == 'username') {
213  $em = $GLOBALS['SQ_SYSTEM']->getEventManager();
214  $em->broadcastEvent($this, 'usernameUpdated', Array('username' => $value));
215  }
216  return TRUE;
217 
218  }//end setAttrValue()
219 
220 
230  function processStatusChange($new_status, $update_parents=TRUE)
231  {
232  // Get the assetid of the root user sucka!
233  $root_user = $GLOBALS['SQ_SYSTEM']->am->getSystemAssetid('root_user');
234 
235  // Do not do this procedure if root user or a shadow asset (LDAP user etc.)
236  if ($this->id != $root_user && strpos($this->id, ':') === FALSE) {
237  // Ok to proceed
238  switch ($new_status) {
239  case SQ_STATUS_UNDER_CONSTRUCTION:
240  // If the current status is archived, try putting in the unique value again
241  if ($this->status == SQ_STATUS_ARCHIVED) {
242  // Connect four!
243  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
244  $db = MatrixDAL::getDb();
245  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
246 
247  // Get the attribute id
248  try {
249  $sql = 'SELECT oa.attrid as owning_attrid, a.attrid as attrid FROM sq_ast_attr a INNER JOIN sq_ast_attr oa ON (a.owning_type_code = oa.type_code AND a.name = oa.name) WHERE a.name = :name AND a.type_code = :type_code';
250  $query = MatrixDAL::preparePdoQuery($sql);
251  MatrixDAL::bindValueToPdo($query, 'name', 'username');
252  MatrixDAL::bindValueToPdo($query, 'type_code', $this->type());
253  $attributes = MatrixDAL::executePdoAssoc($query);
254  } catch (Exception $e) {
255  throw new Exception('Cannot check for attribute value "'.$this->name.'" of type code "'.$this->type().'" due to database error: '.$e->getMessage());
256  return FALSE;
257  }
258 
259  // Set the attributes
260  $owning_attributeid = $attributes[0]['owning_attrid'];
261  $attributeid = $attributes[0]['attrid'];
262 
263  // If username attribute already set in db, no need to do anything here #3994
264  if ($this->_uniqueAttributeExists($owning_attributeid, $this->id)) {
265  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
266  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
267  break;
268  }
269 
270  // Check if another user has the same username
271  $name = $this->getValidUsername($owning_attributeid, $this->attr('username'));
272 
273  // Name has changed better change it
274  if ($name != $this->attr('username')) {
275  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
276  $this->setAttrValue('username', $name);
277  $this->saveAttributes();
278  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
279  }//end if
280 
281  // Ok to contine, add the unique value back into the database
282  try {
283  $prepared = MatrixDAL::preparePdoQuery('INSERT INTO sq_ast_attr_uniq_val (custom_val, owning_attrid, assetid) VALUES (:custom_val, :owning_attrid, :assetid)');
284  MatrixDAL::bindValueToPdo($prepared, 'custom_val', $name);
285  MatrixDAL::bindValueToPdo($prepared, 'owning_attrid', $owning_attributeid);
286  MatrixDAL::bindValueToPdo($prepared, 'assetid', $this->id);
287  MatrixDAL::execPdoQuery($prepared);
288  } catch (Exception $e) {
289  throw new Exception('Unable to add the unique attribute value for asset "'.$this->name.'" (#'.$this->id.') due to database error: '.$e->getMessage());
290  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
291  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
292  return FALSE;
293  }
294 
295  // Everything ok here save changes
296  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
297  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
298  }//end if
299  break;
300  case SQ_STATUS_ARCHIVED:
301  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
302  $db = MatrixDAL::getDb();
303  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
304  try {
305  $prepared = MatrixDAL::preparePdoQuery('DELETE FROM sq_ast_attr_uniq_val WHERE custom_val=:custom_val AND assetid=:assetid');
306  MatrixDAL::bindValueToPdo($prepared, 'custom_val', $this->attr('username'));
307  MatrixDAL::bindValueToPdo($prepared, 'assetid', $this->id);
308  MatrixDAL::execPdoQuery($prepared);
309  } catch (Exception $e) {
310  throw new Exception('Unable to delete unique attribute value for asset "'.$this->name.'" (#'.$this->id.') due to database error: '.$e->getMessage());
311  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
312  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
313  return FALSE;
314  }
315  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
316  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
317  break;
318  }//end switch
319  }//end if
320 
321  return parent::processStatusChange($new_status, $update_parents);
322 
323  }//end processStatusChange()
324 
325 
334  function comparePassword($entered_password)
335  {
336  $password = $this->attr('password');
337 
338  if (!trim($password)) return FALSE;
339 
340  return (crypt($entered_password,$password) == $password);
341 
342  }//end comparePassword()
343 
344 
354  function getValidUsername($owning_attrid, $current_username)
355  {
356  $valid_username = $current_username;
357  $found_one = FALSE;
358  while (!$found_one) {
359  $current_values = Array();
360  try {
361  $prepared = MatrixDAL::preparePdoQuery('SELECT custom_val FROM sq_ast_attr_uniq_val WHERE owning_attrid=:owning_attrid AND custom_val LIKE :custom_val');
362  MatrixDAL::bindValueToPdo($prepared, 'custom_val', $valid_username);
363  MatrixDAL::bindValueToPdo($prepared, 'owning_attrid', $owning_attrid);
364  $current_values = MatrixDAL::executePdoAssoc($prepared);
365  } catch (Exception $e) {
366  throw new Exception('Unable to open database due to database error: '.$e->getMessage());
367  return FALSE;
368  }
369 
370  if (empty($current_values)) {
371  $found_one = TRUE;
372  } else {
373  require_once SQ_FUDGE_PATH.'/general/file_system.inc';
374  $valid_username = increment_filename($valid_username);
375  }//end if
376  }//end while
377 
378  return $valid_username;
379 
380  }//end getValidUsername()
381 
382 
392  function validatePassword($passwd, $add_system_message=FALSE)
393  {
394  $config = new Password_Rules_Config();
395  require_once $config->config_file;
396 
397  // one rule that is always in effect:
398  if ($passwd === '') {
399  if ($add_system_message) {
400  $GLOBALS['SQ_SYSTEM']->addMessage($$GLOBALS['SQ_SYSTEM']->getErrorMessage('CORE0247'));
401  } else {
402  trigger_localised_error('CORE0247', E_USER_NOTICE);
403  }
404  $this->_tmp['password_validation_error'] = TRUE;
405  return FALSE;
406  }
407 
408  $errors = Array();
409 
410  // errors for when a character type does not occur in the password
411  $not_occurring_error_map = Array(
412  'SQ_PASSWD_RULE_NUM_CAPS' => 'CORE0222',
413  'SQ_PASSWD_RULE_NUM_LOWER' => 'CORE0223',
414  'SQ_PASSWD_RULE_NUM_INT' => 'CORE0224',
415  'SQ_PASSWD_RULE_NUM_PUNC' => 'CORE0225',
416  'SQ_PASSWD_RULE_NUM_SPC' => 'CORE0226',
417  );
418 
419  // errors for when a character type incorrectly occurs in the password
420  $occurring_error_map = Array(
421  'SQ_PASSWD_RULE_NUM_CAPS' => 'CORE0227',
422  'SQ_PASSWD_RULE_NUM_LOWER' => 'CORE0228',
423  'SQ_PASSWD_RULE_NUM_INT' => 'CORE0229',
424  'SQ_PASSWD_RULE_NUM_PUNC' => 'CORE0230',
425  'SQ_PASSWD_RULE_NUM_SPC' => 'CORE0231',
426  );
427 
428  if (defined('SQ_PASSWD_RULE_LENGTH') && SQ_PASSWD_RULE_LENGTH > -1) {
429  if (strlen($passwd) < SQ_PASSWD_RULE_LENGTH) {
430  $errors[] = Array('CORE0220', strlen($passwd), SQ_PASSWD_RULE_LENGTH);
431  }
432  }
433 
434  if (defined('SQ_PASSWD_RULE_DISALLOW_USER_INFO') && SQ_PASSWD_RULE_DISALLOW_USER_INFO == 0) {
435  $components = Array('username', 'first_name', 'last_name', 'email');
436  foreach ($components as $component) {
437  $attr = $this->attr($component);
438  if (!empty($attr) && preg_match('/.*'.$this->attr($component).'.*/i', $passwd)) {
439  $errors[] = Array('CORE0221');
440  break;
441  }
442  }
443  }
444 
445  $charlist = count_chars($passwd, 1);
446  $num_rules = get_constant_values('SQ_PASSWD_RULE_NUM_');
447 
448  foreach ($num_rules as $rule => $value) {
449  eval('$'.$rule.'_counter = 0;');
450  if ($value != SQ_PASSWD_RULE_DISABLED) {
451  foreach ($charlist as $char => $occurances) {
452  switch ($rule) {
453  case 'SQ_PASSWD_RULE_NUM_CAPS':
454  if (ctype_upper($char)) {
455  eval('$'.$rule.'_counter += $occurances;');
456  }
457  break;
458 
459  case 'SQ_PASSWD_RULE_NUM_LOWER':
460  if (ctype_lower($char)) {
461  eval('$'.$rule.'_counter += $occurances;');
462  }
463  break;
464 
465  case 'SQ_PASSWD_RULE_NUM_INT':
466  if (ctype_digit($char)) {
467  eval('$'.$rule.'_counter += $occurances;');
468  }
469  break;
470 
471  case 'SQ_PASSWD_RULE_NUM_PUNC':
472  if (ctype_punct($char)) {
473  eval('$'.$rule.'_counter += $occurances;');
474  }
475  break;
476 
477  case 'SQ_PASSWD_RULE_NUM_SPC':
478  if (ctype_space($char)) {
479  eval('$'.$rule.'_counter += $occurances;');
480  }
481  break;
482  }//end switch on rule
483  }//end foreach character
484  }//end if password rule enabled
485  }//end foreach rule
486 
487  foreach ($num_rules as $rule => $value) {
488  if ($value != SQ_PASSWD_RULE_DISABLED) {
489  eval('$tmp_counter = $'.$rule.'_counter;');
490  if ($value == SQ_PASSWD_RULE_DISALLOWED && $tmp_counter > 0) {
491  if (isset($occurring_error_map[$rule])) {
492  $errors[] = Array($occurring_error_map[$rule]);
493  }
494  } else if ($tmp_counter < $value) {
495  if (isset($not_occurring_error_map[$rule])) {
496  $errors[] = Array($not_occurring_error_map[$rule], $tmp_counter, $value);
497  }
498  }
499  }
500  }
501 
502  // check if this password contains blacklisted word
503  $blacklist = SQ_PASSWD_RULE_BLACK_LIST;
504  if (!empty($blacklist)) {
505  $blacklist = str_replace("\r\n","\n", $blacklist);
506  $blacklist = str_replace("\r","\n", $blacklist);
507  $blacklist = explode("\n", $blacklist);
508  foreach ($blacklist as $word) {
509  if ((!SQ_PASSWD_RULE_BLACK_LIST_EXACT && preg_match('/'.$word.'/', $passwd)) || (SQ_PASSWD_RULE_BLACK_LIST_EXACT && (strcmp($passwd, $word) == 0))) {
510  $errors[] = Array('CORE0260');
511  }
512  }
513  }
514 
515  if ($add_system_message) {
516  $msgs = '';
517  foreach ($errors as $error) {
518  $code = array_shift($error);
519  $bit = $GLOBALS['SQ_SYSTEM']->lm->getErrorMessage($code, $error);
520  $bit = preg_replace('/\[([^\]]*)\]$/', '', $bit); // remove error code
521  $msgs .= '<li>'.$bit.'</li>';
522  }
523  if (!empty($errors)) {
524  $GLOBALS['SQ_SYSTEM']->addMessage(translate('password_validation_error', '<ul>'.$msgs.'</ul>'));
525  }
526  } else {
527  foreach ($errors as $error) {
528  $code = array_shift($error);
529  $GLOBALS['SQ_SYSTEM']->lm->raiseError($code, E_USER_WARNING, $error);
530  }
531  }
532 
533  return empty($errors);
534 
535  }//end validatePassword()
536 
537 
545  {
546  include_once SQ_DATA_PATH.'/private/conf/password_rules.inc';
547  $res = Array();
548  if (SQ_PASSWD_RULE_LENGTH > 0) {
549  $res[] = translate('password_rules_min_length', SQ_PASSWD_RULE_LENGTH);
550  }
551  if (SQ_PASSWD_RULE_DISALLOW_USER_INFO == 0) {
552  // yes this was built the wrong way around
553  $res[] = translate('password_rules_user_info_prohibited');
554  }
555 
556  if (SQ_PASSWD_RULE_NUM_CAPS > 1) {
557  $res[] = translate('password_rules_at_least', SQ_PASSWD_RULE_NUM_CAPS, translate('capital_letters'));
558  }
559  if (SQ_PASSWD_RULE_NUM_LOWER > 1) {
560  $res[] = translate('password_rules_at_least', SQ_PASSWD_RULE_NUM_LOWER, translate('lowercase_letters'));
561  }
562  if (SQ_PASSWD_RULE_NUM_INT > 1) {
563  $res[] = translate('password_rules_at_least', SQ_PASSWD_RULE_NUM_INT, translate('numeric_digits'));
564  }
565  if (SQ_PASSWD_RULE_NUM_PUNC > 1) {
566  $res[] = translate('password_rules_at_least', SQ_PASSWD_RULE_NUM_PUNC, translate('punctuation_characters'));
567  }
568  if (SQ_PASSWD_RULE_NUM_SPC > 1) {
569  $res[] = translate('password_rules_at_least', SQ_PASSWD_RULE_NUM_SPC, translate('spaces'));
570  }
571 
572  if (SQ_PASSWD_RULE_NUM_CAPS == 1) {
573  $res[] = translate('password_rules_at_least', translate('one'), translate('capital_letter'));
574  }
575  if (SQ_PASSWD_RULE_NUM_LOWER == 1) {
576  $res[] = translate('password_rules_at_least', translate('one'), translate('lowercase_letter'));
577  }
578  if (SQ_PASSWD_RULE_NUM_INT == 1) {
579  $res[] = translate('password_rules_at_least', translate('one'), translate('numeric_digit'));
580  }
581  if (SQ_PASSWD_RULE_NUM_PUNC == 1) {
582  $res[] = translate('password_rules_at_least', translate('one'), translate('punctuation_character'));
583  }
584  if (SQ_PASSWD_RULE_NUM_SPC == 1) {
585  $res[] = translate('password_rules_at_least', translate('one'), translate('space'));
586  }
587 
588  $disallowed_chars = Array();
589  if (SQ_PASSWD_RULE_NUM_CAPS == -1) {
590  $disallowed_chars[] = translate('capital_letters');
591  }
592  if (SQ_PASSWD_RULE_NUM_LOWER == -1) {
593  $disallowed_chars[] = translate('lowercase_letters');
594  }
595  if (SQ_PASSWD_RULE_NUM_INT == -1) {
596  $disallowed_chars[] = translate('numeric_digits');
597  }
598  if (SQ_PASSWD_RULE_NUM_PUNC == -1) {
599  $disallowed_chars[] = translate('punctuation_characters');
600  }
601  if (SQ_PASSWD_RULE_NUM_SPC == -1) {
602  $disallowed_chars[] = translate('spaces');
603  }
604  if (!empty($disallowed_chars)) {
605  include_once SQ_FUDGE_PATH.'/general/text.inc';
606  $res[] = ucfirst(translate('password_rules_not_allowed', make_readable_list($disallowed_chars, strtolower(translate('and')))));
607  }
608 
609  if (trim(SQ_PASSWD_RULE_BLACK_LIST) != '') {
610  $black_words = Array();
611  foreach (explode("\n", SQ_PASSWD_RULE_BLACK_LIST) as $word) {
612  $black_words[] = '"'.trim($word).'"';
613  }
614  if (!empty($black_words)) {
615  if (SQ_PASSWD_RULE_BLACK_LIST_EXACT) {
616  $res[] = translate('password_rules_blacklist_strict', implode(', ', $black_words));
617  } else {
618  $res[] = translate('password_rules_blacklist_loose', implode(', ', $black_words));
619  }
620  }
621  }
622 
623  if (!empty($res)) {
624  return translate('password_rules_intro').'<ul class="password-rules"><li>'.implode('</li><li>', $res).'</li></ul>';
625  }
626  return '';
627 
628  }//end getPasswordRulesDescription()
629 
630 
640  public function _getName($short_name=FALSE)
641  {
642  return ($this->attr('first_name') || $this->attr('last_name')) ? $this->attr('first_name').' '.$this->attr('last_name') : $this->attr('username');
643 
644  }//end _getName()
645 
646 
659  public function _checkPermissionAccess($perm, $assetids=Array(), $only_workflow=TRUE)
660  {
661  if (empty($assetids)) {
662  // root can do anything
663  if ($GLOBALS['SQ_SYSTEM']->userRoot()) return TRUE;
664 
665  if ($GLOBALS['SQ_SYSTEM']->userRoot($this)) {
666  // we have to be root to view root's details
667  return FALSE;
668  } else if ($GLOBALS['SQ_SYSTEM']->userSystemAdmin($this)) {
669  // this is a sysadmin so they need to
670  // be root or the sysadmin themselves
671  if (!$GLOBALS['SQ_SYSTEM']->userSystemAdmin()) {
672  return FALSE;
673  }
674  if ($this->id == $GLOBALS['SQ_SYSTEM']->currentUserId()) {
675  return TRUE;
676  }
677  return FALSE;
678  } else {
679  // any other user's details
680  if ($GLOBALS['SQ_SYSTEM']->userSystemAdmin()) {
681  return TRUE;
682  }
683  if ($this->id == $GLOBALS['SQ_SYSTEM']->currentUserId()) {
684  return TRUE;
685  }
686  }
687 
688  } else {
689  // a user always has full access to themselves
690  if (in_array($this->id, $assetids)) return TRUE;
691 
692  }
693 
694  return parent::_checkPermissionAccess($perm, $assetids);
695 
696  }//end _checkPermissionAccess()
697 
698 
707  function isDeletableLink($linkid)
708  {
709  if ($GLOBALS['SQ_PURGING_TRASH']) return TRUE;
710 
711  // we dont want our inbox or workspace deleted
712  $inbox_link = $this->getInboxLink();
713  if (!empty($inbox_link) && ($inbox_link['linkid'] == $linkid)) {
714  return translate('cannot_delete_inbox-user_link');
715  }
716 
717  $workspace_link = $this->getWorkspaceLink();
718  if (!empty($workspace_link) && ($workspace_link['linkid'] == $linkid)) {
719  return translate('cannot_delete_workspace-user_link');
720  }
721 
722  return parent::isDeletableLink($linkid);
723 
724  }//end isDeletableLink()
725 
726 
734  function canLogin()
735  {
736  // check that this user is live
737  if ($this->status & SQ_SC_STATUS_NOT_LIVE) {
738  return FALSE;
739  }
740 
741  // check that this user is not only in the trash
742  if ($GLOBALS['SQ_SYSTEM']->am->assetInTrash($this->id, TRUE)) {
743  return FALSE;
744  }
745 
746  return TRUE;
747 
748  }//end canLogin()
749 
750 
760  function canAccessBackend()
761  {
762  return FALSE;
763 
764  }//end canAccessBackend()
765 
766 
774  {
775  return $this->canLogin();
776 
777  }//end canSetAsCurrentUser()
778 
779 
789  function getGroups()
790  {
791  if (!isset($_SESSION['sq_user_groups'][$this->id])) {
792  // we store userid as key in this array to make sure we have the right user,
793  // but to avoid invalidity we clear any other userids out
794  $fetch_roles = ((SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1' || SQ_CONF_ENABLE_ROLES_WF_SYSTEM == '1') && (SQ_CONF_ENABLE_GLOBAL_ROLES == '1'));
795  $group_types = Array('user', 'user_group', 'system_user_group');
796  if ($fetch_roles) $group_types[] = 'role';
797  $_SESSION['sq_user_groups'] = Array($this->id => $GLOBALS['SQ_SYSTEM']->am->getParents($this->id, $group_types, TRUE));
798  }
799  return $_SESSION['sq_user_groups'][$this->id];
800 
801  }//end getGroups()
802 
803 
812  function getUserGroups()
813  {
814  // cache the result so that we dont do this more than once in an execution
815  if (!isset($_SESSION['sq_effective_user_groups'][$this->id])) {
816  $_SESSION['sq_effective_user_groups'][$this->id] = Array();
817  $fetch_roles = ((SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1' || SQ_CONF_ENABLE_ROLES_WF_SYSTEM == '1') && (SQ_CONF_ENABLE_GLOBAL_ROLES == '1'));
818  $groupids = $GLOBALS['SQ_SYSTEM']->am->getParents($this->id, 'user_group', FALSE);
819  foreach ($groupids as $groupid => $type_code) {
820  // if we pass the conditions, let us belong to this group
821  // EXCEPT if this is a role, and roles are disabled
822  if (!(($type_code == 'role') && !$fetch_roles)) {
823  if ($this->_belongsToGroup($groupid)) {
824  $_SESSION['sq_effective_user_groups'][$this->id][] = $groupid;
825  }
826  }
827  }
828  }
829  return $_SESSION['sq_effective_user_groups'][$this->id];
830 
831  }//end getUserGroups()
832 
833 
845  function _belongsToGroup($group_assetid)
846  {
847  $restrictions = $this->attr('restrictions');
848 
849  // if this group isnt in the restrictions array
850  // then we just belong to it and so return
851  if (!in_array($group_assetid, array_keys($restrictions))) {
852  return TRUE;
853  }
854 
855  // for each restriction associated to this group
856  foreach ($restrictions[$group_assetid] as $restriction) {
857 
858  // grab the condition name, make an object
859  $condition_type_code = $restriction['name'];
860  $GLOBALS['SQ_SYSTEM']->am->includeAsset($condition_type_code);
861  $condition = new $condition_type_code();
862 
863  $match = $condition->evaluate($this, $restriction['condition_data']);
864 
865  // they don't match up, so not in this group
866  if ($match != $restriction['match']) return FALSE;
867 
868  }
869 
870  // if we got this far, we've passed all restrictions
871  return TRUE;
872 
873  }//end _belongsToGroup()
874 
875 
882  function getInboxLink()
883  {
884  return $GLOBALS['SQ_SYSTEM']->am->getLink($this->id, SQ_LINK_TYPE_2, 'inbox');
885 
886  }//end getInboxLink()
887 
888 
895  function getWorkspaceLink()
896  {
897  return $GLOBALS['SQ_SYSTEM']->am->getLink($this->id, SQ_LINK_TYPE_2, 'workspace');
898 
899  }//end getWorkspaceLink()
900 
901 
908  function &getWorkspace()
909  {
910  $null = NULL;
911  $link = $this->getWorkspaceLink();
912 
913  if (empty($link)) {
914  trigger_localised_error('CORE0109', E_USER_WARNING,$this->name);
915  return $null;
916  }
917 
918  $workspace = $GLOBALS['SQ_SYSTEM']->am->getAsset($link['minorid']);
919  if (is_null($workspace)) {
920  trigger_localised_error('CORE0109', E_USER_WARNING,$this->name);
921  return $null;
922  }
923  return $workspace;
924 
925  }//end getWorkspace()
926 
927 
934  function printBody()
935  {
936  ?>
937  <table border="0" cellspacing="2" cellpadding="2">
938  <tr>
939  <td><b>Username</b></td>
940  <td><?php echo $this->attr('username'); ?></td>
941  </tr>
942  <tr>
943  <td><b>First Name</b></td>
944  <td><?php echo $this->attr('first_name'); ?></td>
945  </tr>
946  <tr>
947  <td><b>Last Name</b></td>
948  <td><?php echo $this->attr('last_name'); ?></td>
949  </tr>
950  <tr>
951  <td><b>Email</b></td>
952  <td><?php echo $this->attr('email'); ?></td>
953  </tr>
954  </table>
955  <?php
956 
957  }//end printBody()
958 
959 
971  protected function _catchBlankUserNamePass($username, $password)
972  {
973  return (($username != '') && ($password != ''));
974 
975  }//end _catchBlankUserNamePass()
976 
977 
988  protected function _catchBlankSetUserName($username)
989  {
990  if ($username === '') {
991  $this->_tmp['blank_username_caught'] = TRUE;
992  return FALSE;
993  }
994  return TRUE;
995 
996  }//end _catchBlankSetUserName()
997 
998 
1008  function getUserLocks()
1009  {
1010  $db = MatrixDAL::getDb();
1011  try {
1012  $class_name = 'locking_method_'.SQ_CONF_LOCKING_METHOD;
1013  $GLOBALS['SQ_SYSTEM']->am->includeAsset($class_name);
1014 
1015  if (eval('return '.$class_name.'::supportsGetActiveLocks();') === TRUE) {
1016  $result = eval('return '.$class_name.'::getActiveLocks($this->id);');
1017  } else {
1018  // Unable to get the list of active locks due to lack of support
1019  $result = FALSE;
1020  }
1021 
1022  } catch (Exception $e) {
1023  throw new Exception('Unable to get all locks for current user (userid #'.$this->id.'), '.$e->getMessage());
1024 
1025  }//end try catch
1026 
1027  return $result;
1028 
1029  }//end getUserLocks()
1030 
1031 
1038  function releaseUserLocks()
1039  {
1040  $am = $GLOBALS['SQ_SYSTEM']->am;
1041  $current_locks = $this->getUserLocks();
1042  foreach ($current_locks as $lock_data) {
1043  $GLOBALS['SQ_SYSTEM']->releaseLock($lock_data['lockid']);
1044  }
1045 
1046  }//end releaseUserLocks()
1047 
1048 
1055  public function getAvailableKeywords()
1056  {
1057 
1058  $keywords = parent::getAvailableKeywords();
1059  $keywords['asset_attribute_email_image'] = translate('user_email_image');
1060  // right now we have totaly of 56 keywords that are being returned by this function
1061  // if we have more keywords added later , assertion in will need to be changed for
1062  // unit_tests/by_file/core/assets/users/user/user.inc/test_get_user_locks.test
1063 
1064  return $keywords;
1065 
1066  }//end getAvailableKeywords()
1067 
1068 
1078  public function getKeywordReplacement($keyword)
1079  {
1080  $replacement = NULL;
1081 
1082  // Remove any modifiers from keyword
1083  $full_keyword = $keyword;
1084  $keyword = parse_keyword($keyword, $modifiers);
1085  $contextid = extract_context_modifier($modifiers);
1086 
1087  if ($contextid !== NULL) {
1088  // If we were able to extract a context ID to change to, and it's
1089  // different to our current one, then change and then reload a copy
1090  // of the asset in that context (as we would need to do anyway)
1091 
1092  if ((int)$contextid !== $GLOBALS['SQ_SYSTEM']->getContextId()) {
1093  $GLOBALS['SQ_SYSTEM']->changeContext($contextid);
1094  $contexted_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->id);
1095 
1096  // Get the keyword without any modifiers
1097  $replacement = $contexted_asset->getKeywordReplacement($keyword);
1098 
1099  // Then apply the ones we had remaining, then return it
1100  apply_keyword_modifiers($replacement, $modifiers, Array('assetid' => $contexted_asset->id));
1101 
1102  unset($contexted_asset);
1103  $GLOBALS['SQ_SYSTEM']->restoreContext();
1104  return $replacement;
1105 
1106  }//end if contextid is not the currently active context
1107 
1108  }//end if contextid is not NULL
1109 
1110 
1111  if ($keyword == 'asset_attribute_email_image') {
1112  $email = $this->attr('email');
1113  $email_image_link = '';
1114  if (!empty($email)) {
1115  $img_url = $_SERVER['PHP_SELF'].'?SQ_ACTION=attribute_image&id='.$this->id.'&attribute=email';
1116  $email_image_link = '<img id="email_'.$this->id.'" src="'.$img_url.'" />';
1117  }//end if
1118  $replacement = $email_image_link;
1119  }
1120 
1121  if ($replacement !== NULL) {
1122  if (count($modifiers) > 0) {
1123  apply_keyword_modifiers($replacement, $modifiers, Array('assetid' => $this->id));
1124  }
1125  } else {
1126  // Use full keyword, so that modifiers still get respected
1127  $replacement = parent::getKeywordReplacement($full_keyword);
1128  }
1129 
1130  return $replacement;
1131 
1132  }//end getKeywordReplacement()
1133 
1134 
1144  function _uniqueAttributeExists($owning_attrid, $assetid)
1145  {
1146 
1147  try {
1148  $prepared = MatrixDAL::preparePdoQuery('SELECT custom_val FROM sq_ast_attr_uniq_val WHERE owning_attrid=:owning_attrid AND assetid=:assetid');
1149  MatrixDAL::bindValueToPdo($prepared, 'assetid', $assetid);
1150  MatrixDAL::bindValueToPdo($prepared, 'owning_attrid', $owning_attrid);
1151  $current_values = MatrixDAL::executePdoAssoc($prepared);
1152  } catch (Exception $e) {
1153  throw new Exception('Unable to open database due to database error: '.$e->getMessage());
1154  return FALSE;
1155  }
1156 
1157  return (!empty($current_values));
1158  }//end _uniqueAttributeExists()
1159 
1160 }//end class
1161 
1162 ?>