2015-05-02 18:14:51 +02:00
< ? php
2015-05-06 01:25:56 +02:00
/* Copyright ( C ) 2015 Jean - François Ferry < jfefe @ aternatik . fr >
2016-09-26 02:18:11 +02:00
* Copyright ( C ) 2016 Laurent Destailleur < eldy @ users . sourceforge . net >
2015-05-06 01:25:56 +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
* along with this program . If not , see < http :// www . gnu . org / licenses />.
*/
2015-05-02 18:14:51 +02:00
2015-11-22 17:17:06 +01:00
// Create the autoloader for Luracast
require_once DOL_DOCUMENT_ROOT . '/includes/restler/framework/Luracast/Restler/AutoLoader.php' ;
call_user_func ( function () {
$loader = Luracast\Restler\AutoLoader :: instance ();
spl_autoload_register ( $loader );
return $loader ;
});
require_once DOL_DOCUMENT_ROOT . '/includes/restler/framework/Luracast/Restler/iAuthenticate.php' ;
require_once DOL_DOCUMENT_ROOT . '/includes/restler/framework/Luracast/Restler/iUseAuthentication.php' ;
require_once DOL_DOCUMENT_ROOT . '/includes/restler/framework/Luracast/Restler/Resources.php' ;
require_once DOL_DOCUMENT_ROOT . '/includes/restler/framework/Luracast/Restler/Defaults.php' ;
require_once DOL_DOCUMENT_ROOT . '/includes/restler/framework/Luracast/Restler/RestException.php' ;
2015-05-02 18:14:51 +02:00
use \Luracast\Restler\iAuthenticate ;
2015-11-22 17:17:06 +01:00
use \Luracast\Restler\iUseAuthentication ;
2015-05-02 18:14:51 +02:00
use \Luracast\Restler\Resources ;
use \Luracast\Restler\Defaults ;
2015-06-02 15:12:19 +02:00
use \Luracast\Restler\RestException ;
2015-05-02 18:14:51 +02:00
/**
2015-05-06 00:55:42 +02:00
* Dolibarr API access class
2015-05-02 18:14:51 +02:00
*
*/
class DolibarrApiAccess implements iAuthenticate
{
const REALM = 'Restricted Dolibarr API' ;
2015-05-12 16:42:35 +02:00
2015-05-02 18:14:51 +02:00
/**
2015-05-12 16:42:35 +02:00
* @ var array $requires role required by API method user / external / admin
2015-05-02 18:14:51 +02:00
*/
2015-05-03 01:54:04 +02:00
public static $requires = array ( 'user' , 'external' , 'admin' );
2015-05-12 16:42:35 +02:00
2015-05-02 23:54:35 +02:00
/**
* @ var string $role user role
*/
2015-05-02 18:14:51 +02:00
public static $role = 'user' ;
2015-05-12 16:42:35 +02:00
2015-05-03 01:54:04 +02:00
/**
2015-05-12 16:42:35 +02:00
* @ var User $user Loggued user
2015-05-03 01:54:04 +02:00
*/
2015-05-03 14:44:37 +02:00
public static $user = '' ;
2015-05-12 16:42:35 +02:00
2015-06-05 20:23:04 +02:00
// @codingStandardsIgnoreStart
2015-05-02 23:54:35 +02:00
/**
* Check access
2015-05-12 16:42:35 +02:00
*
2015-06-02 15:12:19 +02:00
* @ return bool
* @ throws RestException
2015-05-02 23:54:35 +02:00
*/
2015-06-15 13:25:02 +02:00
public function __isAllowed ()
2015-06-02 15:12:19 +02:00
{
2017-10-16 16:23:50 +02:00
global $conf , $db ;
2015-05-03 01:54:04 +02:00
2016-05-08 12:32:18 +02:00
$login = '' ;
2015-05-02 23:54:35 +02:00
$stored_key = '' ;
2015-05-12 16:42:35 +02:00
2015-05-02 18:14:51 +02:00
$userClass = Defaults :: $userIdentifierClass ;
2015-05-12 16:42:35 +02:00
2017-01-22 20:55:26 +01:00
/* foreach ( $_SERVER as $key => $val )
{
dol_syslog ( $key . ' - ' . $val );
} */
2017-06-25 12:26:16 +02:00
2017-01-22 20:55:26 +01:00
// api key can be provided in url with parameter api_key=xxx or ni header with header DOLAPIKEY:xxx
$api_key = '' ;
2017-10-16 09:29:10 +02:00
if ( isset ( $_GET [ 'api_key' ])) // For backward compatibility
2017-01-22 20:55:26 +01:00
{
// TODO Add option to disable use of api key on url. Return errors if used.
2017-10-16 09:29:10 +02:00
$api_key = $_GET [ 'api_key' ];
2017-01-22 20:55:26 +01:00
}
2017-06-25 12:26:16 +02:00
if ( isset ( $_GET [ 'DOLAPIKEY' ]))
2017-01-22 20:55:26 +01:00
{
// TODO Add option to disable use of api key on url. Return errors if used.
$api_key = $_GET [ 'DOLAPIKEY' ]; // With GET method
}
2017-06-25 12:26:16 +02:00
if ( isset ( $_SERVER [ 'HTTP_DOLAPIKEY' ])) // Param DOLAPIKEY in header can be read with HTTP_DOLAPIKEY
2017-01-22 20:55:26 +01:00
{
$api_key = $_SERVER [ 'HTTP_DOLAPIKEY' ]; // With header method (recommanded)
}
2017-06-25 12:26:16 +02:00
if ( $api_key )
2015-09-21 15:38:17 +02:00
{
2017-10-16 16:23:50 +02:00
$userentity = 0 ;
2015-05-02 23:54:35 +02:00
$sql = " SELECT u.login, u.datec, u.api_key, " ;
$sql .= " u.tms as date_modification, u.entity " ;
$sql .= " FROM " . MAIN_DB_PREFIX . " user as u " ;
2017-01-22 20:55:26 +01:00
$sql .= " WHERE u.api_key = ' " . $db -> escape ( $api_key ) . " ' " ;
2017-10-16 16:23:50 +02:00
// TODO Check if 2 users has same API key.
2017-10-19 17:30:08 +02:00
2015-06-02 15:12:19 +02:00
$result = $db -> query ( $sql );
if ( $result )
2015-05-02 23:54:35 +02:00
{
if ( $db -> num_rows ( $result ))
{
$obj = $db -> fetch_object ( $result );
$login = $obj -> login ;
$stored_key = $obj -> api_key ;
2017-10-16 16:23:50 +02:00
$userentity = $obj -> entity ;
2017-10-19 17:32:23 +02:00
if ( ! defined ( " DOLENTITY " ) && $conf -> entity != ( $obj -> entity ? $obj -> entity : 1 )) // If API was not forced with HTTP_DOLENTITY, and user is on another entity, so we reset entity to entity of user
2017-10-16 16:23:50 +02:00
{
$conf -> entity = ( $obj -> entity ? $obj -> entity : 1 );
2017-10-19 17:30:08 +02:00
// We must also reload global conf to get params from the entity
dol_syslog ( " Entity was not set on http header with HTTP_DOLAPIENTITY (recommanded for performance purpose), so we switch now on entity of user ( " . $conf -> entity . " ) and we have to reload configuration. " , LOG_WARNING );
$conf -> setValues ( $db );
2017-10-16 16:23:50 +02:00
}
2015-05-02 23:54:35 +02:00
}
}
2015-05-03 01:54:04 +02:00
else {
throw new RestException ( 503 , 'Error when fetching user api_key :' . $db -> error_msg );
}
2015-05-02 23:54:35 +02:00
2017-10-16 16:23:50 +02:00
if ( $stored_key != $api_key ) { // This should not happen since we did a search on api_key
2017-01-22 20:55:26 +01:00
$userClass :: setCacheIdentifier ( $api_key );
2015-05-02 18:14:51 +02:00
return false ;
}
2015-05-12 16:42:35 +02:00
2016-05-08 12:32:18 +02:00
if ( ! $login )
{
2017-10-16 16:23:50 +02:00
throw new RestException ( 503 , 'Error when searching login user from api key' );
2016-05-08 12:32:18 +02:00
}
2015-05-02 23:54:35 +02:00
$fuser = new User ( $db );
2017-10-16 16:23:50 +02:00
$result = $fuser -> fetch ( '' , $login , '' , 0 , ( empty ( $userentity ) ? - 1 : $conf -> entity )); // If user is not entity 0, we search in working entity $conf->entity (that may have been forced to a different value than user entity)
if ( $result <= 0 ) {
throw new RestException ( 503 , 'Error when fetching user :' . $fuser -> error . ' (conf->entity=' . $conf -> entity . ')' );
2015-05-03 01:54:04 +02:00
}
$fuser -> getrights ();
2015-05-03 14:44:37 +02:00
static :: $user = $fuser ;
2015-05-12 16:42:35 +02:00
2015-05-02 23:54:35 +02:00
if ( $fuser -> societe_id )
static :: $role = 'external' ;
2015-05-12 16:42:35 +02:00
2015-05-02 23:54:35 +02:00
if ( $fuser -> admin )
static :: $role = 'admin' ;
2015-05-02 18:14:51 +02:00
}
else
{
2017-10-16 14:56:56 +02:00
throw new RestException ( 401 , " Failed to login to API. No parameter 'HTTP_DOLAPIKEY' on HTTP header (and no parameter DOLAPIKEY in URL). " );
2015-05-02 18:14:51 +02:00
}
2015-05-03 01:54:04 +02:00
2017-10-16 16:23:50 +02:00
$userClass :: setCacheIdentifier ( static :: $role );
Resources :: $accessControlFunction = 'DolibarrApiAccess::verifyAccess' ;
$requirefortest = static :: $requires ;
if ( ! is_array ( $requirefortest )) $requirefortest = explode ( ',' , $requirefortest );
return in_array ( static :: $role , ( array ) $requirefortest ) || static :: $role == 'admin' ;
2015-05-02 18:14:51 +02:00
}
2015-05-12 16:42:35 +02:00
2015-06-02 15:12:19 +02:00
/**
* @ return string string to be used with WWW - Authenticate header
* @ example Basic
* @ example Digest
* @ example OAuth
*/
2015-06-15 13:25:02 +02:00
public function __getWWWAuthenticateString ()
2015-05-02 18:14:51 +02:00
{
2015-05-02 23:54:35 +02:00
return '' ;
2015-05-02 18:14:51 +02:00
}
2015-05-12 16:35:05 +02:00
// @codingStandardsIgnoreEnd
2015-05-12 16:42:35 +02:00
2015-05-02 18:14:51 +02:00
/**
2015-06-02 15:12:19 +02:00
* Verify access
*
* @ param array $m Properties of method
*
* @ access private
* @ return bool
*/
2015-05-02 18:14:51 +02:00
public static function verifyAccess ( array $m )
{
2015-05-03 01:54:04 +02:00
$requires = isset ( $m [ 'class' ][ 'DolibarrApiAccess' ][ 'properties' ][ 'requires' ])
2015-05-02 18:14:51 +02:00
? $m [ 'class' ][ 'DolibarrApiAccess' ][ 'properties' ][ 'requires' ]
: false ;
2015-05-12 16:42:35 +02:00
2015-05-02 18:14:51 +02:00
return $requires
2015-05-03 01:54:04 +02:00
? static :: $role == 'admin' || in_array ( static :: $role , ( array ) $requires )
2015-05-02 18:14:51 +02:00
: true ;
2015-05-12 16:42:35 +02:00
2015-05-02 18:14:51 +02:00
}
}