. */ namespace SP\Api; defined('APP_ROOT') || die(); use Defuse\Crypto\Exception\CryptoException; use SP\Core\Crypt\Hash; use SP\Core\Crypt\Vault; use SP\Core\Exceptions\InvalidArgumentException; use SP\Core\Exceptions\SPException; use SP\Core\SessionFactory; use SP\Core\SessionUtil; use SP\DataModel\AuthTokenData; use SP\DataModel\UserLoginData; use SP\Log\Log; use SP\Mgmt\ApiTokens\ApiToken; use SP\Mgmt\Users\User; use SP\Util\Json; /** * Class ApiBase * * @package SP\Api */ abstract class ApiBase implements ApiInterface { /** * El ID de la acción * * @var int */ protected $actionId = 0; /** * El ID de usuario resuelto * * @var int */ protected $userId = 0; /** * Indica si la autentificación es correcta * * @var bool */ protected $auth = false; /** * Los parámetros de la acción a ejecutar * * @var mixed */ protected $data; /** * @var UserLoginData */ protected $UserData; /** * @var Log */ protected $Log; /** * @var AuthTokenData */ protected $ApiTokenData; /** * @param $data * @throws \SP\Core\Exceptions\SPException */ public function __construct($data) { $this->actionId = $this->getActionId($data->method); $this->ApiTokenData = ApiToken::getItem()->getTokenByToken($this->actionId, $data->params->authToken); if ($this->ApiTokenData === false) { ApiUtil::addTracking(); throw new SPException(__('Acceso no permitido', false), SPException::CRITICAL); } $this->data = $data; $this->userId = $this->ApiTokenData->getUserId(); $this->loadUserData(); if ($this->passIsNeeded()) { $this->doAuth(); } SessionFactory::setSessionType(SessionFactory::SESSION_API); $this->Log = new Log(); } /** * Devolver el código de acción a realizar a partir del nombre * * @param $action string El nombre de la acción * @return int */ protected function getActionId($action) { $actions = $this->getActions(); return isset($actions[$action]) ? $actions[$action]['id'] : 0; } /** * Cargar los datos del usuario * * @throws \SP\Core\Exceptions\SPException */ protected function loadUserData() { $this->UserData = User::getItem()->getById($this->ApiTokenData->getUserId()); SessionUtil::loadUserSession($this->UserData); } /** * @return bool */ protected abstract function passIsNeeded(); /** * Realizar la autentificación del usuario * * @throws SPException */ protected function doAuth() { if ($this->UserData->isIsDisabled() || !Hash::checkHashKey($this->getParam('tokenPass', true), $this->ApiTokenData->getHash()) ) { ApiUtil::addTracking(); throw new SPException(__('Acceso no permitido', false), SPException::CRITICAL); } } /** * Devolver el valor de un parámetro * * @param string $name Nombre del parámetro * @param bool $required Si es requerido * @param mixed $default Valor por defecto * @return int|string * @throws SPException */ protected function getParam($name, $required = false, $default = null) { if ($required === true && !isset($this->data->params->$name)) { throw new InvalidArgumentException(SPException::WARNING, __('Parámetros incorrectos', false), $this->getHelp($this->data->method)); } if (isset($this->data->params->$name)) { return $this->data->params->$name; } return $default; } /** * Devolver la clave maestra * * @return string * @throws SPException */ protected function getMPass() { try { /** @var Vault $Vault */ $Vault = unserialize($this->ApiTokenData->getVault()); if ($Vault && $pass = $Vault->getData($this->getParam('tokenPass') . $this->getParam('authToken'))) { return $pass; } else { throw new SPException(__('Error interno', false), SPException::ERROR, __('Datos inválidos', false)); } } catch (CryptoException $e) { throw new SPException(__('Error interno', false), SPException::ERROR, $e->getMessage()); } } /** * Comprobar el acceso a la acción * * @param $action * @throws SPException */ protected function checkActionAccess($action) { if ($this->actionId !== $action) { ApiUtil::addTracking(); throw new SPException(__('Acceso no permitido', false), SPException::CRITICAL); } } /** * Devuelve una respuesta en formato JSON con el estado y el mensaje. * * {"jsonrpc": "2.0", "result": 19, "id": 3} * * @param string $data Los datos a devolver * @return string La cadena en formato JSON * @throws SPException */ protected function wrapJSON(&$data) { $json = [ 'jsonrpc' => '2.0', 'result' => $data, 'id' => $this->data->id ]; return Json::getJson($json); } /** * Comprobar si se ha realizado la autentificación * * @throws SPException */ protected function checkAuth() { if ($this->auth === false) { ApiUtil::addTracking(); throw new SPException(__('Acceso no permitido', false), SPException::CRITICAL); } } }