Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.Account.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 /**
7  * Users Definition
8  *
9  * @author Anakeen
10  * @version $Id: Class.User.php,v 1.65 2008/08/11 14:14:14 marc Exp $
11  * @package FDL
12  * @subpackage CORE
13  */
14 /**
15  */
16 
17 include_once ('Class.DbObj.php');
18 include_once ('Class.QueryDb.php');
19 include_once ('Class.Log.php');
20 include_once ('Class.Application.php');
21 include_once ('Class.Group.php');
22 include_once ('WHAT/Lib.Common.php');
23 
24 define("GALL_ID", 2);
25 define("ANONYMOUS_ID", 3);
26 define("GADMIN_ID", 4);
27 /**
28  * Manage User, Group and Role account object
29  * @class Account
30  */
31 class Account extends DbObj
32 {
34  const GALL_ID = GALL_ID;
36  const ADMIN_ID = 1;
37 
38  const USER_TYPE = "U";
39  const GROUP_TYPE = "G";
40  const ROLE_TYPE = "R";
41 
42  var $fields = array(
43  "id",
44  "lastname",
45  "firstname",
46  "login",
47  "password",
48  "substitute",
49  "isgroup",
50  "accounttype",
51  "memberof",
52  "expires",
53  "passdelay",
54  "status",
55  "mail",
56  "fid"
57  );
58 
59  public $id;
60  public $lastname;
61  public $firstname;
62  public $login;
63  public $password;
64  /**
65  * @deprecated use accountType instead
66  * @var string
67  */
68  public $isgroup;
69  public $expires;
70  public $passdelay;
71  public $status;
72  public $mail;
73  public $fid;
74  public $memberof;
75  /**
76  * @var string U|G|R
77  */
78  public $accounttype;
79  /**
80  * @var int the substitute account identifier
81  */
82  public $substitute;
83  /**
84  * family identifier of user document default is IUSER/IGROUP
85  * @var string
86  */
87  public $famid;
88  /**
89  * @var string new password
90  */
91  public $password_new;
92  var $id_fields = array(
93  "id"
94  );
95 
96  var $dbtable = "users";
97 
98  var $order_by = "lastname, accounttype";
99 
100  var $fulltextfields = array(
101  "login",
102  "lastname",
103  "firstname"
104  );
105 
106  var $sqlcreate = "
107 create table users ( id int not null,
108  primary key (id),
109  lastname text,
110  firstname text,
111  login text not null,
112  password text not null,
113  isgroup char,
114  substitute int,
115  accounttype char,
116  memberof int[],
117  expires int,
118  passdelay int,
119  status char,
120  mail text,
121  fid int);
122 create index users_idx2 on users(lastname);
123 CREATE UNIQUE INDEX users_login on users (login);
124 create sequence seq_id_users start 10;";
125  /**
126  * affect account from login name
127  * @param string $login login
128  * @return bool true if ok
129  */
131  {
132  $login = mb_trim(mb_strtolower($login));
133 
134  $query = new QueryDb($this->dbaccess, "Account");
135  $query->AddQuery("login='" . pg_escape_string($login) . "'");
136 
137  $list = $query->Query(0, 0, "TABLE");
138  if ($query->nb > 0) {
139  $this->Affect($list[0]);
140  return true;
141  }
142  return false;
143  }
144  /**
145  * return substitute account
146  * return null if no susbtitute
147  * @return Account|null
148  */
149  public function getSubstitute()
150  {
151  if ($this->isAffected()) {
152  if ($this->substitute) {
153  return new Account($this->dbaccess, $this->substitute);
154  }
155  }
156  return null;
157  }
158  /**
159  * return incumbent ids account list (accounts which has this account as substitute)
160  * @param bool $returnSystemIds set to true to return system account id, false to return document user id
161  * @return int[]
162  */
163  public function getIncumbents($returnSystemIds = true)
164  {
165  $incumbents = array();
166  if ($this->isAffected()) {
167  $sql = sprintf("select %s from users where substitute=%d;", $returnSystemIds ? 'id' : 'fid', $this->id);
168  simpleQuery($this->dbaccess, $sql, $incumbents, true, false);
169  }
170  return $incumbents;
171  }
172  /**
173  * set substitute to this user
174  * this user become the incumbent of $substitute
175  * @param string $substitute login or user system id
176  * @return string error message (empty if not)
177  */
178  public function setSubstitute($substitute)
179  {
180  $err = '';
181  if (!$this->isAffected()) {
182  $err = sprintf(_("cannot set substitute account object not affected"));
183  }
184  if ($err) return $err;
185  if ($substitute) {
186  if (!(is_numeric($substitute))) {
187  $sql = sprintf("select id from users where login = '%s'", pg_escape_string($substitute));
188  simpleQuery($this->dbaccess, $sql, $substituteId, true, true);
189  if ($substituteId) $substitute = $substituteId;
190  else $err = sprintf(_("cannot set substitute %s login not found") , $substitute);
191  }
192  if ($err) return $err;
193  $sql = sprintf("select id from users where id = '%d'", $substitute);
194  simpleQuery($this->dbaccess, $sql, $substituteId, true, true);
195  if (!$substituteId) $err = sprintf(_("cannot set substitute %s id not found") , $substitute);
196  }
197  if ($err) return $err;
198  if ($substitute == $this->id) {
199  $err = sprintf(_("cannot substitute itself"));
200  }
201  if ($err) return $err;
202  $oldSubstitute = $this->substitute;
203  $this->substitute = $substitute;
204 
205  $err = $this->modify();
206  if (!$err) {
207  $u = new \Account($this->dbaccess, $this->substitute);
208  $u->updateMemberOf();
209  if ($oldSubstitute) {
210  $u->select($oldSubstitute);
211  $u->updateMemberOf();
212  }
213 
214  global $action;
215  if ($action->user->id == $u->id) $action->user->revert();
216  }
217  return $err;
218  }
219  /**
220  * affect account from its login
221  *
222  * @param string $login login
223  * @deprecated use setLoginName instead
224  * @return bool true if ok
225  */
226  function setLogin($login, $unused = '0')
227  {
228  return $this->setLoginName($login);
229  }
230  /**
231  * affect account from its document id
232  *
233  * @param int $fid
234  * @return bool true if ok
235  */
236  function setFid($fid)
237  {
238  $query = new QueryDb($this->dbaccess, "Account");
239  $query->AddQuery(sprintf("fid = %d", $fid));
240  $list = $query->Query(0, 0, "TABLE");
241  if ($query->nb != 0) {
242  $this->Affect($list[0]);
243  } else {
244  return false;
245  }
246  return true;
247  }
248 
249  function preInsert()
250  {
251  $err = '';
252  if ((!$this->login) && $this->accounttype == self::ROLE_TYPE) {
253  // compute auto role reference
254  $this->login = uniqid('role');
255  }
256 
257  if ($this->setloginName($this->login)) return _("this login exists");
258  if ($this->login == "") return _("login must not be empty");
259  $this->login = mb_strtolower($this->login);
260  if ($this->id == "") {
261  $res = pg_query($this->dbid, "select nextval ('seq_id_users')");
262  $arr = pg_fetch_array($res, 0);
263  $this->id = $arr["nextval"];
264  }
265 
266  if (($this->accounttype == self::GROUP_TYPE) || ($this->accounttype == self::ROLE_TYPE) || ($this->isgroup == "Y")) {
267  if ((!$this->accounttype) && ($this->isgroup == "Y")) $this->accounttype = self::GROUP_TYPE;
268  $this->password = '-'; // no passwd for group,role
269  if ($this->accounttype === self::GROUP_TYPE) {
270  $this->isgroup = "Y";
271  }
272  } else {
273  $this->isgroup = "N";
274  }
275  if (!$this->accounttype) {
276  $this->accounttype = self::USER_TYPE;
277  }
278 
279  if ($this->accounttype === self::USER_TYPE && !$this->status) {
280  $this->status = "A";
281  }
282  $this->login = mb_strtolower($this->login);
283 
284  if (isset($this->password_new) && ($this->password_new != "")) {
285  $this->computepass($this->password_new, $this->password);
286  if ($this->id == 1) {
287  $this->setSupervisorHtpasswd($this->password_new);
288  }
289  }
290  //expires and passdelay
291  $this->GetExpires();
292  return $err;
293  }
294 
295  function PostInsert()
296  {
297  //Add default group to user
298  $group = new group($this->dbaccess);
299  $group->iduser = $this->id;
300  $gid = Account::GALL_ID; //2 = default group
301  $group->idgroup = $gid;
302  // not added here it is added by freedom (generally)
303  // if (! $this->fid) $group->Add();
304  $err = $this->synchroAccountDocument();
305  return $err;
306  }
307 
308  function postUpdate()
309  {
310  return $this->synchroAccountDocument();
311  }
312 
313  function preUpdate()
314  {
315  if (isset($this->password_new) && ($this->password_new != "")) {
316 
317  $this->computepass($this->password_new, $this->password);
318  if ($this->id == 1) {
319  $this->setSupervisorHtpasswd($this->password_new);
320  }
321  }
322 
323  $this->login = mb_strtolower($this->login);
324  //expires and passdelay
325  $this->GetExpires();
326  }
327 
328  function postDelete()
329  {
330  include_once ("WHAT/Class.Session.php");
331  include_once ("FDL/Lib.Usercard.php");
332  $err = '';
333  $group = new Group($this->dbaccess, $this->id);
334  $ugroups = $group->groups;
335  // delete reference in group table
336  $sql = sprintf("delete from groups where iduser=%d or idgroup=%d", $this->id, $this->id);
337  simpleQuery($this->dbaccess, $sql);
338 
339  refreshGroups($ugroups, true);
340 
341  global $action;
342  $action->session->CloseUsers($this->id);
343 
344  return $err;
345  }
346  /**
347  * @deprecated use SearchAccount class instead
348  * @param string $login
349  * @param string $unused
350  * @param int $whatid
351  * @return bool
352  */
353  function CheckLogin($login, $unused, $whatid)
354  {
355  $query = new QueryDb($this->dbaccess, "Account");
356 
357  $query->basic_elem->sup_where = array(
358  "login='" . pg_escape_string($login) . "'"
359  );
360 
361  $list = $query->Query();
362  if ($query->nb == 0 or ($query->nb == 1 and $list[0]->id == $whatid)) {
363  return true;
364  } else {
365  return false;
366  }
367  }
368  /**
369  * return display name of a user
370  * @param int $uid user identifier
371  * @return string|null firstname and lastname or null if not found
372  */
373  static function getDisplayName($uid)
374  {
375  static $tdn = array();
376 
377  $uid = intval($uid);
378  if ($uid > 0) {
379  if (isset($tdn[$uid])) return $tdn[$uid];
380  $dbid = getDbId(getDbAccess());
381  $res = pg_query($dbid, "select firstname, lastname from users where id=$uid");
382  if (pg_num_rows($res) > 0) {
383  $arr = pg_fetch_array($res, 0);
384  if ($arr["firstname"]) $tdn[$uid] = $arr["firstname"] . ' ' . $arr["lastname"];
385  else $tdn[$uid] = $arr["lastname"];
386  return $tdn[$uid];
387  }
388  return null;
389  }
390  return null;
391  }
392  /**
393  * Same as ::getDisplayName but for current object
394  */
395  public function getAccountName()
396  {
397  return trim(sprintf("%s %s", $this->firstname, $this->lastname));
398  }
399  /**
400  * return system user identifier from user document reference
401  * @static
402  * @see getFidFromUid
403  * @param int $fid
404  * @return int
405  */
406  static function getUidFromFid($fid)
407  {
408  $uid = 0;
409  if ($fid) {
410  simpleQuery('', sprintf("select id from users where fid=%d", $fid) , $uid, true, true);
411  }
412  return $uid;
413  }
414  /**
415  * return user document reference from system user identifier
416  * @static
417  * @see getUidFromFid
418  * @param int $fid
419  * @return int
420  */
421  static function getFidFromUid($uid)
422  {
423  $fid = 0;
424  if ($uid) {
425  simpleQuery('', sprintf("select fid from users where id=%d", $uid) , $fid, true, true);
426  }
427  return $fid;
428  }
429  /**
430  * update user from IUSER document
431  * @deprecated replace by updateUser
432  * @param int $fid document id
433  * @param string $login login
434  */
435  function setUsers($fid, $lname, $fname, $expires, $passdelay, $login, $status, $pwd1, $pwd2, $unused = '', $extmail = '')
436  {
437  return $this->updateUser($fid, $lname, $fname, $expires, $passdelay, $login, $status, $pwd1, $pwd2, $extmail);
438  }
439  /**
440  * update user from IUSER document
441  * @param int $fid document id
442  * @param string $lname last name
443  * @param string $fname first name
444  * @param string $expires expiration date
445  * @param int $passdelay password delay
446  * @param string $login login
447  * @param string $status 'A' (Activate) , 'D' (Desactivated)
448  * @param string $pwd1 password one
449  * @param string $pwd2 password two
450  * @param string $extmail mail address
451  * @param array $roles
452  * @param int $substitute system substitute id
453  * @return string error message
454  */
455  function updateUser($fid, $lname, $fname, $expires, $passdelay, $login, $status, $pwd1, $pwd2, $extmail = '', array $roles = array(-1
456  ) , $substitute = - 1)
457  {
458  $this->lastname = $lname;
459  $this->firstname = $fname;
460  $this->status = $status;
461  if ($login != "") $this->login = $login;
462  //don't modify password in database even if force constraint
463  if ($pwd1 == $pwd2 and $pwd1 <> "") {
464  $this->password_new = $pwd2;
465  }
466 
467  if ($extmail != "") {
468  $this->mail = trim($extmail);
469  } else {
470  $this->mail = $this->getMail();
471  }
472  if ($expires > 0) $this->expires = $expires;
473  if ($passdelay > 0) $this->passdelay = $passdelay;
474  elseif ($passdelay == - 1) { // suppress expire date
475  $this->expires = 0;
476  $this->passdelay = 0;
477  }
478 
479  $this->fid = $fid;
480  if (!$this->isAffected()) {
481  $err = $this->Add();
482  } else {
483  $err = $this->Modify();
484  }
485  if ($roles != array(-1
486  )) {
487  $err.= $this->setRoles($roles);
488  } else {
489  $this->updateMemberOf();
490  }
491 
492  if ((!$err) && ($substitute > - 1)) {
493  $err = $this->setSubstitute($substitute);
494  }
495  return $err;
496  }
497  /**
498  * update user from FREEDOM IGROUP document
499  * @param int $fid document id
500  * @param string $gname group name
501  * @param string $login login
502  * @param array $roles system role ids
503  */
504  function setGroups($fid, $gname, $login, array $roles = array(-1
505  ))
506  {
507  if ($gname != "") $this->lastname = $gname;
508  if (($this->login == "") && ($login != "")) $this->login = $login;
509 
510  $this->mail = $this->getMail();
511  $this->fid = $fid;
512  if (!$this->isAffected()) {
513  $this->accounttype = self::GROUP_TYPE;
514  $err = $this->Add();
515  } else {
516  $err = $this->Modify();
517  }
518  if ($roles != array(-1
519  )) {
520  $err.= $this->setRoles($roles);
521  } else {
522  $this->updateMemberOf();
523  }
524  return $err;
525  }
526  /**
527  * revert values from database
528  */
529  public function revert()
530  {
531  if ($this->isAffected()) {
532  $this->select($this->id);
533  }
534  }
535  //Add and Update expires and passdelay for password
536  //Call in PreUpdate and PreInsert
537  function getExpires()
538  {
539  if (intval($this->passdelay) == 0) {
540  $this->expires = "0";
541  $this->passdelay = "0";
542  } // neither expire
543  else if (intval($this->expires) == 0) {
544  $this->expires = time() + $this->passdelay;
545  }
546  }
547 
548  function synchroAccountDocument()
549  {
550  $err = '';
552  if ($dbaccess == "") return _("no freedom DB access");
553  if ($this->fid <> "") {
554  include_once ("FDL/freedom_util.php");
555  /**
556  * @var \Dcp\Family\IUSER $iuser
557  */
558  $iuser = new_Doc($dbaccess, $this->fid);
559 
560  $err = $iuser->RefreshDocUser();
561  } //Update from what
562  else {
563  include_once ("FDL/Lib.Dir.php");
564  if ($this->famid != "") $fam = $this->famid;
565  elseif ($this->accounttype == self::GROUP_TYPE) $fam = "IGROUP";
566  elseif ($this->accounttype == self::ROLE_TYPE) $fam = "ROLE";
567  else $fam = "IUSER";;
568  $filter = array(
569  "us_whatid = '" . $this->id . "'"
570  );
571  $tdoc = internalGetDocCollection($dbaccess, 0, 0, "ALL", $filter, 1, "LIST", $fam);
572  if (count($tdoc) == 0) {
573  //Create a new doc IUSER
574 
575  /**
576  * @var \Dcp\Family\IUSER $iuser
577  */
578  $iuser = createDoc($dbaccess, $fam);
579  $iuser->SetValue("US_WHATID", $this->id);
580  $iuser->Add();
581  $this->fid = $iuser->id;
582  $this->modify(true, array(
583  'fid'
584  ) , true);
585  $err = $iuser->refreshDocUser();
586  } else {
587  /**
588  * @var \Dcp\Family\IUSER $iuser
589  */
590  $iuser = $tdoc[0];
591  $this->fid = $iuser->id;
592  $this->modify(true, array(
593  'fid'
594  ) , true);
595  $err = $iuser->RefreshDocUser();
596  }
597  }
598  return $err;
599  }
600  // --------------------------------------------------------------------
601  function computepass($pass, &$passk)
602  {
603  $salt = '';
604  $salt_space = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";
605  srand((double)microtime() * 1000000);
606  for ($i = 0; $i < 16; $i++) $salt.= $salt_space[rand(0, strlen($salt_space) - 1) ];
607  $passk = crypt($pass, "\$5\${$salt}");
608  $this->_deleteUserSessions();
609  }
610  /**
611  * @param string $pass clear password to test
612  * @return bool
613  */
614  function checkpassword($pass)
615  {
616  if ($this->accounttype != 'U') return false; // don't log in group or role
617  return ($this->checkpass($pass, $this->password));
618  }
619  // --------------------------------------------------------------------
620  function checkpass($pass, $passk)
621  {
622  if (substr($passk, 0, 3) != '$5$') {
623  /* Old DES crypted passwords => SSHA256 crypting*/
624  $salt = substr($passk, 0, 2);
625  $passres = crypt($pass, $salt);
626  if ($passres == $passk) {
627  $this->computepass($pass, $this->password);
628  $err = $this->modify(true, array(
629  'password'
630  ) , true);
631  if ($err == '') {
632  if ($this->id == 1) $this->setSupervisorHtpasswd($pass);
633  $log = new Log("", "Session", "Authentication");
634  $facility = constant(getParam("AUTHENT_LOGFACILITY", "LOG_AUTH"));
635  $log->wlog("S", sprintf('User %s password crypted with salted SHA256 algorithm.', $this->login) , NULL, $facility);
636  }
637  }
638  } else {
639  $salt = substr($passk, 3, 19);
640  $passres = crypt($pass, "\$5\${$salt}");
641  }
642  return ($passres == $passk);
643  }
644  /**
645  * return mail adress
646  * @param bool $rawmail set to false to have long mail with firstname and lastname
647  * @return string mail address empty if no mail
648  */
649  function getMail($rawmail = true)
650  {
651  if ($this->accounttype == 'U') {
652  if (!$this->mail) return '';
653  if ($rawmail) {
654  return $this->mail;
655  } else {
656  $dn = trim($this->firstname . ' ' . $this->lastname);
657  $mail = sprintf('"%s" <%s>', str_replace('"', '-', $dn) , $this->mail);
658  return $mail;
659  }
660  } else {
661  $sql = sprintf("with recursive amembers(uid) as (
662  select iduser, users.login, users.mail from groups,users where idgroup = %d and users.id=groups.iduser
663 union
664  select iduser, users.login, users.mail from groups,users, amembers where groups.idgroup = amembers.uid and users.id=groups.iduser
665 ) select users.firstname, users.lastname, users.mail from amembers, users where users.id=amembers.uid and users.accounttype='U' and users.mail is not null order by users.mail;", $this->id);
666  simpleQuery($this->dbaccess, $sql, $umail);
667  $tMail = array();
668  if ($rawmail) {
669  foreach ($umail as $aMail) {
670 
671  $tMail[] = $aMail["mail"];
672  }
673  $tMail = array_unique($tMail);
674  } else {
675  foreach ($umail as $aMail) {
676  $dn = trim($aMail["firstname"] . ' ' . $aMail["lastname"]);
677  $tMail[] = sprintf('"%s" <%s>', str_replace('"', '-', $dn) , $aMail["mail"]);
678  }
679  }
680  return implode(', ', $tMail);
681  }
682  }
683 
684  function PostInit()
685  {
686  $group = new group($this->dbaccess);
687 
688  $userAdmin=new Account($this->dbaccess);
689  // Create admin user
690  $userAdmin->id = Account::ADMIN_ID;
691  $userAdmin->lastname = "Master";
692  $userAdmin->firstname = "Dynacase Platform";
693  $userAdmin->password_new = "anakeen";
694  $userAdmin->login = "admin";
695  $userAdmin->Add(true);
696 
697  $group->iduser = $userAdmin->id;
698 
699  // Create default group
700 
701  $groupAll=new Account($this->dbaccess);
702  $groupAll->id = Account::GALL_ID;
703  $groupAll->lastname = "Utilisateurs";
704  $groupAll->firstname = "";
705  $groupAll->login = "all";
706  $groupAll->accounttype = self::GROUP_TYPE;
707  $groupAll->Add(true);
708 
709  $group->idgroup = $groupAll->id;
710  $group->Add(true);
711 
712  // Create anonymous user
713 
714  $anonymousUser=new Account($this->dbaccess);
715  $anonymousUser->id = Account::ANONYMOUS_ID;
716  $anonymousUser->lastname = "anonymous";
717  $anonymousUser->firstname = "guest";
718  $anonymousUser->login = "anonymous";
719  $anonymousUser->password = "-";
720  $anonymousUser->accounttype = self::USER_TYPE;
721  $anonymousUser->Add(true);
722 
723  // Create admin group
724 
725  $groupAdmin=new Account($this->dbaccess);
726  $groupAdmin->id = Account::GADMIN_ID;
727  $groupAdmin->lastname = "Administrateurs";
728  $groupAdmin->firstname = "";
729  $groupAdmin->login = "gadmin";
730  $groupAdmin->accounttype = self::GROUP_TYPE;
731  $groupAdmin->Add(true);
732  $group->idgroup = Account::GALL_ID;
733  $group->iduser = Account::GADMIN_ID;
734  $group->Add(true);
735  // Store error messages
736 
737  }
738  /**
739  * get the first incumbent which has $acl privilege
740  * @param Doc $doc document to verify
741  * @param string $acl document acl name
742  * @return string incumbent's name which has privilege
743  */
744  function getIncumbentPrivilege(Doc & $doc, $acl)
745  {
746  if ($this->id == 1) return '';
747  if ($incumbents = $this->getIncumbents()) {
748  if ($doc->control($acl, true) != '') {
749  foreach ($incumbents as $aIncumbent) {
750  $eErr = $doc->controlUserId($doc->profid, $aIncumbent, $acl);
751  if (!$eErr) return Account::getDisplayName($aIncumbent);
752  }
753  }
754  }
755  return '';
756  }
757  /**
758  * get All Users (not group not role)
759  * @static
760  * @param string $qtype return type LIST|TABLE|ITEM
761  * @param int $start
762  * @param int $slice
763  * @param string $filteruser keyword to filter user on login or lastname
764  * @return array
765  */
766  public static function getUserList($qtype = "LIST", $start = 0, $slice = 0, $filteruser = '')
767  {
768  $query = new QueryDb(getDbAccess() , "Account");
769  $query->order_by = "lastname";
770  $query->AddQuery("(accountType='U')");
771  if ($filteruser) $query->AddQuery("(login ~* '" . pg_escape_string($filteruser) . "')" . " or " . "(lastname ~* '" . pg_escape_string($filteruser) . "')");
772  return ($query->Query($start, $slice, $qtype));
773  }
774  /**
775  * get All groups
776  * @param string $qtype return type LIST|TABLE|ITEM
777  * @return array
778  */
779  public static function getGroupList($qtype = "LIST")
780  {
781  $query = new QueryDb(getDbAccess() , "Account");
782  $query->order_by = "lastname";
783  $query->AddQuery("(accountType='G')");
784  $l = $query->Query(0, 0, $qtype);
785  return ($query->nb > 0) ? $l : array();
786  }
787  /**
788  * get All Roles
789  * @param string $qtype return type LIST|TABLE|ITEM
790  * @return array
791  */
792  public static function getRoleList($qtype = "LIST")
793  {
794  $query = new QueryDb(getDbAccess() , "Account");
795  $query->order_by = "lastname";
796  $query->AddQuery("(accountType='R')");
797  $l = $query->Query(0, 0, $qtype);
798  return ($query->nb > 0) ? $l : array();
799  }
800  /**
801  * get All users & groups (except role)
802  * @param string $qtype return type LIST|TABLE|ITEM
803  * @return array
804  */
805  public static function getUserAndGroupList($qtype = "LIST")
806  {
807  $query = new QueryDb(getDbAccess() , "Account");
808  $query->AddQuery("(accountType='G' or accountType='U')");
809 
810  $query->order_by = "accounttype, lastname";
811  return ($query->Query(0, 0, $qtype));
812  }
813  /**
814  * get All ascendant group ids of the user object
815  */
816  function getGroupsId()
817  {
818 
819  $sql = sprintf("select idgroup from groups, users where groups.idgroup=users.id and users.accounttype='G' and groups.iduser=%d", $this->id);
820  simpleQuery($this->dbaccess, $sql, $groupsid, true, false);
821  return $groupsid;
822  }
823  /**
824  * for group :: get All user & groups ids in all descendant(recursive);
825  * @param int $id group identifier
826  * @return array of account array
827  */
828  function getRUsersList($id, $r = array())
829  {
830  $query = new QueryDb($this->dbaccess, "Account");
831  $list = $query->Query(0, 0, "TABLE", "select users.* from users, groups where " . "groups.iduser=users.id and " . "idgroup=$id ;");
832 
833  $uid = array();
834 
835  if ($query->nb > 0) {
836  foreach ($list as $k => $v) {
837  $uid[$v["id"]] = $v;
838  if ($v["accounttype"] == "G") {
839  if (!in_array($v["id"], $r)) {
840  array_push($r, $v["id"]);
841  $uid+= $this->GetRUsersList($v["id"], $r);
842  }
843  }
844  }
845  }
846 
847  return $uid;
848  }
849  /**
850  * for group :: get All direct user & groups ids
851  * @param int $id group identifier
852  * @param bool $onlygroup set to true if you want only child groups
853  */
854  function getUsersGroupList($gid, $onlygroup = false)
855  {
856  $query = new QueryDb($this->dbaccess, "Account");
857  $optgroup = '';
858  if ($onlygroup) $optgroup = " and users.accounttype='G' ";
859 
860  $list = $query->Query(0, 0, "TABLE", "select users.* from users, groups where " . "groups.iduser=users.id and " . "idgroup=$gid $optgroup;");
861 
862  $uid = array();
863  if ($query->nb > 0) {
864  foreach ($list as $k => $v) {
865  $uid[$v["id"]] = $v;
866  }
867  }
868 
869  return $uid;
870  }
871  /**
872  * return all user members (recursive)
873  * @return array of user values ["login"=>, "id"=>, "fid"=>,...)
874  */
875  private function getUserMembers()
876  {
877  $tr = array();
878 
879  $g = new Group($this->dbaccess);
880  $lg = $g->getChildsGroupId($this->id);
881  $lg[] = $this->id;
882  $cond = getSqlCond($lg, "idgroup", true);
883  if (!$cond) $cond = "true";
884  $condname = "";
885 
886  $sort = 'lastname';
887  $sql = sprintf("SELECT distinct on (%s, users.id) users.id, users.login, users.firstname , users.lastname, users.mail,users.fid from users, groups where %s and (groups.iduser=users.id) %s and accounttype='U' order by %s", $sort, $cond, $condname, $sort);
888 
889  $err = simpleQuery($this->dbaccess, $sql, $result);
890  if ($err != "") return $err;
891  return $result;
892  }
893  /**
894  * return all group (recursive) /role of user
895  * @param string $accountFilter G|R to indicate if want only group or only role
896  * @return array of users characteristics
897  */
898  public function getUserParents($accountFilter = '')
899  {
900  $acond = '';
901  if ($accountFilter) {
902  $acond = sprintf("and users.accounttype='%s'", pg_escape_string($accountFilter));
903  }
904  $sql = sprintf("with recursive agroups(gid) as (
905  select idgroup from groups,users where iduser = %d and users.id=groups.idgroup
906 union
907  select idgroup from groups,users, agroups where groups.iduser = agroups.gid and users.id=groups.idgroup
908 ) select users.* from agroups, users where users.id=agroups.gid %s order by lastname", $this->id, $acond);
909  simpleQuery($this->dbaccess, $sql, $parents);
910  return $parents;
911  }
912  /**
913  * get memberof for user without substitutes
914  * @param int $uid if not set it is the current account object else use another account identifier
915  * @return array
916  * @throws Dcp\Exception
917  */
918  public function getStrictMemberOf($uid = - 1)
919  {
920  if ($uid == - 1) $uid = $this->id;
921  if (!$uid) return array();
922  // get all ascendants groupe,role of a user
923  $sql = sprintf("with recursive agroups(gid, login, actype) as (
924  select idgroup, users.login, users.accounttype from groups,users where iduser = %d and users.id=groups.idgroup
925  union
926  select idgroup, users.login, users.accounttype from groups,users, agroups where groups.iduser = agroups.gid and users.id=groups.idgroup
927 ) select gid from agroups;", $uid);
928 
929  simpleQuery($this->dbaccess, $sql, $gids, true, false);
930  return $gids;
931  }
932  /**
933  * update memberof fields with all group/role of user
934  * @param bool $updateSubstitute also update substitute by default
935  * @return array of memberof identificators
936  * @throws Dcp\Exception
937  */
938  public function updateMemberOf($updateSubstitute = true)
939  {
940  if (!$this->id) return array();
941 
942  $lg = $this->getStrictMemberOf();
943  // search incumbents
944  $sql = sprintf("select id from users where substitute=%d;", $this->id);
945  simpleQuery($this->dbaccess, $sql, $incumbents, true, false);
946  foreach ($incumbents as $aIncumbent) {
947  $lg[] = $aIncumbent;
948  // use strict no propagate substitutes
949  $lg = array_merge($lg, $this->getStrictMemberOf($aIncumbent));
950  }
951 
952  $lg = array_values(array_unique($lg));
953  $this->memberof = '{' . implode(',', $lg) . '}';
954  $err = $this->modify(true, array(
955  'memberof'
956  ) , true);
957  if ($err) throw new Dcp\Exception($err);
958  if ($updateSubstitute && $this->substitute) {
959  $u = new Account($this->dbaccess, $this->substitute);
960  $u->updateMemberOf(false);
961  }
962 
963  return $lg;
964  }
965  /**
966  * return id of group/role id
967  * @param bool $useSystemId set to false to return document id instead of system id
968  * @return array
969  */
970  public function getMemberOf($useSystemId = true)
971  {
972  $memberOf = array();
973  if (strlen($this->memberof) > 2) {
974  $memberOf = explode(',', substr($this->memberof, 1, -1));
975  }
976  if (!$useSystemId) {
977  if (!empty($memberOf)) {
978  simpleQuery($this->dbaccess, sprintf("select fid from users where id in (%s)", implode(',', $memberOf)) , $dUids, true);
979  return $dUids;
980  }
981  }
982  return $memberOf;
983  }
984  /**
985  * return list of account (group/role) member for a user
986  * return null if user not exists
987  * @static
988  * @param int $uid user identifier
989  * @return array|null
990  */
991  public static function getUserMemberOf($uid, $strict = false)
992  {
993  global $action;
994  $memberOf = array();
995  if ($action->user->id == $uid) {
996  if ($strict) $memberOf = $action->user->getStrictMemberOf();
997  else $memberOf = $action->user->getMemberOf();
998  } else {
999  $u = new Account('', $uid);
1000  if ($u->isAffected()) {
1001  if ($strict) $memberOf = $u->getStrictMemberOf();
1002  else $memberOf = $u->getMemberOf();
1003  } else {
1004  return null;
1005  }
1006  }
1007  return $memberOf;
1008  }
1009  /**
1010  * verify if user is member of group (recursive)
1011  * @return bool
1012  */
1013  public function isMember($uid)
1014  {
1015  $tr = array();
1016 
1017  $g = new Group($this->dbaccess);
1018  $lg = $g->getChildsGroupId($this->id);
1019  $lg[] = $this->id;
1020  $cond = getSqlCond($lg, "idgroup", true);
1021  if (!$cond) $cond = "true";
1022 
1023  $sql = sprintf("select users.id from users, groups where %s and (groups.iduser=users.id) and users.id=%d and isgroup != 'Y'", $cond, $uid);
1024 
1025  $err = simpleQuery($this->dbaccess, $sql, $result, true, true);
1026 
1027  return ($result != '');
1028  }
1029  /**
1030  * only use with group or role
1031  * if it is a group : get all direct user member of a group
1032  * if it is a role : het user which has role directly
1033  * @param string $qtype LIST|TABLE|ITEM
1034  * @param bool $withgroup set to true to return sub group also
1035  * @param int|string $limit max users returned
1036  * @return array of user properties
1037  */
1038  function getGroupUserList($qtype = "LIST", $withgroup = false, $limit = "all")
1039  {
1040  $query = new QueryDb($this->dbaccess, "Account");
1041  $query->order_by = "accounttype desc, lastname";
1042  $selgroup = "and (accounttype='U')";
1043  if ($withgroup) $selgroup = "";
1044  return ($query->Query(0, $limit, $qtype, "select users.* from users, groups where " . "groups.iduser=users.id and " . "idgroup={$this->id} {$selgroup};"));
1045  }
1046  /**
1047  * get all users of a group/role direct or indirect
1048  * @param int|string $limit max users returned
1049  * @param bool $onlyUsers set to true to have also sub groups
1050  * @return array of user properties
1051  */
1052  function getAllMembers($limit = "all", $onlyUsers = true)
1053  {
1054  if ($limit != 'all') $limit = intval($limit);
1055  if ($onlyUsers) {
1056  $sql = sprintf("select * from users where memberof && '{%d}' and accounttype='U' order by lastname limit %s", $this->id, $limit);
1057  } else {
1058  $sql = sprintf("select * from users where memberof && '{%d}' order by accounttype, lastname limit %s", $this->id, $limit);
1059  }
1060  simpleQuery($this->dbaccess, $sql, $users);
1061  return $users;
1062  }
1063  /**
1064  * Get user token for open access
1065  *
1066  * @param bool|int $expireDelay set expiration delay in seconds (-1 if nether expire)
1067  * @param bool $oneshot set to true to use one token is consumed/deleted when used
1068  *
1069  * @param array $context get http var restriction
1070  * @param string $description text description information
1071  * @param bool $forceCreate set to true to always return a new token
1072  *
1073  * @return string
1074  * @throws \Dcp\Exception
1075  */
1076  function getUserToken($expireDelay = - 1, $oneshot = false, $context = array() , $description = "", $forceCreate = false)
1077  {
1078  if ($expireDelay === - 1 || $expireDelay === false) {
1079  $expireDelay = UserToken::INFINITY;
1080  }
1081  if ($context && (count($context) > 0)) {
1082  $scontext = serialize($context);
1083  } else $scontext = '';
1084 
1085  if (!$this->isAffected()) {
1086  throw new Dcp\Exception(sprintf("User token : account must be affected"));
1087  }
1088  include_once ('WHAT/Class.UserToken.php');
1089  include_once ('WHAT/Class.QueryDb.php');
1090 
1091  $expireDate = UserToken::getExpirationDate($expireDelay);
1092  $tu = array();
1093  if (!$oneshot && !$forceCreate) {
1094  $q = new QueryDb($this->dbaccess, "UserToken");
1095  $q->addQuery(sprintf("userid=%d", $this->id));
1096  $q->addQuery(sprintf("expire='%s'", $expireDate));
1097  if ($scontext) $q->addQuery("context='" . pg_escape_string($scontext) . "'");
1098  $tu = $q->Query(0, 0, "TABLE");
1099  $create = ($q->nb == 0);
1100  } else {
1101  $create = true;
1102  }
1103 
1104  if ($create) {
1105  // create one
1106  $uk = new UserToken("");
1107  $uk->userid = $this->id;
1108  $uk->description = $description;
1109  $uk->token = $uk->genToken();
1110  $uk->type = "CORE";
1111  $uk->expire = $uk->setExpiration($expireDelay);
1112  if ($uk->expire === false) {
1113  throw new Dcp\Exception(sprintf("User token : Invalid date. Expire must be a delay in seconds"));
1114  }
1115  $uk->expendable = $oneshot;
1116  $uk->context = $scontext;
1117  $err = $uk->add();
1118  if ($err) {
1119  throw new Dcp\Exception($err);
1120  }
1121  $token = $uk->token;
1122  } else {
1123  $token = $tu[0]["token"];
1124  }
1125  return $token;
1126  }
1127  /**
1128  * Set password for the admin account in the `admin' subdir
1129  *
1130  * @deprecated use {@link Account::setSupervisorHtpasswd} instead
1131  * @see Account::setSupervisorHtpasswd
1132  *
1133  * @param string $admin_passwd the password
1134  * @return string error message, emptuy string if no error
1135  */
1137  {
1139  return $this->setSupervisorHtpasswd($admin_passwd);
1140  }
1141  /**
1142  * Set password for the admin account in the `admin' subdir
1143  * @param string $admin_passwd the password
1144  * @return string error message, emptuy string if no error
1145  */
1147  {
1148  include_once ('WHAT/Lib.Prefix.php');
1149 
1150  global $pubdir;
1151 
1152  if ($this->id != 1) {
1153  $err = sprintf("Method %s can only be used on the admin user.", __FUNCTION__);
1154  return $err;
1155  }
1156 
1157  $supervisorDir = $pubdir . DIRECTORY_SEPARATOR . 'supervisor';
1158  $tmpFile = @tempnam($supervisorDir, '.htpasswd');
1159  if ($tmpFile === false) {
1160  $err = sprintf("Error creating temporary file in '%s'.", $supervisorDir);
1161  return $err;
1162  }
1163  if (chmod($tmpFile, 0600) === false) {
1164  $err = sprintf("Error setting mode 0600 on temporary file '%s'.", $tmpFile);
1165  unlink($tmpFile);
1166  return $err;
1167  }
1168  $passwdLine = sprintf("%s:{SHA}%s", 'admin', base64_encode(sha1($admin_passwd, true)));
1169  if (file_put_contents($tmpFile, $passwdLine) === false) {
1170  $err = sprintf("Error writing to temporary file '%s'.", $tmpFile);
1171  unlink($tmpFile);
1172  return $err;
1173  }
1174  $htpasswdFile = $supervisorDir . DIRECTORY_SEPARATOR . '.htpasswd';
1175  if (rename($tmpFile, $htpasswdFile) === false) {
1176  $err = sprintf("Error renaming temporary file '%s' to '%s'.", $tmpFile, $htpasswdFile);
1177  unlink($tmpFile);
1178  return $err;
1179  }
1180  return '';
1181  }
1182  /**
1183  * add a role to a user/group
1184  * @param string $idRole system identicator or reference role (login)
1185  * @return string error message
1186  */
1187  public function addRole($idRole)
1188  {
1189  if (!$this->isAffected()) return ErrorCode::getError("ACCT0002", $idRole);
1190  if ($this->accounttype != self::USER_TYPE) return ErrorCode::getError("ACCT0003", $idRole, $this->login);
1191  if (!is_numeric($idRole)) {
1192  simpleQuery($this->dbaccess, sprintf("select id from users where login = '%'", pg_escape_string($idRole)) , $idRoleW, true, true);
1193  if ($idRoleW) $idRole = $idRoleW;
1194  }
1195  if (!is_numeric($idRole)) {
1196  return ErrorCode::getError("ACCT0001", $idRole, $this->login);
1197  }
1198  $g = new group($this->dbaccess);
1199  $g->idgroup = $idRole;
1200  $g->iduser = $this->id;
1201  $err = $g->add();
1202  if ($err == 'OK') {
1203  $err = '';
1204  $this->updateMemberOf();
1205  }
1206  return $err;
1207  }
1208  /**
1209  * set role set to a user/group
1210  * @param array $roleIds system identicators or reference roles (login)
1211  * @return string error message
1212  */
1213  public function setRoles(array $roleIds)
1214  {
1215  if (!$this->isAffected()) return ErrorCode::getError("ACCT0006", implode(',', $roleIds));
1216 
1217  if ($this->accounttype == self::ROLE_TYPE) return ErrorCode::getError("ACCT0007", implode(',', $roleIds) , $this->login);
1218  $this->deleteRoles();
1219  $err = '';
1220  if ($this->accounttype == self::USER_TYPE || $this->accounttype == self::GROUP_TYPE) {
1221  $g = new group($this->dbaccess);
1222  foreach ($roleIds as $rid) {
1223  if (!is_numeric($rid)) {
1224  simpleQuery($this->dbaccess, sprintf("select id from users where login = '%'", pg_escape_string($rid)) , $idRoleW, true, true);
1225  if ($idRoleW) $rid = $idRoleW;
1226  }
1227  if (!is_numeric($rid)) {
1228  $err.= ErrorCode::getError("ACCT0008", $rid, $this->login);
1229  } else {
1230 
1231  $g->idgroup = $rid;
1232  $g->iduser = $this->id;
1233  $gerr = $g->add(true);
1234  if ($gerr == 'OK') $gerr = '';
1235  $err.= $gerr;
1236  }
1237  }
1238 
1239  $this->updateMemberOf();
1240  }
1241  if ($this->accounttype == self::GROUP_TYPE) {
1242  // must propagate to users
1243  $lu = $this->getUserMembers();
1244  $uw = new Account($this->dbaccess);
1245  foreach ($lu as $u) {
1246  $uw->id = $u["id"];
1247  $uw->updateMemberOf();
1248  }
1249  }
1250  return $err;
1251  }
1252  /**
1253  * return direct role ids (not role which can comes from parent groups)
1254  * @param bool $useSystemId if true return system id else return document ids
1255  * @return array
1256  */
1257  function getRoles($useSystemId = true)
1258  {
1259  $returnColumn = $useSystemId ? "id" : "fid";
1260  $sql = sprintf("SELECT users.%s from users, groups where groups.iduser=%d and users.id = groups.idgroup and users.accounttype='R'", $returnColumn, $this->id);
1261  simpleQuery($this->dbaccess, $sql, $rids, true, false);
1262  return $rids;
1263  }
1264  /**
1265  * return direct and indirect role which comes from groups
1266  * @param bool $useSystemId if true return system id else return document ids
1267  * @return array of users properties
1268  */
1269  function getAllRoles()
1270  {
1271  $mo = $this->getMemberOf();
1272  if (empty($mo)) return array();
1273  $sql = sprintf("SELECT * from users where id in (%s) and accounttype='R'", implode(',', $mo));
1274  simpleQuery($this->dbaccess, $sql, $rusers);
1275  return $rusers;
1276  }
1277  /**
1278  * delete all role of a user/group
1279  * @return string error message
1280  */
1281  public function deleteRoles()
1282  {
1283  if (!$this->isAffected()) return ErrorCode::getError("ACCT0004");
1284  if ($this->accounttype == self::ROLE_TYPE) return ErrorCode::getError("ACCT0005", $this->login);
1285  $err = '';
1286  $sql = sprintf("DELETE FROM groups USING users where groups.iduser=%d and users.id=groups.idgroup and users.accounttype='R'", $this->id);
1287  $err = simpleQuery($this->dbaccess, $sql);
1288  if (!$err) {
1289 
1290  $err = simpleQuery($this->dbaccess, "delete from permission where computed");
1291  }
1292 
1293  return $err;
1294  }
1295  private function _deleteUserSessions()
1296  {
1297  if (AuthenticatorManager::$session !== null && AuthenticatorManager::$session->userid == $this->id) {
1298  AuthenticatorManager::$session->deleteUserSessionsExcept();
1299  } else {
1300  $session = new Session($this->dbaccess);
1301  $session->deleteUserSessionsExcept($this->id);
1302  }
1303  }
1304 }
getAllMembers($limit="all", $onlyUsers=true)
static getUserAndGroupList($qtype="LIST")
const GALL_ID
setFid($fid)
static getFidFromUid($uid)
$tdoc
if($_POST["login"]=="")
Definition: chgpasswd.php:19
global $action
global $pubdir
Definition: vault_init.php:18
setLoginName($login)
getGroupUserList($qtype="LIST", $withgroup=false, $limit="all")
$core user expires
Definition: chgpasswd.php:55
Add($nopost=false, $nopre=false)
Exception class use exceptionCode to identifiy correctly exception.
Definition: exceptions.php:19
$memberOf
static getExpirationDate($delayInSeconds)
static getUserMemberOf($uid, $strict=false)
static getUserList($qtype="LIST", $start=0, $slice=0, $filteruser= '')
getRUsersList($id, $r=array())
const ANONYMOUS_ID
updateMemberOf($updateSubstitute=true)
$admin_passwd
setRoles(array $roleIds)
updateUser($fid, $lname, $fname, $expires, $passdelay, $login, $status, $pwd1, $pwd2, $extmail= '', array $roles=array(-1), $substitute=-1)
refreshGroups($groupIdList, $refresh=false, &$currentPath=array(), &$groupDepth=array())
const GROUP_TYPE
static getError($code, $args=null)
Definition: ErrorCode.php:27
isAffected()
getMail($rawmail=true)
const GADMIN_ID
const ADMIN_ID
modify($nopost=false, $sfields="", $nopre=false)
isMember($uid)
getRoles($useSystemId=true)
if($real||$full) else
getUsersGroupList($gid, $onlygroup=false)
setSubstitute($substitute)
setUsers($fid, $lname, $fname, $expires, $passdelay, $login, $status, $pwd1, $pwd2, $unused= '', $extmail= '')
setAdminHtpasswd($admin_passwd)
const USER_TYPE
getParam($name, $def="")
must be in core or global type
Definition: Lib.Common.php:193
createDoc($dbaccess, $fromid, $control=true, $defaultvalues=true, $temporary=false)
static getGroupList($qtype="LIST")
static getDisplayName($uid)
getUserParents($accountFilter= '')
internalGetDocCollection($dbaccess, $dirid, $start="0", $slice="ALL", $sqlfilters=array(), $userid=1, $qtype="LIST", $fromid="", $distinct=false, $orderby="title", $latest=true, $trash="", &$debug=null, $folderRecursiveLevel=2, $join= '',\SearchDoc &$searchDoc=null)
Definition: Lib.Dir.php:428
getIncumbentPrivilege(Doc &$doc, $acl)
if(!$core->user->isAffected()) if($_POST["passwd1"]!=$_POST["passwd2"]) if($_POST["passwd1"]=="") $core user password_new
Definition: chgpasswd.php:54
CheckLogin($login, $unused, $whatid)
static getRoleList($qtype="LIST")
deprecatedFunction($msg= '')
Definition: Lib.Common.php:86
getUserToken($expireDelay=-1, $oneshot=false, $context=array(), $description="", $forceCreate=false)
getDbAccess()
Definition: Lib.Common.php:368
static getUidFromFid($fid)
new_Doc($dbaccess, $id= '', $latest=false)
checkpass($pass, $passk)
getStrictMemberOf($uid=-1)
setGroups($fid, $gname, $login, array $roles=array(-1))
if(($docid!==0)&&(!is_numeric($docid))) $query
simpleQuery($dbaccess, $query, &$result=array(), $singlecolumn=false, $singleresult=false, $useStrict=null)
Definition: Lib.Common.php:484
computepass($pass, &$passk)
if($file) if($subject==""&&$file) if($subject=="") $err
getIncumbents($returnSystemIds=true)
checkpassword($pass)
getMemberOf($useSystemId=true)
setSupervisorHtpasswd($admin_passwd)
addRole($idRole)
setLogin($login, $unused= '0')
mb_trim($string)
Definition: Lib.Common.php:113
controlUserId($docid, $uid, $aclname)
control($aclname, $strict=false)
Definition: Class.Doc.php:6593
const ROLE_TYPE
← centre documentaire © anakeen