dolibarr  17.0.4
api_users.class.php
1 <?php
2 /* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
3  * Copyright (C) 2020 Thibault FOUCART <support@ptibogxiv.net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 use Luracast\Restler\RestException;
20 
21 require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
22 require_once DOL_DOCUMENT_ROOT.'/user/class/usergroup.class.php';
23 
24 
31 class Users extends DolibarrApi
32 {
36  static $FIELDS = array(
37  'login',
38  );
39 
43  public $useraccount;
44 
48  public function __construct()
49  {
50  global $db, $conf;
51 
52  $this->db = $db;
53  $this->useraccount = new User($this->db);
54  }
55 
56 
71  public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $user_ids = 0, $category = 0, $sqlfilters = '')
72  {
73  global $conf;
74 
75  if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) {
76  throw new RestException(401, "You are not allowed to read list of users");
77  }
78 
79  $obj_ret = array();
80 
81  // case of external user, $societe param is ignored and replaced by user's socid
82  //$socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $societe;
83 
84  $sql = "SELECT t.rowid";
85  $sql .= " FROM ".$this->db->prefix()."user as t";
86  if ($category > 0) {
87  $sql .= ", ".$this->db->prefix()."categorie_user as c";
88  }
89  $sql .= ' WHERE t.entity IN ('.getEntity('user').')';
90  if ($user_ids) {
91  $sql .= " AND t.rowid IN (".$this->db->sanitize($user_ids).")";
92  }
93 
94  // Select products of given category
95  if ($category > 0) {
96  $sql .= " AND c.fk_categorie = ".((int) $category);
97  $sql .= " AND c.fk_user = t.rowid";
98  }
99 
100  // Add sql filters
101  if ($sqlfilters) {
102  $errormessage = '';
103  $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
104  if ($errormessage) {
105  throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
106  }
107  }
108 
109  $sql .= $this->db->order($sortfield, $sortorder);
110  if ($limit) {
111  if ($page < 0) {
112  $page = 0;
113  }
114  $offset = $limit * $page;
115 
116  $sql .= $this->db->plimit($limit + 1, $offset);
117  }
118 
119  $result = $this->db->query($sql);
120 
121  if ($result) {
122  $i = 0;
123  $num = $this->db->num_rows($result);
124  $min = min($num, ($limit <= 0 ? $num : $limit));
125  while ($i < $min) {
126  $obj = $this->db->fetch_object($result);
127  $user_static = new User($this->db);
128  if ($user_static->fetch($obj->rowid)) {
129  $obj_ret[] = $this->_cleanObjectDatas($user_static);
130  }
131  $i++;
132  }
133  } else {
134  throw new RestException(503, 'Error when retrieve User list : '.$this->db->lasterror());
135  }
136  if (!count($obj_ret)) {
137  throw new RestException(404, 'No User found');
138  }
139  return $obj_ret;
140  }
141 
152  public function get($id, $includepermissions = 0)
153  {
154  if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin) && $id != 0 && DolibarrApiAccess::$user->id != $id) {
155  throw new RestException(401, 'Not allowed');
156  }
157 
158  if ($id == 0) {
159  $result = $this->useraccount->initAsSpecimen();
160  } else {
161  $result = $this->useraccount->fetch($id);
162  }
163  if (!$result) {
164  throw new RestException(404, 'User not found');
165  }
166 
167  if ($id > 0 && !DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) {
168  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
169  }
170 
171  if ($includepermissions) {
172  $this->useraccount->getRights();
173  }
174 
175  return $this->_cleanObjectDatas($this->useraccount);
176  }
177 
191  public function getByLogin($login, $includepermissions = 0)
192  {
193  if (empty($login)) {
194  throw new RestException(400, 'Bad parameters');
195  }
196 
197  if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin) && DolibarrApiAccess::$user->login != $login) {
198  throw new RestException(401, 'Not allowed');
199  }
200 
201  $result = $this->useraccount->fetch('', $login);
202  if (!$result) {
203  throw new RestException(404, 'User not found');
204  }
205 
206  if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) {
207  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
208  }
209 
210  if ($includepermissions) {
211  $this->useraccount->getRights();
212  }
213 
214  return $this->_cleanObjectDatas($this->useraccount);
215  }
216 
230  public function getByEmail($email, $includepermissions = 0)
231  {
232  if (empty($email)) {
233  throw new RestException(400, 'Bad parameters');
234  }
235 
236  if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin) && DolibarrApiAccess::$user->email != $email) {
237  throw new RestException(401, 'Not allowed');
238  }
239 
240  $result = $this->useraccount->fetch('', '', '', 0, -1, $email);
241  if (!$result) {
242  throw new RestException(404, 'User not found');
243  }
244 
245  if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) {
246  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
247  }
248 
249  if ($includepermissions) {
250  $this->useraccount->getRights();
251  }
252 
253  return $this->_cleanObjectDatas($this->useraccount);
254  }
255 
267  public function getInfo($includepermissions = 0)
268  {
269  if (empty(DolibarrApiAccess::$user->rights->user->self->creer) && empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) {
270  throw new RestException(401, 'Not allowed');
271  }
272 
273  $apiUser = DolibarrApiAccess::$user;
274 
275  $result = $this->useraccount->fetch($apiUser->id);
276  if (!$result) {
277  throw new RestException(404, 'User not found');
278  }
279 
280  if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) {
281  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
282  }
283 
284  if ($includepermissions) {
285  $this->useraccount->getRights();
286  }
287 
288  $usergroup = new UserGroup($this->db);
289  $userGroupList = $usergroup->listGroupsForUser($apiUser->id, false);
290  if (!is_array($userGroupList)) {
291  throw new RestException(404, 'User group not found');
292  }
293 
294  $this->useraccount->user_group_list = $this->_cleanUserGroupListDatas($userGroupList);
295 
296  return $this->_cleanObjectDatas($this->useraccount);
297  }
298 
307  public function post($request_data = null)
308  {
309  // Check user authorization
310  if (empty(DolibarrApiAccess::$user->rights->user->creer) && empty(DolibarrApiAccess::$user->admin)) {
311  throw new RestException(401, "User creation not allowed for login ".DolibarrApiAccess::$user->login);
312  }
313 
314  // check mandatory fields
315  /*if (!isset($request_data["login"]))
316  throw new RestException(400, "login field missing");
317  if (!isset($request_data["password"]))
318  throw new RestException(400, "password field missing");
319  if (!isset($request_data["lastname"]))
320  throw new RestException(400, "lastname field missing");*/
321 
322  //assign field values
323  foreach ($request_data as $field => $value) {
324  if (in_array($field, array('pass_crypted', 'pass_indatabase', 'pass_indatabase_crypted', 'pass_temp', 'api_key'))) {
325  // This properties can't be set/modified with API
326  throw new RestException(401, 'The property '.$field." can't be set/modified using the APIs");
327  }
328  /*if ($field == 'pass') {
329  if (empty(DolibarrApiAccess::$user->rights->user->user->password)) {
330  throw new RestException(401, 'You are not allowed to modify/set password of other users');
331  continue;
332  }
333  }
334  */
335 
336  $this->useraccount->$field = $value;
337  }
338 
339  if ($this->useraccount->create(DolibarrApiAccess::$user) < 0) {
340  throw new RestException(500, 'Error creating', array_merge(array($this->useraccount->error), $this->useraccount->errors));
341  }
342  return $this->useraccount->id;
343  }
344 
345 
357  public function put($id, $request_data = null)
358  {
359  // Check user authorization
360  if (empty(DolibarrApiAccess::$user->rights->user->user->creer) && empty(DolibarrApiAccess::$user->admin)) {
361  throw new RestException(401, "User update not allowed");
362  }
363 
364  $result = $this->useraccount->fetch($id);
365  if (!$result) {
366  throw new RestException(404, 'Account not found');
367  }
368 
369  if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) {
370  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
371  }
372 
373  foreach ($request_data as $field => $value) {
374  if ($field == 'id') {
375  continue;
376  }
377  if (in_array($field, array('pass_crypted', 'pass_indatabase', 'pass_indatabase_crypted', 'pass_temp', 'api_key'))) {
378  // This properties can't be set/modified with API
379  throw new RestException(401, 'The property '.$field." can't be set/modified using the APIs");
380  }
381  if ($field == 'pass') {
382  if ($this->useraccount->id != DolibarrApiAccess::$user->id && empty(DolibarrApiAccess::$user->rights->user->user->password)) {
383  throw new RestException(401, 'You are not allowed to modify password of other users');
384  }
385  if ($this->useraccount->id == DolibarrApiAccess::$user->id && empty(DolibarrApiAccess::$user->rights->user->self->password)) {
386  throw new RestException(401, 'You are not allowed to modify your own password');
387  }
388  }
389  if (DolibarrApiAccess::$user->admin) { // If user for API is admin
390  if ($field == 'admin' && $value != $this->useraccount->admin && empty($value)) {
391  throw new RestException(401, 'Reseting the admin status of a user is not possible using the API');
392  }
393  } else {
394  if ($field == 'admin' && $value != $this->useraccount->admin) {
395  throw new RestException(401, 'Only an admin user can modify the admin status of another user');
396  }
397  }
398  if ($field == 'entity' && $value != $this->useraccount->entity) {
399  throw new RestException(401, 'Changing entity of a user using the APIs is not possible');
400  }
401  // The status must be updated using setstatus() because it
402  // is not handled by the update() method.
403  if ($field == 'statut') {
404  $result = $this->useraccount->setstatus($value);
405  if ($result < 0) {
406  throw new RestException(500, 'Error when updating status of user: '.$this->useraccount->error);
407  }
408  } else {
409  $this->useraccount->$field = $value;
410  }
411  }
412 
413  // If there is no error, update() returns the number of affected
414  // rows so if the update is a no op, the return value is zezo.
415  if ($this->useraccount->update(DolibarrApiAccess::$user) >= 0) {
416  return $this->get($id);
417  } else {
418  throw new RestException(500, $this->useraccount->error);
419  }
420  }
421 
422 
434  public function getGroups($id)
435  {
436  if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) {
437  throw new RestException(403);
438  }
439 
440  $obj_ret = array();
441 
442  $user = new User($this->db);
443  $result = $user->fetch($id);
444  if (!$result) {
445  throw new RestException(404, 'user not found');
446  }
447 
448  $usergroup = new UserGroup($this->db);
449  $groups = $usergroup->listGroupsForUser($id, false);
450  $obj_ret = array();
451  foreach ($groups as $group) {
452  $obj_ret[] = $this->_cleanObjectDatas($group);
453  }
454  return $obj_ret;
455  }
456 
457 
472  public function setGroup($id, $group, $entity = 1)
473  {
474  global $conf;
475 
476  if (empty(DolibarrApiAccess::$user->rights->user->user->creer) && empty(DolibarrApiAccess::$user->admin)) {
477  throw new RestException(401);
478  }
479 
480  $result = $this->useraccount->fetch($id);
481  if (!$result) {
482  throw new RestException(404, 'User not found');
483  }
484 
485  if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) {
486  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
487  }
488 
489  if (isModEnabled('multicompany') && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && !empty(DolibarrApiAccess::$user->admin) && empty(DolibarrApiAccess::$user->entity)) {
490  $entity = (!empty($entity) ? $entity : $conf->entity);
491  } else {
492  // When using API, action is done on entity of logged user because a user of entity X with permission to create user should not be able to
493  // hack the security by giving himself permissions on another entity.
494  $entity = (DolibarrApiAccess::$user->entity > 0 ? DolibarrApiAccess::$user->entity : $conf->entity);
495  }
496 
497  $result = $this->useraccount->SetInGroup($group, $entity);
498  if (!($result > 0)) {
499  throw new RestException(500, $this->useraccount->error);
500  }
501 
502  return 1;
503  }
504 
523  public function listGroups($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $group_ids = 0, $sqlfilters = '')
524  {
525  global $conf;
526 
527  $obj_ret = array();
528 
529  if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) ||
530  !empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->group_advance->read) && empty(DolibarrApiAccess::$user->admin)) {
531  throw new RestException(401, "You are not allowed to read groups");
532  }
533 
534  // case of external user, $societe param is ignored and replaced by user's socid
535  //$socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $societe;
536 
537  $sql = "SELECT t.rowid";
538  $sql .= " FROM ".$this->db->prefix()."usergroup as t";
539  $sql .= ' WHERE t.entity IN ('.getEntity('user').')';
540  if ($group_ids) {
541  $sql .= " AND t.rowid IN (".$this->db->sanitize($group_ids).")";
542  }
543  // Add sql filters
544  if ($sqlfilters) {
545  $errormessage = '';
546  $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
547  if ($errormessage) {
548  throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
549  }
550  }
551 
552  $sql .= $this->db->order($sortfield, $sortorder);
553  if ($limit) {
554  if ($page < 0) {
555  $page = 0;
556  }
557  $offset = $limit * $page;
558 
559  $sql .= $this->db->plimit($limit + 1, $offset);
560  }
561 
562  $result = $this->db->query($sql);
563 
564  if ($result) {
565  $i = 0;
566  $num = $this->db->num_rows($result);
567  $min = min($num, ($limit <= 0 ? $num : $limit));
568  while ($i < $min) {
569  $obj = $this->db->fetch_object($result);
570  $group_static = new UserGroup($this->db);
571  if ($group_static->fetch($obj->rowid)) {
572  $obj_ret[] = $this->_cleanObjectDatas($group_static);
573  }
574  $i++;
575  }
576  } else {
577  throw new RestException(503, 'Error when retrieve Group list : '.$this->db->lasterror());
578  }
579  if (!count($obj_ret)) {
580  throw new RestException(404, 'No Group found');
581  }
582  return $obj_ret;
583  }
584 
599  public function infoGroups($group, $load_members = 0)
600  {
601  global $db, $conf;
602 
603  if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) ||
604  !empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->group_advance->read) && empty(DolibarrApiAccess::$user->admin)) {
605  throw new RestException(401, "You are not allowed to read groups");
606  }
607 
608  $group_static = new UserGroup($this->db);
609  $result = $group_static->fetch($group, '', $load_members);
610 
611  if (!$result) {
612  throw new RestException(404, 'Group not found');
613  }
614 
615  return $this->_cleanObjectDatas($group_static);
616  }
617 
627  public function delete($id)
628  {
629  if (empty(DolibarrApiAccess::$user->rights->user->user->supprimer) && empty(DolibarrApiAccess::$user->admin)) {
630  throw new RestException(401, 'Not allowed');
631  }
632  $result = $this->useraccount->fetch($id);
633  if (!$result) {
634  throw new RestException(404, 'User not found');
635  }
636 
637  if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) {
638  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
639  }
640  $this->useraccount->oldcopy = clone $this->useraccount;
641 
642  if (!$this->useraccount->delete(DolibarrApiAccess::$user)) {
643  throw new RestException(500);
644  }
645 
646  return array(
647  'success' => array(
648  'code' => 200,
649  'message' => 'Ticket deleted'
650  )
651  );
652  }
653 
654  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
661  protected function _cleanObjectDatas($object)
662  {
663  // phpcs:enable
664  global $conf;
665 
666  $object = parent::_cleanObjectDatas($object);
667 
668  unset($object->default_values);
669  unset($object->lastsearch_values);
670  unset($object->lastsearch_values_tmp);
671 
672  unset($object->total_ht);
673  unset($object->total_tva);
674  unset($object->total_localtax1);
675  unset($object->total_localtax2);
676  unset($object->total_ttc);
677 
678  unset($object->label_incoterms);
679  unset($object->location_incoterms);
680 
681  unset($object->fk_delivery_address);
682  unset($object->fk_incoterms);
683  unset($object->all_permissions_are_loaded);
684  unset($object->shipping_method_id);
685  unset($object->nb_rights);
686  unset($object->search_sid);
687  unset($object->ldap_sid);
688  unset($object->clicktodial_loaded);
689 
690  // List of properties never returned by API, whatever are permissions
691  unset($object->pass);
692  unset($object->pass_indatabase);
693  unset($object->pass_indatabase_crypted);
694  unset($object->pass_temp);
695  unset($object->api_key);
696  unset($object->clicktodial_password);
697  unset($object->openid);
698 
699  unset($object->lines);
700  unset($object->model_pdf);
701 
702  unset($object->skype);
703  unset($object->twitter);
704  unset($object->facebook);
705  unset($object->linkedin);
706 
707  $canreadsalary = ((!empty($conf->salaries->enabled) && !empty(DolibarrApiAccess::$user->rights->salaries->read)) || (empty($conf->salaries->enabled)));
708 
709  if (!$canreadsalary) {
710  unset($object->salary);
711  unset($object->salaryextra);
712  unset($object->thm);
713  unset($object->tjm);
714  }
715 
716  return $object;
717  }
718 
725  private function _cleanUserGroupListDatas($objectList)
726  {
727  $cleanObjectList = array();
728 
729  foreach ($objectList as $object) {
730  $cleanObject = parent::_cleanObjectDatas($object);
731 
732  unset($cleanObject->default_values);
733  unset($cleanObject->lastsearch_values);
734  unset($cleanObject->lastsearch_values_tmp);
735 
736  unset($cleanObject->total_ht);
737  unset($cleanObject->total_tva);
738  unset($cleanObject->total_localtax1);
739  unset($cleanObject->total_localtax2);
740  unset($cleanObject->total_ttc);
741 
742  unset($cleanObject->libelle_incoterms);
743  unset($cleanObject->location_incoterms);
744 
745  unset($cleanObject->fk_delivery_address);
746  unset($cleanObject->fk_incoterms);
747  unset($cleanObject->all_permissions_are_loaded);
748  unset($cleanObject->shipping_method_id);
749  unset($cleanObject->nb_rights);
750  unset($cleanObject->search_sid);
751  unset($cleanObject->ldap_sid);
752  unset($cleanObject->clicktodial_loaded);
753 
754  unset($cleanObject->datec);
755  unset($cleanObject->datem);
756  unset($cleanObject->members);
757  unset($cleanObject->note);
758  unset($cleanObject->note_private);
759 
760  $cleanObjectList[] = $cleanObject;
761  }
762 
763  return $cleanObjectList;
764  }
765 
773  private function _validate($data)
774  {
775  $account = array();
776  foreach (Users::$FIELDS as $field) {
777  if (!isset($data[$field])) {
778  throw new RestException(400, "$field field missing");
779  }
780  $account[$field] = $data[$field];
781  }
782  return $account;
783  }
784 }
Class for API REST v1.
Definition: api.class.php:31
static _checkAccessToResource($resource, $resource_id=0, $dbtablename='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid')
Check access by user to a given resource.
Definition: api.class.php:283
Class to manage user groups.
Class to manage Dolibarr users.
Definition: user.class.php:47
put($id, $request_data=null)
Update user account.
_cleanObjectDatas($object)
Clean sensible object datas.
getInfo($includepermissions=0)
Get more properties of a user.
_cleanUserGroupListDatas($objectList)
Clean sensible user group list datas.
listGroups($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $group_ids=0, $sqlfilters='')
List Groups.
setGroup($id, $group, $entity=1)
Add a user into a group.
infoGroups($group, $load_members=0)
Get properties of an group object.
_validate($data)
Validate fields before create or update object.
getByEmail($email, $includepermissions=0)
Get properties of an user object by Email.
getGroups($id)
List the groups of a user.
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $user_ids=0, $category=0, $sqlfilters='')
List Users.
post($request_data=null)
Create user account.
getByLogin($login, $includepermissions=0)
Get properties of an user object by login.
__construct()
Constructor.
forgeSQLFromUniversalSearchCriteria($filter, &$error='')
forgeSQLFromUniversalSearchCriteria
isModEnabled($module)
Is Dolibarr module enabled.
$conf db
API class for accounts.
Definition: inc.php:41