diff --git a/inc/SP/Account/Account.class.php b/inc/SP/Account/Account.class.php index b66ff933..b5a2cfdd 100644 --- a/inc/SP/Account/Account.class.php +++ b/inc/SP/Account/Account.class.php @@ -365,18 +365,19 @@ class Account extends AccountBase implements AccountInterface /** * Incrementa el contador de visitas de una cuenta en la BBDD * + * @param int $id * @return bool * @throws \SP\Core\Exceptions\QueryException * @throws \SP\Core\Exceptions\ConstraintException */ - public function incrementViewCounter() + public function incrementViewCounter($id = null) { $query = /** @lang SQL */ 'UPDATE accounts SET account_countView = (account_countView + 1) WHERE account_id = ? LIMIT 1'; $Data = new QueryData(); $Data->setQuery($query); - $Data->addParam($this->accountData->getAccountId()); + $Data->addParam($id ?: $this->accountData->getAccountId()); return DB::getQuery($Data); } @@ -384,18 +385,19 @@ class Account extends AccountBase implements AccountInterface /** * Incrementa el contador de vista de clave de una cuenta en la BBDD * + * @param null $id * @return bool * @throws \SP\Core\Exceptions\QueryException * @throws \SP\Core\Exceptions\ConstraintException */ - public function incrementDecryptCounter() + public function incrementDecryptCounter($id = null) { $query = /** @lang SQL */ 'UPDATE accounts SET account_countDecrypt = (account_countDecrypt + 1) WHERE account_id = ? LIMIT 1'; $Data = new QueryData(); $Data->setQuery($query); - $Data->addParam($this->accountData->getAccountId()); + $Data->addParam($id ?: $this->accountData->getAccountId()); return DB::getQuery($Data); } @@ -473,4 +475,44 @@ class Account extends AccountBase implements AccountInterface return DB::getResults($Data); } + + /** + * Obtener los datos de una cuenta. + * Esta funcion realiza la consulta a la BBDD y guarda los datos en las variables de la clase. + * + * @return AccountExtData + * @throws \SP\Core\Exceptions\SPException + */ + public function getDataForLink() + { + $query = /** @lang SQL */ + 'SELECT account_name,' + . 'account_login,' + . 'account_pass,' + . 'account_key,' + . 'account_url,' + . 'account_notes,' + . 'category_name,' + . 'customer_name ' + . 'FROM accounts ' + . 'LEFT JOIN customers ON account_customerId = customer_id ' + . 'LEFT JOIN categories ON account_categoryId = category_id ' + . 'WHERE account_id = ? LIMIT 1'; + + $Data = new QueryData(); + $Data->setQuery($query); + $Data->setMapClass($this->accountData); + $Data->addParam($this->accountData->getAccountId()); + + /** @var AccountExtData|array $queryRes */ + $queryRes = DB::getResults($Data); + + if ($queryRes === false) { + throw new SPException(SPException::SP_CRITICAL, __('No se pudieron obtener los datos de la cuenta', false)); + } elseif (is_array($queryRes) && count($queryRes) === 0) { + throw new SPException(SPException::SP_CRITICAL, __('La cuenta no existe', false)); + } + + return $this->accountData; + } } \ No newline at end of file diff --git a/inc/SP/Controller/AccountController.class.php b/inc/SP/Controller/AccountController.class.php index 5f13a17c..602e01b2 100644 --- a/inc/SP/Controller/AccountController.class.php +++ b/inc/SP/Controller/AccountController.class.php @@ -41,6 +41,7 @@ use SP\Core\Init; use SP\Core\Session; use SP\Core\SessionUtil; use SP\Core\Template; +use SP\DataModel\AccountData; use SP\DataModel\AccountExtData; use SP\DataModel\CustomFieldData; use SP\DataModel\PublicLinkData; @@ -122,22 +123,12 @@ class AccountController extends ControllerBase implements ActionsInterface * Obtener la vista de detalles de cuenta para enlaces públicos * * @param PublicLinkData $PublicLinkData - * @return bool - * @throws \SP\Core\Exceptions\SPException - * @throws \SP\Core\Exceptions\FileNotFoundException - * @throws \SP\Core\Exceptions\QueryException - * @throws \SP\Core\Exceptions\ConstraintException * */ public function getAccountFromLink(PublicLinkData $PublicLinkData) { $this->setAction(self::ACTION_ACC_VIEW); - // Obtener los datos de la cuenta antes y comprobar el acceso - if (!$this->setAccountData()) { - return false; - } - $this->view->addTemplate('account-link'); $this->view->assign('title', [ @@ -146,50 +137,27 @@ class AccountController extends ControllerBase implements ActionsInterface 'icon' => $this->icons->getIconView()->getIcon() ] ); - $this->Account->incrementViewCounter(); - $this->Account->incrementDecryptCounter(); - $AccountPassData = $this->Account->getAccountPassData(); - // Obtener la llave de la clave maestra - $securedKey = Crypt::unlockSecuredKey($PublicLinkData->getPassIV(), Config::getConfig()->getPasswordSalt() . $PublicLinkData->getLinkHash()); + try { + $Account = new Account(); + $Account->incrementViewCounter($PublicLinkData->getItemId()); + $Account->incrementDecryptCounter($PublicLinkData->getItemId()); - // Desencriptar la clave de la cuenta - $accountSecuredKey = Crypt::unlockSecuredKey($AccountPassData->getAccountKey(), Crypt::decrypt($PublicLinkData->getPass(), $securedKey)); - $accountPass = Crypt::decrypt($AccountPassData->getAccountPass(), $accountSecuredKey); + $key = Config::getConfig()->getPasswordSalt() . $PublicLinkData->getLinkHash(); + $securedKey = Crypt::unlockSecuredKey($PublicLinkData->getPassIV(), $key); - $this->view->assign('useImage', Config::getConfig()->isPublinksImageEnabled() || Config::getConfig()->isAccountPassToImage()); + /** @var AccountExtData $AccountData */ + $AccountData = unserialize(Crypt::decrypt($PublicLinkData->getData(), $securedKey, $key)); - if ($this->view->useImage) { - $accountPass = ImageUtil::convertText($accountPass); + $this->view->assign('useImage', Config::getConfig()->isPublinksImageEnabled() || Config::getConfig()->isAccountPassToImage()); + + $accountPass = $this->view->useImage ? ImageUtil::convertText($AccountData->getAccountPass()) : $AccountData->getAccountPass(); + + $this->view->assign('accountPass', $accountPass); + $this->view->assign('accountData', $AccountData); + } catch (\Exception $e) { + $this->showError(self::ERR_EXCEPTION); } - - $this->view->assign('accountPass', $accountPass); - } - - /** - * Establecer las variables que contienen la información de la cuenta. - * - * @throws \SP\Core\Exceptions\SPException - */ - private function setAccountData() - { - $Account = new Account(new AccountExtData($this->getId())); - $this->Account = $Account; - $this->AccountData = $Account->getData(); - - $this->view->assign('accountId', $this->getId()); - $this->view->assign('accountData', $this->AccountData); - $this->view->assign('gotData', $this->isGotData()); - - return true; - } - - /** - * @return int - */ - private function getId() - { - return $this->id; } /** @@ -317,8 +285,9 @@ class AccountController extends ControllerBase implements ActionsInterface $PublicLinkData = PublicLink::getItem()->getHashForItem($this->getId()); - $publicLinkUrl = (Checks::publicLinksIsEnabled() && $PublicLinkData ? Init::$WEBURI . '/index.php?h=' . $PublicLinkData->getPublicLinkHash() . '&a=link' : ''); + $publicLinkUrl = (Checks::publicLinksIsEnabled() && $PublicLinkData ? Init::$WEBURI . '/index.php?h=' . $PublicLinkData->getPublicLinkHash() . '&a=link' : null); $this->view->assign('publicLinkUrl', $publicLinkUrl); + $this->view->assign('publicLinkId', $PublicLinkData->getPublicLinkId()); $this->view->assign('accountPassDate', date('Y-m-d H:i:s', $this->AccountData->getAccountPassDate())); $this->view->assign('accountPassDateChange', date('Y-m-d', $this->AccountData->getAccountPassDateChange() ?: 0)); @@ -391,6 +360,32 @@ class AccountController extends ControllerBase implements ActionsInterface $this->setCommonData(); } + /** + * Establecer las variables que contienen la información de la cuenta. + * + * @throws \SP\Core\Exceptions\SPException + */ + private function setAccountData() + { + $Account = new Account(new AccountExtData($this->getId())); + $this->Account = $Account; + $this->AccountData = $Account->getData(); + + $this->view->assign('accountId', $this->getId()); + $this->view->assign('accountData', $this->AccountData); + $this->view->assign('gotData', $this->isGotData()); + + return true; + } + + /** + * @return int + */ + private function getId() + { + return $this->id; + } + /** * Obtener los datos para mostrar el interface para editar cuenta * diff --git a/inc/SP/Controller/ItemActionController.class.php b/inc/SP/Controller/ItemActionController.class.php index b1ec8f47..0785394d 100644 --- a/inc/SP/Controller/ItemActionController.class.php +++ b/inc/SP/Controller/ItemActionController.class.php @@ -692,6 +692,9 @@ class ItemActionController implements ItemControllerInterface * @throws \SP\Core\Exceptions\SPException * @throws \SP\Core\Exceptions\InvalidClassException * @throws \phpmailer\phpmailerException + * @throws \Defuse\Crypto\Exception\BadFormatException + * @throws \Defuse\Crypto\Exception\CryptoException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException */ protected function publicLinkAction() { diff --git a/inc/SP/DataModel/PublicLinkData.class.php b/inc/SP/DataModel/PublicLinkData.class.php index 67871ffb..3f320666 100644 --- a/inc/SP/DataModel/PublicLinkData.class.php +++ b/inc/SP/DataModel/PublicLinkData.class.php @@ -81,6 +81,10 @@ class PublicLinkData extends PublicLinkBaseData * @var array */ protected $useInfo = []; + /** + * @var string + */ + protected $data; /** * @return int @@ -289,4 +293,20 @@ class PublicLinkData extends PublicLinkBaseData { $this->useInfo[] = $useInfo; } + + /** + * @return string + */ + public function getData() + { + return $this->data; + } + + /** + * @param string $data + */ + public function setData($data) + { + $this->data = $data; + } } \ No newline at end of file diff --git a/inc/SP/Mgmt/PublicLinks/PublicLink.class.php b/inc/SP/Mgmt/PublicLinks/PublicLink.class.php index 0124581f..c3e23bf4 100644 --- a/inc/SP/Mgmt/PublicLinks/PublicLink.class.php +++ b/inc/SP/Mgmt/PublicLinks/PublicLink.class.php @@ -110,6 +110,11 @@ class PublicLink extends PublicLinkBase implements ItemInterface /** * @return $this + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + * @throws \Defuse\Crypto\Exception\CryptoException + * @throws \Defuse\Crypto\Exception\BadFormatException * @throws SPException */ public function add() @@ -123,7 +128,7 @@ class PublicLink extends PublicLinkBase implements ItemInterface $this->itemData->setMaxCountViews(Config::getConfig()->getPublinksMaxViews()); $this->calcDateExpire(); $this->createLinkHash(); - $this->createLinkPass(); + $this->setLinkData(); $query = /** @lang SQL */ 'INSERT INTO publicLinks @@ -186,6 +191,9 @@ class PublicLink extends PublicLinkBase implements ItemInterface /** * @return $this + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + * @throws \Defuse\Crypto\Exception\CryptoException + * @throws \Defuse\Crypto\Exception\BadFormatException * @throws SPException */ public function refresh() @@ -194,7 +202,7 @@ class PublicLink extends PublicLinkBase implements ItemInterface $this->calcDateExpire(); $this->createLinkHash(true); - $this->createLinkPass(); + $this->setLinkData(); $query = /** @lang SQL */ 'UPDATE publicLinks @@ -359,7 +367,7 @@ class PublicLink extends PublicLinkBase implements ItemInterface public function getHashForItem($itemId) { $query = /** @lang SQL */ - 'SELECT publicLink_hash FROM publicLinks WHERE publicLink_itemId = ? LIMIT 1'; + 'SELECT publicLink_id, publicLink_hash FROM publicLinks WHERE publicLink_itemId = ? LIMIT 1'; $Data = new QueryData(); $Data->setMapClassName($this->getDataModel()); diff --git a/inc/SP/Mgmt/PublicLinks/PublicLinkBase.class.php b/inc/SP/Mgmt/PublicLinks/PublicLinkBase.class.php index 90316d98..145bec34 100644 --- a/inc/SP/Mgmt/PublicLinks/PublicLinkBase.class.php +++ b/inc/SP/Mgmt/PublicLinks/PublicLinkBase.class.php @@ -26,10 +26,12 @@ namespace SP\Mgmt\PublicLinks; defined('APP_ROOT') || die(); +use SP\Account\Account; use SP\Config\Config; use SP\Core\Crypt\Crypt; use SP\Core\Crypt\Session as CryptSession; use SP\Core\Exceptions\SPException; +use SP\DataModel\AccountExtData; use SP\DataModel\PublicLinkData; use SP\Mgmt\ItemBase; use SP\DataModel\PublicLinkBaseData; @@ -84,6 +86,33 @@ abstract class PublicLinkBase extends ItemBase $this->itemData->setPassIV($securedKey); } + /** + * Obtener los datos de una cuenta y encriptarlos para el enlace + * + * @throws \Defuse\Crypto\Exception\CryptoException + * @throws \SP\Core\Exceptions\SPException + * @throws \Defuse\Crypto\Exception\BadFormatException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + */ + protected final function setLinkData() + { + // Obtener los datos de la cuenta + $Account = new Account(new AccountExtData($this->itemData->getItemId())); + $AccountData = $Account->getDataForLink(); + + $key = CryptSession::getSessionKey(); + $securedKey = Crypt::unlockSecuredKey($AccountData->getAccountKey(), $key); + $AccountData->setAccountPass(Crypt::decrypt($AccountData->getAccountPass(), $securedKey, $key)); + $AccountData->setAccountKey(null); + + // Encriptar los datos de la cuenta + $linkKey = Config::getConfig()->getPasswordSalt() . $this->createLinkHash(); + $linkSecuredKey = Crypt::makeSecuredKey($linkKey); + + $this->itemData->setData(Crypt::encrypt(serialize($AccountData), $linkSecuredKey, $linkKey)); + $this->itemData->setPassIV($linkSecuredKey); + } + /** * Generar el hash para el enlace * diff --git a/inc/themes/material-blue/views/account/actions.inc b/inc/themes/material-blue/views/account/actions.inc index 67cdb5f9..1939edf3 100644 --- a/inc/themes/material-blue/views/account/actions.inc +++ b/inc/themes/material-blue/views/account/actions.inc @@ -43,18 +43,34 @@ use SP\Util\Checks; isShowLink() && $AccountAcl->isShowViewPass() && $accountData->getAccountParentId() === 0 && $accountIsHistory !== 1): ?> -