2016-04-10 13:57:53 +02:00
< ? php
/* Copyright ( C ) 2015 Jean - François Ferry < jfefe @ aternatik . fr >
2023-09-26 18:43:25 +02:00
* Copyright ( C ) 2020 Thibault FOUCART < support @ ptibogxiv . net >
2024-03-13 00:32:54 +01:00
* Copyright ( C ) 2024 MDW < mdeweerd @ users . noreply . github . com >
2016-04-10 13:57:53 +02:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2019-09-23 21:55:30 +02:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
2016-04-10 13:57:53 +02:00
*/
use Luracast\Restler\RestException ;
2019-01-27 13:52:08 +01:00
require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php' ;
require_once DOL_DOCUMENT_ROOT . '/user/class/usergroup.class.php' ;
2016-04-10 13:57:53 +02:00
2021-05-17 19:50:10 +02:00
2016-04-10 13:57:53 +02:00
/**
2016-06-13 23:24:54 +02:00
* API class for users
2016-04-10 13:57:53 +02:00
*
2017-10-22 15:42:19 +02:00
* @ access protected
2016-04-10 13:57:53 +02:00
* @ class DolibarrApiAccess { @ requires user , external }
*/
2016-06-13 23:24:54 +02:00
class Users extends DolibarrApi
2016-04-10 13:57:53 +02:00
{
/**
2017-10-22 15:42:19 +02:00
* @ var array $FIELDS Mandatory fields , checked when create and update object
2016-04-10 13:57:53 +02:00
*/
2023-12-04 13:53:48 +01:00
public static $FIELDS = array (
2018-08-15 14:28:34 +02:00
'login' ,
2016-04-10 13:57:53 +02:00
);
/**
2016-04-11 23:27:43 +02:00
* @ var User $user { @ type User }
2016-04-10 13:57:53 +02:00
*/
2016-04-11 23:27:43 +02:00
public $useraccount ;
2016-04-10 13:57:53 +02:00
/**
* Constructor
*/
2020-10-29 00:34:41 +01:00
public function __construct ()
{
2024-02-01 13:34:55 +01:00
global $db ;
2021-05-18 02:06:35 +02:00
2016-04-10 13:57:53 +02:00
$this -> db = $db ;
2016-04-11 23:27:43 +02:00
$this -> useraccount = new User ( $this -> db );
2016-04-10 13:57:53 +02:00
}
2017-10-22 15:42:19 +02:00
2016-09-19 02:13:16 +02:00
/**
* List Users
*
* Get a list of Users
*
* @ param string $sortfield Sort field
* @ param string $sortorder Sort order
* @ param int $limit Limit for list
* @ param int $page Page number
2023-09-26 18:43:25 +02:00
* @ param string $user_ids User ids filter field . Example : '1' or '1,2,3' { @ pattern /^ [ 0 - 9 ,] * $ / i }
2021-05-17 16:17:03 +02:00
* @ param int $category Use this param to filter list by category
2020-10-29 00:34:41 +01:00
* @ param string $sqlfilters Other criteria to filter answers separated by a comma . Syntax example " (t.ref:like:'SO-%') and (t.date_creation:<:'20160101') "
2024-01-12 17:18:52 +01:00
* @ param string $properties Restrict the data returned to these properties . Ignored if empty . Comma separated list of properties names
2016-10-25 18:33:45 +02:00
* @ return array Array of User objects
2016-09-19 02:13:16 +02:00
*/
2024-01-10 17:01:40 +01:00
public function index ( $sortfield = " t.rowid " , $sortorder = 'ASC' , $limit = 100 , $page = 0 , $user_ids = '0' , $category = 0 , $sqlfilters = '' , $properties = '' )
2020-10-29 00:34:41 +01:00
{
2024-02-01 13:34:55 +01:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'lire' ) && empty ( DolibarrApiAccess :: $user -> admin )) {
throw new RestException ( 403 , " You are not allowed to read list of users " );
2021-05-18 02:06:35 +02:00
}
2020-10-29 00:34:41 +01:00
2021-04-08 00:33:25 +02:00
$obj_ret = array ();
2020-10-29 00:34:41 +01:00
// case of external user, $societe param is ignored and replaced by user's socid
//$socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $societe;
$sql = " SELECT t.rowid " ;
2023-04-28 09:31:33 +02:00
$sql .= " FROM " . MAIN_DB_PREFIX . " user AS t LEFT JOIN " . MAIN_DB_PREFIX . " user_extrafields AS ef ON (ef.fk_object = t.rowid) " ; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields
2020-10-29 00:34:41 +01:00
if ( $category > 0 ) {
2022-01-27 10:00:26 +01:00
$sql .= " , " . $this -> db -> prefix () . " categorie_user as c " ;
2020-10-29 00:34:41 +01:00
}
$sql .= ' WHERE t.entity IN (' . getEntity ( 'user' ) . ')' ;
if ( $user_ids ) {
2021-03-22 11:30:18 +01:00
$sql .= " AND t.rowid IN ( " . $this -> db -> sanitize ( $user_ids ) . " ) " ;
2020-10-29 00:34:41 +01:00
}
// Select products of given category
if ( $category > 0 ) {
2021-06-09 15:36:47 +02:00
$sql .= " AND c.fk_categorie = " . (( int ) $category );
2021-03-22 13:31:06 +01:00
$sql .= " AND c.fk_user = t.rowid " ;
2020-10-29 00:34:41 +01:00
}
// Add sql filters
if ( $sqlfilters ) {
2021-12-20 20:49:32 +01:00
$errormessage = '' ;
2023-02-25 19:48:33 +01:00
$sql .= forgeSQLFromUniversalSearchCriteria ( $sqlfilters , $errormessage );
if ( $errormessage ) {
throw new RestException ( 400 , 'Error when validating parameter sqlfilters -> ' . $errormessage );
2020-10-29 00:34:41 +01:00
}
}
$sql .= $this -> db -> order ( $sortfield , $sortorder );
if ( $limit ) {
if ( $page < 0 ) {
$page = 0 ;
}
$offset = $limit * $page ;
$sql .= $this -> db -> plimit ( $limit + 1 , $offset );
}
$result = $this -> db -> query ( $sql );
if ( $result ) {
$i = 0 ;
$num = $this -> db -> num_rows ( $result );
$min = min ( $num , ( $limit <= 0 ? $num : $limit ));
while ( $i < $min ) {
$obj = $this -> db -> fetch_object ( $result );
$user_static = new User ( $this -> db );
if ( $user_static -> fetch ( $obj -> rowid )) {
2023-09-26 18:04:48 +02:00
$obj_ret [] = $this -> _filterObjectProperties ( $this -> _cleanObjectDatas ( $user_static ), $properties );
2020-10-29 00:34:41 +01:00
}
$i ++ ;
}
} else {
throw new RestException ( 503 , 'Error when retrieve User list : ' . $this -> db -> lasterror ());
}
2023-12-31 14:11:05 +01:00
2020-10-29 00:34:41 +01:00
return $obj_ret ;
2016-09-19 02:13:16 +02:00
}
2017-10-22 15:42:19 +02:00
2016-04-10 13:57:53 +02:00
/**
2016-04-11 23:27:43 +02:00
* Get properties of an user object
2016-04-10 13:57:53 +02:00
*
2023-09-26 18:43:25 +02:00
* @ param int $id ID of user
2020-12-24 02:33:11 +01:00
* @ param int $includepermissions Set this to 1 to have the array of permissions loaded ( not done by default for performance purpose )
2023-09-26 18:43:25 +02:00
* @ return array | mixed data without useless information
2017-10-22 15:42:19 +02:00
*
2020-12-24 02:33:11 +01:00
* @ throws RestException 401 Insufficient rights
* @ throws RestException 404 User or group not found
2016-04-10 13:57:53 +02:00
*/
2020-10-29 00:34:41 +01:00
public function get ( $id , $includepermissions = 0 )
{
2024-02-09 15:58:49 +01:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'lire' ) && empty ( DolibarrApiAccess :: $user -> admin ) && $id != 0 && DolibarrApiAccess :: $user -> id != $id ) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , 'Not allowed' );
2021-04-08 00:33:25 +02:00
}
2020-10-29 00:34:41 +01:00
if ( $id == 0 ) {
$result = $this -> useraccount -> initAsSpecimen ();
} else {
$result = $this -> useraccount -> fetch ( $id );
}
if ( ! $result ) {
2016-04-10 13:57:53 +02:00
throw new RestException ( 404 , 'User not found' );
}
2020-10-29 00:34:41 +01:00
if ( $id > 0 && ! DolibarrApi :: _checkAccessToResource ( 'user' , $this -> useraccount -> id , 'user' )) {
2024-04-02 14:47:49 +02:00
throw new RestException ( 403 , 'Access not allowed for login ' . DolibarrApiAccess :: $user -> login );
2016-04-10 13:57:53 +02:00
}
2020-08-31 17:09:14 +02:00
if ( $includepermissions ) {
$this -> useraccount -> getRights ();
}
return $this -> _cleanObjectDatas ( $this -> useraccount );
}
2020-08-31 17:11:05 +02:00
2020-08-31 17:09:14 +02:00
/**
* Get properties of an user object by login
*
2023-09-26 18:43:25 +02:00
* @ param string $login Login of user
2020-12-24 02:33:11 +01:00
* @ param int $includepermissions Set this to 1 to have the array of permissions loaded ( not done by default for performance purpose )
2023-09-26 18:43:25 +02:00
* @ return array | mixed Data without useless information
2020-08-31 17:09:14 +02:00
*
* @ url GET login / { login }
2020-08-31 17:11:05 +02:00
*
2021-09-10 13:29:19 +02:00
* @ throws RestException 400 Bad request
2023-09-26 18:43:25 +02:00
* @ throws RestException 401 Insufficient rights
* @ throws RestException 404 User or group not found
2020-08-31 17:09:14 +02:00
*/
2020-10-29 00:34:41 +01:00
public function getByLogin ( $login , $includepermissions = 0 )
{
2021-09-10 13:29:19 +02:00
if ( empty ( $login )) {
throw new RestException ( 400 , 'Bad parameters' );
}
2024-02-09 15:58:49 +01:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'lire' ) && empty ( DolibarrApiAccess :: $user -> admin ) && DolibarrApiAccess :: $user -> login != $login ) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , 'Not allowed' );
2021-04-08 00:33:25 +02:00
}
2020-08-31 17:09:14 +02:00
$result = $this -> useraccount -> fetch ( '' , $login );
2020-10-29 00:34:41 +01:00
if ( ! $result ) {
2020-08-31 17:09:14 +02:00
throw new RestException ( 404 , 'User not found' );
}
2020-10-29 00:34:41 +01:00
if ( ! DolibarrApi :: _checkAccessToResource ( 'user' , $this -> useraccount -> id , 'user' )) {
2024-04-02 14:47:49 +02:00
throw new RestException ( 403 , 'Access not allowed for login ' . DolibarrApiAccess :: $user -> login );
2020-08-31 17:09:14 +02:00
}
if ( $includepermissions ) {
$this -> useraccount -> getRights ();
}
return $this -> _cleanObjectDatas ( $this -> useraccount );
}
2020-08-31 17:11:05 +02:00
2020-08-31 17:09:14 +02:00
/**
* Get properties of an user object by Email
*
2023-09-26 18:43:25 +02:00
* @ param string $email Email of user
2020-12-24 02:33:11 +01:00
* @ param int $includepermissions Set this to 1 to have the array of permissions loaded ( not done by default for performance purpose )
2023-09-26 18:43:25 +02:00
* @ return array | mixed Data without useless information
2020-08-31 17:09:14 +02:00
*
* @ url GET email / { email }
2020-08-31 17:11:05 +02:00
*
2021-09-10 13:29:19 +02:00
* @ throws RestException 400 Bad request
2020-08-31 17:09:14 +02:00
* @ throws RestException 401 Insufficient rights
* @ throws RestException 404 User or group not found
*/
2020-10-29 00:34:41 +01:00
public function getByEmail ( $email , $includepermissions = 0 )
{
2021-09-10 13:29:19 +02:00
if ( empty ( $email )) {
throw new RestException ( 400 , 'Bad parameters' );
}
2024-02-09 15:58:49 +01:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'lire' ) && empty ( DolibarrApiAccess :: $user -> admin ) && DolibarrApiAccess :: $user -> email != $email ) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , 'Not allowed' );
2021-04-08 00:33:25 +02:00
}
2020-08-31 17:09:14 +02:00
$result = $this -> useraccount -> fetch ( '' , '' , '' , 0 , - 1 , $email );
2020-10-29 00:34:41 +01:00
if ( ! $result ) {
2020-08-31 17:09:14 +02:00
throw new RestException ( 404 , 'User not found' );
}
2020-10-29 00:34:41 +01:00
if ( ! DolibarrApi :: _checkAccessToResource ( 'user' , $this -> useraccount -> id , 'user' )) {
2024-04-02 14:47:49 +02:00
throw new RestException ( 403 , 'Access not allowed for login ' . DolibarrApiAccess :: $user -> login );
2020-08-31 17:09:14 +02:00
}
2020-02-03 03:47:45 +01:00
if ( $includepermissions ) {
$this -> useraccount -> getRights ();
}
2016-04-11 23:27:43 +02:00
return $this -> _cleanObjectDatas ( $this -> useraccount );
2016-04-10 13:57:53 +02:00
}
2017-10-22 15:42:19 +02:00
2020-10-29 00:34:41 +01:00
/**
2021-04-08 00:33:25 +02:00
* Get more properties of a user
2020-10-29 00:34:41 +01:00
*
* @ url GET / info
*
2021-06-05 01:17:16 +02:00
* @ param int $includepermissions Set this to 1 to have the array of permissions loaded ( not done by default for performance purpose )
2023-09-26 18:43:25 +02:00
* @ return array | mixed Data without useless information
2020-10-29 00:34:41 +01:00
*
* @ throws RestException 401 Insufficient rights
* @ throws RestException 404 User or group not found
*/
2020-11-28 10:28:23 +01:00
public function getInfo ( $includepermissions = 0 )
2020-10-29 00:34:41 +01:00
{
2024-03-19 22:02:42 +01:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'self' , 'creer' ) && ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'lire' ) && empty ( DolibarrApiAccess :: $user -> admin )) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , 'Not allowed' );
2021-04-08 00:33:25 +02:00
}
2020-10-29 00:34:41 +01:00
$apiUser = DolibarrApiAccess :: $user ;
$result = $this -> useraccount -> fetch ( $apiUser -> id );
if ( ! $result ) {
throw new RestException ( 404 , 'User not found' );
}
if ( ! DolibarrApi :: _checkAccessToResource ( 'user' , $this -> useraccount -> id , 'user' )) {
2024-04-02 14:47:49 +02:00
throw new RestException ( 403 , 'Access not allowed for login ' . DolibarrApiAccess :: $user -> login );
2020-10-29 00:34:41 +01:00
}
2020-11-28 10:32:02 +01:00
2020-11-28 10:28:23 +01:00
if ( $includepermissions ) {
$this -> useraccount -> getRights ();
}
2020-10-29 00:34:41 +01:00
$usergroup = new UserGroup ( $this -> db );
$userGroupList = $usergroup -> listGroupsForUser ( $apiUser -> id , false );
if ( ! is_array ( $userGroupList )) {
throw new RestException ( 404 , 'User group not found' );
}
$this -> useraccount -> user_group_list = $this -> _cleanUserGroupListDatas ( $userGroupList );
return $this -> _cleanObjectDatas ( $this -> useraccount );
}
2017-10-22 15:42:19 +02:00
2016-05-13 20:20:48 +02:00
/**
* Create user account
*
* @ param array $request_data New user data
* @ return int
2021-04-08 00:33:25 +02:00
*
* @ throws RestException 401 Not allowed
2016-05-13 20:20:48 +02:00
*/
2020-10-29 00:34:41 +01:00
public function post ( $request_data = null )
{
2021-04-08 00:33:25 +02:00
// Check user authorization
2024-02-09 15:58:49 +01:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'creer' ) && empty ( DolibarrApiAccess :: $user -> admin )) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , " User creation not allowed for login " . DolibarrApiAccess :: $user -> login );
2021-04-08 00:33:25 +02:00
}
2020-10-29 00:34:41 +01:00
// check mandatory fields
/* if ( ! isset ( $request_data [ " login " ]))
throw new RestException ( 400 , " login field missing " );
if ( ! isset ( $request_data [ " password " ]))
throw new RestException ( 400 , " password field missing " );
if ( ! isset ( $request_data [ " lastname " ]))
throw new RestException ( 400 , " lastname field missing " ); */
2021-04-08 00:33:25 +02:00
2020-10-29 00:34:41 +01:00
//assign field values
foreach ( $request_data as $field => $value ) {
2021-04-08 00:33:25 +02:00
if ( in_array ( $field , array ( 'pass_crypted' , 'pass_indatabase' , 'pass_indatabase_crypted' , 'pass_temp' , 'api_key' ))) {
// This properties can't be set/modified with API
2024-04-07 14:59:25 +02:00
throw new RestException ( 405 , 'The property ' . $field . " can't be set/modified using the APIs " );
2021-04-08 00:33:25 +02:00
}
2023-12-15 12:15:33 +01:00
if ( $field === 'caller' ) {
2024-01-12 17:18:52 +01:00
// Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
2024-04-02 12:28:55 +02:00
$this -> useraccount -> context [ 'caller' ] = sanitizeVal ( $request_data [ 'caller' ], 'aZ09' );
2023-12-15 12:15:33 +01:00
continue ;
}
2021-04-08 00:33:25 +02:00
/* if ( $field == 'pass' ) {
2024-02-09 15:58:49 +01:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'password' )) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , 'You are not allowed to modify/set password of other users' );
2021-04-08 00:33:25 +02:00
continue ;
}
}
*/
2024-04-02 12:28:55 +02:00
$this -> useraccount -> $field = $this -> _checkValForAPI ( $field , $value , $this -> useraccount );
2020-10-29 00:34:41 +01:00
}
if ( $this -> useraccount -> create ( DolibarrApiAccess :: $user ) < 0 ) {
2020-10-31 21:04:38 +01:00
throw new RestException ( 500 , 'Error creating' , array_merge ( array ( $this -> useraccount -> error ), $this -> useraccount -> errors ));
2020-10-29 00:34:41 +01:00
}
return $this -> useraccount -> id ;
}
2017-10-22 15:42:19 +02:00
2016-04-10 13:57:53 +02:00
/**
2021-04-08 00:33:25 +02:00
* Update user account
2016-04-10 13:57:53 +02:00
*
2023-09-26 18:43:25 +02:00
* @ param int $id Id of account to update
* @ param array $request_data Datas
2024-02-22 01:32:55 +01:00
* @ return Object Updated object
2020-10-29 00:34:41 +01:00
*
2024-02-01 13:34:55 +01:00
* @ throws RestException 403 Not allowed
2020-12-24 02:09:11 +01:00
* @ throws RestException 404 Not found
* @ throws RestException 500 System error
2016-04-10 13:57:53 +02:00
*/
2020-10-29 00:34:41 +01:00
public function put ( $id , $request_data = null )
{
2021-04-08 00:33:25 +02:00
// Check user authorization
2023-06-20 00:59:44 +02:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'creer' ) && empty ( DolibarrApiAccess :: $user -> admin )) {
2024-02-01 13:34:55 +01:00
throw new RestException ( 403 , " User update not allowed " );
2021-04-08 00:33:25 +02:00
}
2016-04-10 13:57:53 +02:00
2016-04-11 23:27:43 +02:00
$result = $this -> useraccount -> fetch ( $id );
2020-10-29 00:34:41 +01:00
if ( ! $result ) {
2016-04-10 13:57:53 +02:00
throw new RestException ( 404 , 'Account not found' );
}
2020-10-29 00:34:41 +01:00
if ( ! DolibarrApi :: _checkAccessToResource ( 'user' , $this -> useraccount -> id , 'user' )) {
2024-04-02 14:47:49 +02:00
throw new RestException ( 403 , 'Access not allowed for login ' . DolibarrApiAccess :: $user -> login );
2016-04-10 13:57:53 +02:00
}
2020-10-29 00:34:41 +01:00
foreach ( $request_data as $field => $value ) {
2021-04-08 00:33:25 +02:00
if ( in_array ( $field , array ( 'pass_crypted' , 'pass_indatabase' , 'pass_indatabase_crypted' , 'pass_temp' , 'api_key' ))) {
// This properties can't be set/modified with API
2024-04-07 14:59:25 +02:00
throw new RestException ( 405 , 'The property ' . $field . " can't be set/modified using the APIs " );
2021-04-08 00:33:25 +02:00
}
2023-12-15 12:15:33 +01:00
if ( $field == 'id' ) {
continue ;
}
2021-04-08 00:33:25 +02:00
if ( $field == 'pass' ) {
2024-02-09 15:58:49 +01:00
if ( $this -> useraccount -> id != DolibarrApiAccess :: $user -> id && ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'password' )) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , 'You are not allowed to modify password of other users' );
2021-04-08 00:33:25 +02:00
}
2024-02-09 15:58:49 +01:00
if ( $this -> useraccount -> id == DolibarrApiAccess :: $user -> id && ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'self' , 'password' )) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , 'You are not allowed to modify your own password' );
2021-04-08 00:33:25 +02:00
}
}
2023-12-15 12:15:33 +01:00
if ( $field === 'caller' ) {
2024-01-12 17:18:52 +01:00
// Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
2024-04-02 12:28:55 +02:00
$this -> useraccount -> context [ 'caller' ] = sanitizeVal ( $request_data [ 'caller' ], 'aZ09' );
2023-12-15 12:15:33 +01:00
continue ;
}
2021-04-08 00:33:25 +02:00
if ( DolibarrApiAccess :: $user -> admin ) { // If user for API is admin
if ( $field == 'admin' && $value != $this -> useraccount -> admin && empty ( $value )) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , 'Reseting the admin status of a user is not possible using the API' );
2021-04-08 00:33:25 +02:00
}
} else {
if ( $field == 'admin' && $value != $this -> useraccount -> admin ) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , 'Only an admin user can modify the admin status of another user' );
2021-04-08 00:33:25 +02:00
}
}
if ( $field == 'entity' && $value != $this -> useraccount -> entity ) {
2024-04-07 14:59:25 +02:00
throw new RestException ( 403 , 'Changing entity of a user using the APIs is not possible' );
2021-04-08 00:33:25 +02:00
}
2023-12-15 12:15:33 +01:00
2019-01-27 13:20:33 +01:00
// The status must be updated using setstatus() because it
// is not handled by the update() method.
2023-12-15 12:15:33 +01:00
if ( $field == 'statut' || $field == 'status' ) {
2019-01-27 13:20:33 +01:00
$result = $this -> useraccount -> setstatus ( $value );
if ( $result < 0 ) {
2020-10-29 00:34:41 +01:00
throw new RestException ( 500 , 'Error when updating status of user: ' . $this -> useraccount -> error );
2019-01-27 13:20:33 +01:00
}
} else {
2024-04-02 12:28:55 +02:00
$this -> useraccount -> $field = $this -> _checkValForAPI ( $field , $value , $this -> useraccount );
2019-01-27 13:20:33 +01:00
}
2016-04-10 13:57:53 +02:00
}
2019-01-27 13:20:33 +01:00
// If there is no error, update() returns the number of affected
// rows so if the update is a no op, the return value is zezo.
2020-10-29 00:34:41 +01:00
if ( $this -> useraccount -> update ( DolibarrApiAccess :: $user ) >= 0 ) {
2016-04-10 13:57:53 +02:00
return $this -> get ( $id );
2020-05-21 15:05:19 +02:00
} else {
2017-12-21 16:50:18 +01:00
throw new RestException ( 500 , $this -> useraccount -> error );
2017-12-01 15:39:18 +01:00
}
2020-10-29 00:34:41 +01:00
}
2016-04-27 08:59:12 +02:00
2019-01-27 13:52:08 +01:00
/**
* List the groups of a user
*
* @ param int $id Id of user
* @ return array Array of group objects
*
2020-03-17 13:50:20 +01:00
* @ throws RestException 403 Not allowed
2020-10-29 00:34:41 +01:00
* @ throws RestException 404 Not found
2019-01-27 13:52:08 +01:00
*
* @ url GET { id } / groups
*/
2019-02-25 20:35:59 +01:00
public function getGroups ( $id )
2019-01-27 13:52:08 +01:00
{
2024-02-09 15:58:49 +01:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'lire' ) && empty ( DolibarrApiAccess :: $user -> admin )) {
2020-03-17 13:50:20 +01:00
throw new RestException ( 403 );
2019-01-27 13:52:08 +01:00
}
$user = new User ( $this -> db );
$result = $user -> fetch ( $id );
2019-11-16 23:24:29 +01:00
if ( ! $result ) {
2019-01-27 13:52:08 +01:00
throw new RestException ( 404 , 'user not found' );
}
$usergroup = new UserGroup ( $this -> db );
$groups = $usergroup -> listGroupsForUser ( $id , false );
$obj_ret = array ();
foreach ( $groups as $group ) {
$obj_ret [] = $this -> _cleanObjectDatas ( $group );
}
return $obj_ret ;
}
2020-10-29 00:34:41 +01:00
/**
2018-07-24 17:16:21 +02:00
* Add a user into a group
2016-04-27 08:59:12 +02:00
*
2017-05-24 15:24:35 +02:00
* @ param int $id User ID
* @ param int $group Group ID
2018-07-25 17:00:49 +02:00
* @ param int $entity Entity ID ( valid only for superadmin in multicompany transverse mode )
2017-05-24 15:24:35 +02:00
* @ return int 1 if success
2020-10-29 00:34:41 +01:00
*
2024-02-01 13:34:55 +01:00
* @ throws RestException 403 Not allowed
2021-04-08 00:33:25 +02:00
* @ throws RestException 404 User not found
2022-03-18 16:14:20 +01:00
* @ throws RestException 500 System error
2021-04-08 00:33:25 +02:00
*
2016-06-13 23:24:54 +02:00
* @ url GET { id } / setGroup / { group }
2016-04-27 08:59:12 +02:00
*/
2020-10-29 00:34:41 +01:00
public function setGroup ( $id , $group , $entity = 1 )
{
2018-07-24 17:16:21 +02:00
global $conf ;
2023-06-20 00:59:44 +02:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'creer' ) && empty ( DolibarrApiAccess :: $user -> admin )) {
2024-02-01 13:34:55 +01:00
throw new RestException ( 403 );
2021-04-08 00:33:25 +02:00
}
2018-07-25 17:00:49 +02:00
$result = $this -> useraccount -> fetch ( $id );
2020-10-29 00:34:41 +01:00
if ( ! $result ) {
2018-07-25 17:00:49 +02:00
throw new RestException ( 404 , 'User not found' );
}
2017-10-22 15:42:19 +02:00
2020-10-29 00:34:41 +01:00
if ( ! DolibarrApi :: _checkAccessToResource ( 'user' , $this -> useraccount -> id , 'user' )) {
2024-02-01 13:34:55 +01:00
throw new RestException ( 403 , 'Access not allowed for login ' . DolibarrApiAccess :: $user -> login );
2018-07-25 17:00:49 +02:00
}
2017-10-22 15:42:19 +02:00
2023-11-27 12:08:48 +01:00
if ( isModEnabled ( 'multicompany' ) && getDolGlobalString ( 'MULTICOMPANY_TRANSVERSE_MODE' ) && ! empty ( DolibarrApiAccess :: $user -> admin ) && empty ( DolibarrApiAccess :: $user -> entity )) {
2019-11-16 23:24:29 +01:00
$entity = ( ! empty ( $entity ) ? $entity : $conf -> entity );
2020-05-21 15:05:19 +02:00
} else {
2018-07-25 17:00:49 +02:00
// 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
// hack the security by giving himself permissions on another entity.
$entity = ( DolibarrApiAccess :: $user -> entity > 0 ? DolibarrApiAccess :: $user -> entity : $conf -> entity );
}
2017-10-22 15:42:19 +02:00
2018-07-25 17:00:49 +02:00
$result = $this -> useraccount -> SetInGroup ( $group , $entity );
2020-10-29 00:34:41 +01:00
if ( ! ( $result > 0 )) {
2018-07-25 17:00:49 +02:00
throw new RestException ( 500 , $this -> useraccount -> error );
}
return 1 ;
}
2019-11-26 21:36:30 +01:00
2019-11-26 21:33:42 +01:00
/**
* List Groups
*
* Return an array with a list of Groups
2019-11-26 21:36:30 +01:00
*
2019-11-26 21:33:42 +01:00
* @ url GET / groups
*
* @ param string $sortfield Sort field
* @ param string $sortorder Sort order
* @ param int $limit Limit for list
* @ param int $page Page number
2023-09-26 18:43:25 +02:00
* @ param string $group_ids Groups ids filter field . Example : '1' or '1,2,3' { @ pattern /^ [ 0 - 9 ,] * $ / i }
2019-11-26 21:33:42 +01:00
* @ param string $sqlfilters Other criteria to filter answers separated by a comma . Syntax example " (t.ref:like:'SO-%') and (t.date_creation:<:'20160101') "
2024-01-12 17:18:52 +01:00
* @ param string $properties Restrict the data returned to these properties . Ignored if empty . Comma separated list of properties names
2019-11-26 21:33:42 +01:00
* @ return array Array of User objects
2021-04-08 00:33:25 +02:00
*
2024-02-01 13:34:55 +01:00
* @ throws RestException 403 Not allowed
2021-04-08 00:33:25 +02:00
* @ throws RestException 404 User not found
* @ throws RestException 503 Error
2019-11-26 21:33:42 +01:00
*/
2024-01-10 17:01:40 +01:00
public function listGroups ( $sortfield = " t.rowid " , $sortorder = 'ASC' , $limit = 100 , $page = 0 , $group_ids = '0' , $sqlfilters = '' , $properties = '' )
2020-10-29 00:34:41 +01:00
{
2021-05-17 19:50:10 +02:00
global $conf ;
2019-11-26 21:33:42 +01:00
2020-10-29 00:34:41 +01:00
$obj_ret = array ();
2019-11-26 21:33:42 +01:00
2024-02-09 15:58:49 +01:00
if (( ! getDolGlobalString ( 'MAIN_USE_ADVANCED_PERMS' ) && ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'lire' ) && empty ( DolibarrApiAccess :: $user -> admin )) ||
getDolGlobalString ( 'MAIN_USE_ADVANCED_PERMS' ) && ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'group_advance' , 'read' ) && empty ( DolibarrApiAccess :: $user -> admin )) {
2024-02-01 13:34:55 +01:00
throw new RestException ( 403 , " You are not allowed to read groups " );
2020-10-29 00:34:41 +01:00
}
// case of external user, $societe param is ignored and replaced by user's socid
//$socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $societe;
$sql = " SELECT t.rowid " ;
2023-04-28 09:31:33 +02:00
$sql .= " FROM " . MAIN_DB_PREFIX . " usergroup AS t LEFT JOIN " . MAIN_DB_PREFIX . " usergroup_extrafields AS ef ON (ef.fk_object = t.rowid) " ; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields
2020-10-29 00:34:41 +01:00
$sql .= ' WHERE t.entity IN (' . getEntity ( 'user' ) . ')' ;
if ( $group_ids ) {
2021-03-22 11:30:18 +01:00
$sql .= " AND t.rowid IN ( " . $this -> db -> sanitize ( $group_ids ) . " ) " ;
2020-10-29 00:34:41 +01:00
}
// Add sql filters
if ( $sqlfilters ) {
2021-12-20 20:49:32 +01:00
$errormessage = '' ;
2023-02-25 19:48:33 +01:00
$sql .= forgeSQLFromUniversalSearchCriteria ( $sqlfilters , $errormessage );
if ( $errormessage ) {
throw new RestException ( 400 , 'Error when validating parameter sqlfilters -> ' . $errormessage );
2020-10-29 00:34:41 +01:00
}
}
$sql .= $this -> db -> order ( $sortfield , $sortorder );
if ( $limit ) {
if ( $page < 0 ) {
$page = 0 ;
}
$offset = $limit * $page ;
$sql .= $this -> db -> plimit ( $limit + 1 , $offset );
}
$result = $this -> db -> query ( $sql );
if ( $result ) {
$i = 0 ;
$num = $this -> db -> num_rows ( $result );
$min = min ( $num , ( $limit <= 0 ? $num : $limit ));
while ( $i < $min ) {
$obj = $this -> db -> fetch_object ( $result );
$group_static = new UserGroup ( $this -> db );
if ( $group_static -> fetch ( $obj -> rowid )) {
2023-09-26 18:04:48 +02:00
$obj_ret [] = $this -> _filterObjectProperties ( $this -> _cleanObjectDatas ( $group_static ), $properties );
2020-10-29 00:34:41 +01:00
}
$i ++ ;
}
} else {
throw new RestException ( 503 , 'Error when retrieve Group list : ' . $this -> db -> lasterror ());
}
2023-12-31 14:11:05 +01:00
2020-10-29 00:34:41 +01:00
return $obj_ret ;
2019-11-26 21:33:42 +01:00
}
2019-11-26 21:36:30 +01:00
2019-11-26 21:33:42 +01:00
/**
2019-11-27 16:04:52 +01:00
* Get properties of an group object
2019-11-26 21:33:42 +01:00
*
2024-01-12 17:18:52 +01:00
* Return an array with group information
2019-11-26 21:36:30 +01:00
*
2019-11-26 21:34:45 +01:00
* @ url GET / groups / { group }
2019-11-26 21:33:42 +01:00
*
2023-09-26 18:43:25 +02:00
* @ param int $group ID of group
2019-11-26 21:33:42 +01:00
* @ param int $load_members Load members list or not { @ min 0 } { @ max 1 }
2023-02-08 19:09:05 +01:00
* @ return object object of User objects
2021-04-08 00:33:25 +02:00
*
2024-02-01 13:34:55 +01:00
* @ throws RestException 403 Not allowed
2021-04-08 00:33:25 +02:00
* @ throws RestException 404 User not found
2019-11-26 21:33:42 +01:00
*/
2020-10-29 00:34:41 +01:00
public function infoGroups ( $group , $load_members = 0 )
{
global $db , $conf ;
2019-11-26 21:33:42 +01:00
2024-02-09 15:58:49 +01:00
if (( ! getDolGlobalString ( 'MAIN_USE_ADVANCED_PERMS' ) && ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'lire' ) && empty ( DolibarrApiAccess :: $user -> admin )) ||
getDolGlobalString ( 'MAIN_USE_ADVANCED_PERMS' ) && ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'group_advance' , 'read' ) && empty ( DolibarrApiAccess :: $user -> admin )) {
2024-02-01 13:34:55 +01:00
throw new RestException ( 403 , " You are not allowed to read groups " );
2020-10-29 00:34:41 +01:00
}
2019-11-26 21:33:42 +01:00
2020-10-29 00:34:41 +01:00
$group_static = new UserGroup ( $this -> db );
$result = $group_static -> fetch ( $group , '' , $load_members );
2019-11-26 21:33:42 +01:00
2020-10-29 00:34:41 +01:00
if ( ! $result ) {
2019-11-26 21:33:42 +01:00
throw new RestException ( 404 , 'Group not found' );
}
2019-11-26 21:36:30 +01:00
2020-10-29 00:34:41 +01:00
return $this -> _cleanObjectDatas ( $group_static );
2019-11-26 21:33:42 +01:00
}
2016-04-27 08:59:12 +02:00
2016-04-10 13:57:53 +02:00
/**
2021-04-08 00:33:25 +02:00
* Delete account / user
2016-04-10 13:57:53 +02:00
*
* @ param int $id Account ID
* @ return array
2021-04-08 00:33:25 +02:00
*
2024-02-01 13:34:55 +01:00
* @ throws RestException 403 Not allowed
2021-04-08 00:33:25 +02:00
* @ throws RestException 404 User not found
2016-04-10 13:57:53 +02:00
*/
2020-10-29 00:34:41 +01:00
public function delete ( $id )
{
2024-02-09 15:58:49 +01:00
if ( ! DolibarrApiAccess :: $user -> hasRight ( 'user' , 'user' , 'supprimer' ) && empty ( DolibarrApiAccess :: $user -> admin )) {
2024-02-01 13:34:55 +01:00
throw new RestException ( 403 , 'Not allowed' );
2021-04-08 00:33:25 +02:00
}
2016-04-11 23:27:43 +02:00
$result = $this -> useraccount -> fetch ( $id );
2020-10-29 00:34:41 +01:00
if ( ! $result ) {
2016-04-10 13:57:53 +02:00
throw new RestException ( 404 , 'User not found' );
}
2020-10-29 00:34:41 +01:00
if ( ! DolibarrApi :: _checkAccessToResource ( 'user' , $this -> useraccount -> id , 'user' )) {
2024-02-01 13:34:55 +01:00
throw new RestException ( 403 , 'Access not allowed for login ' . DolibarrApiAccess :: $user -> login );
2016-04-10 13:57:53 +02:00
}
2020-10-29 00:34:41 +01:00
$this -> useraccount -> oldcopy = clone $this -> useraccount ;
2022-11-26 00:50:45 +01:00
if ( ! $this -> useraccount -> delete ( DolibarrApiAccess :: $user )) {
throw new RestException ( 500 );
}
return array (
'success' => array (
'code' => 200 ,
'message' => 'Ticket deleted'
)
);
2016-04-10 13:57:53 +02:00
}
2020-10-31 15:59:33 +01:00
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2017-05-16 18:12:10 +02:00
/**
* Clean sensible object datas
*
2023-09-26 18:43:25 +02:00
* @ param Object $object Object to clean
* @ return Object Object with cleaned properties
2017-05-16 18:12:10 +02:00
*/
2019-03-04 19:57:46 +01:00
protected function _cleanObjectDatas ( $object )
2017-11-25 13:17:38 +01:00
{
2020-10-31 15:59:33 +01:00
// phpcs:enable
2017-11-25 01:24:24 +01:00
global $conf ;
2017-10-22 15:42:19 +02:00
2020-10-29 00:34:41 +01:00
$object = parent :: _cleanObjectDatas ( $object );
unset ( $object -> default_values );
unset ( $object -> lastsearch_values );
unset ( $object -> lastsearch_values_tmp );
unset ( $object -> total_ht );
unset ( $object -> total_tva );
unset ( $object -> total_localtax1 );
unset ( $object -> total_localtax2 );
unset ( $object -> total_ttc );
unset ( $object -> label_incoterms );
unset ( $object -> location_incoterms );
unset ( $object -> fk_delivery_address );
unset ( $object -> fk_incoterms );
unset ( $object -> all_permissions_are_loaded );
unset ( $object -> shipping_method_id );
unset ( $object -> nb_rights );
unset ( $object -> search_sid );
unset ( $object -> ldap_sid );
unset ( $object -> clicktodial_loaded );
// List of properties never returned by API, whatever are permissions
unset ( $object -> pass );
unset ( $object -> pass_indatabase );
unset ( $object -> pass_indatabase_crypted );
unset ( $object -> pass_temp );
unset ( $object -> api_key );
unset ( $object -> clicktodial_password );
unset ( $object -> openid );
unset ( $object -> lines );
unset ( $object -> model_pdf );
2021-10-27 16:39:34 +02:00
2024-02-09 15:58:49 +01:00
$canreadsalary = (( isModEnabled ( 'salaries' ) && DolibarrApiAccess :: $user -> hasRight ( 'salaries' , 'read' )) || ! isModEnabled ( 'salaries' ));
2020-10-29 00:34:41 +01:00
if ( ! $canreadsalary ) {
2017-11-25 01:24:24 +01:00
unset ( $object -> salary );
unset ( $object -> salaryextra );
unset ( $object -> thm );
unset ( $object -> tjm );
}
2017-11-25 01:16:12 +01:00
2020-10-29 00:34:41 +01:00
return $object ;
2017-10-22 15:42:19 +02:00
}
2020-10-29 00:34:41 +01:00
/**
* Clean sensible user group list datas
*
* @ param array $objectList Array of object to clean
* @ return array Array of cleaned object properties
*/
private function _cleanUserGroupListDatas ( $objectList )
{
$cleanObjectList = array ();
foreach ( $objectList as $object ) {
$cleanObject = parent :: _cleanObjectDatas ( $object );
unset ( $cleanObject -> default_values );
unset ( $cleanObject -> lastsearch_values );
unset ( $cleanObject -> lastsearch_values_tmp );
unset ( $cleanObject -> total_ht );
unset ( $cleanObject -> total_tva );
unset ( $cleanObject -> total_localtax1 );
unset ( $cleanObject -> total_localtax2 );
unset ( $cleanObject -> total_ttc );
unset ( $cleanObject -> libelle_incoterms );
unset ( $cleanObject -> location_incoterms );
unset ( $cleanObject -> fk_delivery_address );
unset ( $cleanObject -> fk_incoterms );
unset ( $cleanObject -> all_permissions_are_loaded );
unset ( $cleanObject -> shipping_method_id );
unset ( $cleanObject -> nb_rights );
unset ( $cleanObject -> search_sid );
unset ( $cleanObject -> ldap_sid );
unset ( $cleanObject -> clicktodial_loaded );
unset ( $cleanObject -> datec );
2023-04-03 12:22:05 +02:00
unset ( $cleanObject -> tms );
2020-10-29 00:34:41 +01:00
unset ( $cleanObject -> members );
unset ( $cleanObject -> note );
unset ( $cleanObject -> note_private );
$cleanObjectList [] = $cleanObject ;
}
return $cleanObjectList ;
}
2019-11-14 17:57:29 +01:00
2016-04-10 13:57:53 +02:00
/**
* Validate fields before create or update object
2020-10-29 00:34:41 +01:00
*
2016-10-25 21:15:25 +02:00
* @ param array | null $data Data to validate
2016-04-10 13:57:53 +02:00
* @ return array
* @ throws RestException
2020-10-29 00:34:41 +01:00
*/
private function _validate ( $data )
{
$account = array ();
foreach ( Users :: $FIELDS as $field ) {
if ( ! isset ( $data [ $field ])) {
throw new RestException ( 400 , " $field field missing " );
}
$account [ $field ] = $data [ $field ];
}
return $account ;
}
2016-04-10 13:57:53 +02:00
}