From f821b716e4a9d8e5d6416aa5d683d16a3dd8c199 Mon Sep 17 00:00:00 2001 From: nuxsmin Date: Mon, 5 Mar 2018 01:33:16 +0100 Subject: [PATCH] * [ADD] Added notifications event handler * [ADD] Added account acl file based cache * [ADD] Added deep links * [FIX] Several bugfixes --- .../web/Controllers/AccountController.php | 159 +++- .../web/Controllers/ControllerBase.php | 42 +- .../Helpers/Account/AccountActionsDto.php | 12 +- .../Helpers/Account/AccountActionsHelper.php | 19 +- .../Helpers/Account/AccountHelper.php | 71 +- .../Helpers/Account/AccountHistoryHelper.php | 48 +- .../Helpers/Account/AccountSearchHelper.php | 26 +- .../Controllers/Helpers/ItemsGridHelper.php | 25 +- .../web/Controllers/IndexController.php | 4 +- .../web/Controllers/LoginController.php | 16 +- .../Controllers/NotificationController.php | 2 +- .../web/Controllers/UserController.php | 6 +- .../Controllers/UserPassResetController.php | 4 +- .../material-blue/views/_layouts/main.inc | 4 +- .../views/_partials/fixed-header.inc | 16 +- .../views/account/account-permissions.inc | 5 +- .../material-blue/views/account/account.inc | 11 +- .../material-blue/views/account/actions.inc | 2 +- .../views/account/search-rows.inc | 28 +- .../material-blue/views/login/index.inc | 7 - .../views/notification/notification.inc | 2 +- lib/Definitions.php | 9 +- lib/SP/Account/AccountAcl.php | 559 ++++--------- lib/SP/Account/AccountSearchItem.php | 77 +- lib/SP/Account/AccountUtil.php | 12 +- lib/SP/Bootstrap.php | 31 +- lib/SP/Controller/AccountController.php | 2 +- lib/SP/Controller/ItemListController.php | 2 +- lib/SP/Controller/ItemShowController.php | 2 +- lib/SP/Core/Acl/Acl.php | 46 +- lib/SP/Core/DiFactory.php | 132 --- lib/SP/Core/Events/EventMessage.php | 31 +- lib/SP/Core/Init.php | 758 ------------------ lib/SP/Core/Session/Session.php | 56 +- lib/SP/Core/UI/Theme.php | 34 +- lib/SP/DataModel/Dto/AccountAclDto.php | 20 +- lib/SP/DataModel/Dto/AccountCache.php | 20 +- .../DataModel/Dto/AccountDetailsResponse.php | 23 +- lib/SP/Http/Request.php | 6 +- lib/SP/Mvc/View/Template.php | 199 ++--- lib/SP/Providers/Log/LogHandler.php | 3 +- .../Mail/{Mailer.php => MailHandler.php} | 16 +- ...Exception.php => MailHandlerException.php} | 2 +- .../Notification/NotificationHandler.php | 128 +++ .../Account/AccountToTagRepository.php | 4 +- .../Account/AccountToUserGroupRepository.php | 8 +- .../Account/AccountToUserRepository.php | 4 +- .../EventLog/EventlogRepository.php | 6 +- .../PublicLink/PublicLinkRepository.php | 5 +- .../UserGroup/UserToUserGroupRepository.php | 68 +- lib/SP/Services/Account/AccountAclService.php | 324 ++++++++ .../Services/Account/AccountCryptService.php | 11 +- .../Account/AccountHistoryService.php | 5 +- .../Services/Account/AccountSearchService.php | 111 ++- lib/SP/Services/Account/AccountService.php | 39 +- .../Services/Account/AccountToTagService.php | 3 +- lib/SP/Services/Export/XmlExportService.php | 8 +- .../UserGroup/UserToUserGroupService.php | 45 +- lib/SP/Storage/FileCache.php | 24 + lib/SP/Storage/FileStorageInterface.php | 7 + lib/SP/Util/ArrayUtil.php | 4 + lib/SP/Util/ErrorUtil.php | 117 ++- lib/SP/Util/FileUtil.php | 60 ++ public/js/app-actions.js | 38 +- public/js/app-actions.min.js | 76 +- public/js/app-main.js | 5 +- public/js/app-main.min.js | 10 +- public/js/app-triggers.js | 17 +- public/js/app-triggers.min.js | 32 +- schemas/30018010101.sql | 14 +- 70 files changed, 1690 insertions(+), 2032 deletions(-) delete mode 100644 lib/SP/Core/DiFactory.php delete mode 100644 lib/SP/Core/Init.php rename lib/SP/Providers/Mail/{Mailer.php => MailHandler.php} (92%) rename lib/SP/Providers/Mail/{MailerException.php => MailHandlerException.php} (95%) create mode 100644 lib/SP/Providers/Notification/NotificationHandler.php create mode 100644 lib/SP/Services/Account/AccountAclService.php create mode 100644 lib/SP/Util/FileUtil.php diff --git a/app/modules/web/Controllers/AccountController.php b/app/modules/web/Controllers/AccountController.php index 53cb2b92..fdddc040 100644 --- a/app/modules/web/Controllers/AccountController.php +++ b/app/modules/web/Controllers/AccountController.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -33,8 +33,10 @@ use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Core\Exceptions\SPException; use SP\Core\Exceptions\ValidationException; +use SP\Core\Session\Session; use SP\DataModel\AccountExtData; use SP\Http\JsonResponse; +use SP\Http\Request; use SP\Modules\Web\Controllers\Helpers\Account\AccountHelper; use SP\Modules\Web\Controllers\Helpers\Account\AccountHistoryHelper; use SP\Modules\Web\Controllers\Helpers\Account\AccountPasswordHelper; @@ -44,6 +46,7 @@ use SP\Modules\Web\Controllers\Traits\ItemTrait; use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Modules\Web\Forms\AccountForm; use SP\Mvc\Controller\CrudControllerInterface; +use SP\Services\Account\AccountAclService; use SP\Services\Account\AccountHistoryService; use SP\Services\Account\AccountService; use SP\Services\Auth\AuthException; @@ -84,7 +87,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e); } } @@ -110,7 +113,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e); } } @@ -147,11 +150,15 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->eventDispatcher->notifyEvent('show.account', new Event($this)); + if ($this->isAjax === false) { + $this->upgradeView(); + } + $this->view(); } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e); } } @@ -161,7 +168,6 @@ class AccountController extends ControllerBase implements CrudControllerInterfac * @param string $hash Link's hash * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface - * @throws \SP\Core\Dic\ContainerException */ public function viewLinkAction($hash) { @@ -230,14 +236,14 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ->addDetail(__('Cliente'), $accountData->getClientName())) ); } else { - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_PAGE_NO_PERMISSION); + ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_PAGE_NO_PERMISSION, 'account-link'); } $this->view(); } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e, 'account-link'); } } @@ -262,11 +268,15 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->eventDispatcher->notifyEvent('show.account.create', new Event($this)); + if ($this->isAjax === false) { + $this->upgradeView(); + } + $this->view(); } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e); } } @@ -301,11 +311,15 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->eventDispatcher->notifyEvent('show.account.copy', new Event($this)); + if ($this->isAjax === false) { + $this->upgradeView(); + } + $this->view(); } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e); } } @@ -343,11 +357,15 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->eventDispatcher->notifyEvent('show.account.edit', new Event($this)); + if ($this->isAjax === false) { + $this->upgradeView(); + } + $this->view(); } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e); } } @@ -381,11 +399,15 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->eventDispatcher->notifyEvent('show.account.delete', new Event($this)); + if ($this->isAjax === false) { + $this->upgradeView(); + } + $this->view(); } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e); } } @@ -421,11 +443,15 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->eventDispatcher->notifyEvent('show.account.editpass', new Event($this)); + if ($this->isAjax === false) { + $this->upgradeView(); + } + $this->view(); } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e); } } @@ -459,11 +485,15 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->eventDispatcher->notifyEvent('show.account.history', new Event($this)); + if ($this->isAjax === false) { + $this->upgradeView(); + } + $this->view(); } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e); } } @@ -486,11 +516,15 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->eventDispatcher->notifyEvent('show.account.request', new Event($this)); + if ($this->isAjax === false) { + $this->upgradeView(); + } + $this->view(); } catch (\Exception $e) { processException($e); - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_EXCEPTION); + ErrorUtil::showExceptionInView($this->view, $e); } } @@ -585,11 +619,14 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->addCustomFieldsForItem(ActionsInterface::ACCOUNT, $accountId); + $accountDetails = $this->accountService->getById($accountId)->getAccountVData(); + $this->eventDispatcher->notifyEvent('create.account', new Event($this, EventMessage::factory() ->addDescription(__u('Cuenta creada')) - ->addDetail(__u('Cuenta'), $itemData->name)) + ->addDetail(__u('Cuenta'), $accountDetails->getName()) + ->addDetail(__u('Cliente'), $accountDetails->getClientName())) ); $this->returnJsonResponseData( @@ -628,11 +665,14 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->updateCustomFieldsForItem(ActionsInterface::ACCOUNT, $id); + $accountDetails = $this->accountService->getById($id)->getAccountVData(); + $this->eventDispatcher->notifyEvent('edit.account', new Event($this, EventMessage::factory() ->addDescription(__u('Cuenta actualizada')) - ->addDetail(__u('Cuenta'), $itemData->name)) + ->addDetail(__u('Cuenta'), $accountDetails->getName()) + ->addDetail(__u('Cliente'), $accountDetails->getClientName())) ); $this->returnJsonResponseData( @@ -665,15 +705,16 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $form = new AccountForm($id); $form->validate(ActionsInterface::ACCOUNT_EDIT_PASS); - $itemData = $form->getItemData(); + $this->accountService->editPassword($form->getItemData()); - $this->accountService->editPassword($itemData); + $accountDetails = $this->accountService->getById($id)->getAccountVData(); $this->eventDispatcher->notifyEvent('edit.account.pass', new Event($this, EventMessage::factory() ->addDescription(__u('Clave actualizada')) - ->addDetail(__u('Cuenta'), $itemData->name)) + ->addDetail(__u('Cuenta'), $accountDetails->getName()) + ->addDetail(__u('Cliente'), $accountDetails->getClientName())) ); $this->returnJsonResponseData( @@ -706,11 +747,14 @@ class AccountController extends ControllerBase implements CrudControllerInterfac try { $this->accountService->editRestore($historyId, $id); + $accountDetails = $this->accountService->getById($id)->getAccountVData(); + $this->eventDispatcher->notifyEvent('edit.account.restore', new Event($this, EventMessage::factory() ->addDescription(__u('Cuenta restaurada')) - ->addDetail(__u('Cuenta'), $id)) + ->addDetail(__u('Cuenta'), $accountDetails->getName()) + ->addDetail(__u('Cliente'), $accountDetails->getClientName())) ); $this->returnJsonResponseData( @@ -747,12 +791,10 @@ class AccountController extends ControllerBase implements CrudControllerInterfac new Event($this, EventMessage::factory()->addDescription(__u('Cuentas eliminadas'))) ); - $this->returnJsonResponseData( - ['nextAction' => Acl::getActionRoute(ActionsInterface::ACCOUNT_SEARCH)], - JsonResponse::JSON_SUCCESS, - __u('Cuentas eliminadas') - ); + $this->returnJsonResponseData(JsonResponse::JSON_SUCCESS, __u('Cuentas eliminadas')); } else { + $accountDetails = $this->accountService->getById($id)->getAccountVData(); + $this->accountService->delete($id); $this->deleteCustomFieldsForItem(ActionsInterface::ACCOUNT, $id); @@ -761,14 +803,11 @@ class AccountController extends ControllerBase implements CrudControllerInterfac new Event($this, EventMessage::factory() ->addDescription(__u('Cuenta eliminada')) - ->addDetail(__u('Cuenta'), $id)) + ->addDetail(__u('Cuenta'), $accountDetails->getName()) + ->addDetail(__u('Cliente'), $accountDetails->getClientName())) ); - $this->returnJsonResponseData( - ['nextAction' => Acl::getActionRoute(ActionsInterface::ACCOUNT_SEARCH)], - JsonResponse::JSON_SUCCESS, - __u('Cuenta eliminada') - ); + $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Cuenta eliminada')); } } catch (\Exception $e) { processException($e); @@ -777,6 +816,55 @@ class AccountController extends ControllerBase implements CrudControllerInterfac } } + /** + * Saves a request action + * + * @param $id Account's ID + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + */ + public function saveRequestAction($id) + { + try { + $description = Request::analyzeString('description'); + + if (empty($description)) { + throw new ValidationException(__u('Es necesaria una descripción')); + } + + $accountDetails = $this->accountService->getById($id)->getAccountVData(); + + $this->eventDispatcher->notifyEvent('request.account', + new Event($this, + EventMessage::factory() + ->addDescription(__u('Solicitud')) + ->addDetail(__u('Solicitante'), sprintf('%s (%s)', $this->userData->getName(), $this->userData->getLogin())) + ->addDetail(__u('Cuenta'), $accountDetails->getName()) + ->addDetail(__u('Cliente'), $accountDetails->getClientName()) + ->addDetail(__u('Descripción'), $description) + ->addData('accountId', $id) + ->addData('whoId', $this->userData->getId()) + ->addData('userId', $accountDetails->userId) + ->addData('userId', $accountDetails->userEditId)) + ); + + $this->returnJsonResponseData( + [ + 'itemId' => $id, + 'nextAction' => Acl::getActionRoute(ActionsInterface::ACCOUNT) + ], + JsonResponse::JSON_SUCCESS, + __u('Solicitud realizada') + ); + } catch (ValidationException $e) { + $this->returnJsonResponseException($e); + } catch (\Exception $e) { + processException($e); + + $this->returnJsonResponseException($e); + } + } + /** * Initialize class * @@ -790,6 +878,13 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->checkLoggedIn(); } + if (DEBUG === true && $this->session->getAppStatus() === Session::APP_STATUS_RELOADED) { + $this->session->resetAppStatus(); + + // Reset de los datos de ACL de cuentas + AccountAclService::clearAcl($this->session->getUserData()->getId()); + } + $this->accountService = $this->dic->get(AccountService::class); } } \ No newline at end of file diff --git a/app/modules/web/Controllers/ControllerBase.php b/app/modules/web/Controllers/ControllerBase.php index 1369cbe2..2df6bb64 100644 --- a/app/modules/web/Controllers/ControllerBase.php +++ b/app/modules/web/Controllers/ControllerBase.php @@ -34,10 +34,12 @@ use SP\Config\ConfigData; use SP\Core\Acl\Acl; use SP\Core\Events\EventDispatcher; use SP\Core\Exceptions\FileNotFoundException; +use SP\Core\Language; use SP\Core\Session\Session; use SP\Core\UI\Theme; use SP\Core\UI\ThemeIconsBase; use SP\DataModel\ProfileData; +use SP\Modules\Web\Controllers\Helpers\LayoutHelper; use SP\Mvc\Controller\ControllerTrait; use SP\Mvc\View\Template; use SP\Providers\Auth\Browser\Browser; @@ -125,6 +127,10 @@ abstract class ControllerBase * @var ContainerInterface */ protected $dic; + /** + * @var + */ + protected $isAjax = false; /** * Constructor @@ -134,7 +140,7 @@ abstract class ControllerBase * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface */ - public function __construct(Container $container, $actionName) + public final function __construct(Container $container, $actionName) { $this->dic = $container; @@ -154,6 +160,8 @@ abstract class ControllerBase $this->icons = $this->theme->getIcons(); + $this->isAjax = $this->router->request()->headers()->get('X_REQUESTED_WITH') === 'XMLHttpRequest'; + if ($this->session->isLoggedIn()) { $this->userData = clone $this->session->getUserData(); $this->userProfileData = clone $this->session->getUserProfile(); @@ -161,6 +169,8 @@ abstract class ControllerBase $this->setViewVars(); } + $this->view->assign('language', substr(Language::$globalLang, 0, 2)); + if (method_exists($this, 'initialize')) { $this->initialize(); } @@ -186,7 +196,7 @@ abstract class ControllerBase /** * Mostrar los datos de la plantilla */ - public function view() + protected function view() { try { echo $this->view->render(); @@ -202,7 +212,7 @@ abstract class ControllerBase /** * Renderizar los datos de la plantilla y devolverlos */ - public function render() + protected function render() { try { return $this->view->render(); @@ -213,10 +223,32 @@ abstract class ControllerBase } } + /** + * Upgrades a View to use a full page layout + * + * @param string $page + */ + protected function upgradeView($page = null) + { + $this->view->upgrade(); + + if ($this->view->isUpgraded() === false) { + return; + } + + $this->view->assign('contentPage', $page ?: strtolower($this->controllerName)); + + try { + $this->dic->get(LayoutHelper::class)->getFullLayout('main', $this->acl); + } catch (\Exception $e) { + processException($e); + } + } + /** * Obtener los datos para la vista de depuración */ - public function getDebug() + protected function getDebug() { global $memInit; @@ -234,7 +266,7 @@ abstract class ControllerBase * @throws \Psr\Container\NotFoundExceptionInterface * @throws AuthException */ - public function checkLoggedIn() + protected function checkLoggedIn() { if ($this->session->isLoggedIn() && $this->session->getAuthCompleted() === true diff --git a/app/modules/web/Controllers/Helpers/Account/AccountActionsDto.php b/app/modules/web/Controllers/Helpers/Account/AccountActionsDto.php index 10dde341..f98baf26 100644 --- a/app/modules/web/Controllers/Helpers/Account/AccountActionsDto.php +++ b/app/modules/web/Controllers/Helpers/Account/AccountActionsDto.php @@ -46,7 +46,7 @@ class AccountActionsDto /** * @var bool */ - private $publicLink = false; + private $publicLinkId; /** * AccountActionsDto constructor. @@ -105,16 +105,16 @@ class AccountActionsDto /** * @return bool */ - public function hasPublicLink() + public function getPublicLinkId() { - return $this->publicLink; + return $this->publicLinkId; } /** - * @param bool $publicLink + * @param bool $publicLinkId */ - public function setPublicLink($publicLink) + public function setPublicLinkId($publicLinkId) { - $this->publicLink = (bool)$publicLink; + $this->publicLinkId = (int)$publicLinkId; } } \ No newline at end of file diff --git a/app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php index 70f644b4..33919896 100644 --- a/app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php +++ b/app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -76,7 +76,6 @@ class AccountActionsHelper extends HelperBase * @param AccountAcl $accountAcl * @param AccountActionsDto $accountActionsDto * @return DataGridAction[] - * @throws \ReflectionException */ public function getActionsForAccount(AccountAcl $accountAcl, AccountActionsDto $accountActionsDto) { @@ -101,12 +100,13 @@ class AccountActionsHelper extends HelperBase if ($accountActionsDto->isHistory() === false && $accountActionsDto->isLinked() === false + && $this->configData->isPublinksEnabled() && $accountAcl->isShowLink() && $accountAcl->isShowViewPass() ) { - $action = $accountActionsDto->hasPublicLink() ? $this->getPublicLinkRefreshAction() : $this->getPublicLinkAction(); + $action = $accountActionsDto->getPublicLinkId() ? $this->getPublicLinkRefreshAction() : $this->getPublicLinkAction(); - $actionsEnabled[] = $action->addData('item-id', $accountActionsDto->getAccountId()); + $actionsEnabled[] = $action->addData('item-id', $accountActionsDto->getPublicLinkId()); } if ($accountAcl->isShowViewPass()) { @@ -143,7 +143,7 @@ class AccountActionsHelper extends HelperBase $actionsEnabled[] = $this->getEditAction()->addData('item-id', $accountActionsDto->getAccountId()); } - if ($accountAcl->getAction() === ActionsInterface::ACCOUNT_VIEW + if ($accountAcl->getActionId() === ActionsInterface::ACCOUNT_VIEW && !$accountAcl->isShowEdit() && $this->configData->isMailRequestsEnabled() ) { @@ -186,7 +186,6 @@ class AccountActionsHelper extends HelperBase /** * @return DataGridAction - * @throws \ReflectionException */ public function getDeleteAction() { @@ -248,7 +247,6 @@ class AccountActionsHelper extends HelperBase /** * @return DataGridAction - * @throws \ReflectionException */ public function getViewPassAction() { @@ -271,7 +269,6 @@ class AccountActionsHelper extends HelperBase /** * @return DataGridAction - * @throws \ReflectionException */ public function getCopyPassAction() { @@ -297,7 +294,6 @@ class AccountActionsHelper extends HelperBase /** * @return DataGridAction - * @throws \ReflectionException */ public function getCopyAction() { @@ -319,7 +315,6 @@ class AccountActionsHelper extends HelperBase /** * @return DataGridAction - * @throws \ReflectionException */ public function getEditPassAction() { @@ -341,7 +336,6 @@ class AccountActionsHelper extends HelperBase /** * @return DataGridAction - * @throws \ReflectionException */ public function getEditAction() { @@ -363,7 +357,6 @@ class AccountActionsHelper extends HelperBase /** * @return DataGridAction - * @throws \ReflectionException */ public function getRequestAction() { diff --git a/app/modules/web/Controllers/Helpers/Account/AccountHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountHelper.php index 026a3f42..a32eb485 100644 --- a/app/modules/web/Controllers/Helpers/Account/AccountHelper.php +++ b/app/modules/web/Controllers/Helpers/Account/AccountHelper.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -36,6 +36,7 @@ use SP\DataModel\Dto\AccountDetailsResponse; use SP\Modules\Web\Controllers\Helpers\HelperBase; use SP\Modules\Web\Controllers\Traits\ItemTrait; use SP\Mvc\View\Components\SelectItemAdapter; +use SP\Services\Account\AccountAclService; use SP\Services\Account\AccountHistoryService; use SP\Services\Account\AccountService; use SP\Services\Category\CategoryService; @@ -100,17 +101,14 @@ class AccountHelper extends HelperBase * @throws UpdatedMasterPassException * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface - * @throws \ReflectionException - * @throws \SP\Core\Dic\ContainerException */ public function setViewForAccount(AccountDetailsResponse $accountDetailsResponse, $actionId) { $this->accountId = $accountDetailsResponse->getAccountVData()->getId(); $this->actionId = $actionId; - $this->accountAcl = new AccountAcl($actionId); $this->checkActionAccess(); - $accountAcl = $this->checkAccess($accountDetailsResponse); + $this->accountAcl = $this->checkAccess($accountDetailsResponse); $accountData = $accountDetailsResponse->getAccountVData(); @@ -131,7 +129,7 @@ class AccountHelper extends HelperBase $this->view->assign('maxFileSize', round($this->configData->getFilesAllowedSize() / 1024, 1)); $this->view->assign('filesAllowedExts', implode(',', $this->configData->getFilesAllowedExts())); - if ($this->configData->isPublinksEnabled() && $accountAcl->isShowLink()) { + if ($this->configData->isPublinksEnabled() && $this->accountAcl->isShowLink()) { $publicLinkData = $this->publicLinkService->getHashForItem($this->accountId); $publicLinkUrl = $publicLinkData ? PublicLinkService::getLinkForHash($publicLinkData->getHash()) : null; @@ -139,11 +137,17 @@ class AccountHelper extends HelperBase $this->view->assign('publicLinkId', $publicLinkData ? $publicLinkData->getId() : 0); $this->view->assign('publicLinkShow', true); - $accountActionsDto->setPublicLink(!empty($publicLinkUrl)); + $accountActionsDto->setPublicLinkId($publicLinkData->getId()); } else { $this->view->assign('publicLinkShow', false); } + $userData = $this->session->getUserData(); + $userProfileData = $this->session->getUserProfile(); + + $this->view->assign('allowPrivate', $userProfileData->isAccPrivate() && $accountData->getUserId() === $userData->getId()); + $this->view->assign('allowPrivateGroup', $userProfileData->isAccPrivateGroup() && $accountData->getUserGroupId() === $userData->getUserGroupId()); + $this->view->assign('accountPassDate', date('Y-m-d H:i:s', $accountData->getPassDate())); $this->view->assign('accountPassDateChange', date('Y-m-d', $accountData->getPassDateChange() ?: 0)); $this->view->assign('linkedAccounts', $this->accountService->getLinked($this->accountId)); @@ -152,7 +156,7 @@ class AccountHelper extends HelperBase $this->view->assign('accountData', $accountData); $this->view->assign('gotData', true); - $this->view->assign('actions', Bootstrap::getContainer()->get(AccountActionsHelper::class)->getActionsForAccount($accountAcl, $accountActionsDto)); + $this->view->assign('accountActions', Bootstrap::getContainer()->get(AccountActionsHelper::class)->getActionsForAccount($this->accountAcl, $accountActionsDto)); $this->setViewCommon(); } @@ -165,11 +169,11 @@ class AccountHelper extends HelperBase public function checkActionAccess() { if (!$this->acl->checkUserAccess($this->actionId)) { - throw new UnauthorizedPageException(SPException::INFO); + throw new UnauthorizedPageException(UnauthorizedPageException::INFO); } if (!$this->dic->get(MasterPassService::class)->checkUserUpdateMPass($this->session->getUserData()->getLastUpdateMPass())) { - throw new UpdatedMasterPassException(SPException::INFO); + throw new UpdatedMasterPassException(UnauthorizedPageException::INFO); } } @@ -184,18 +188,20 @@ class AccountHelper extends HelperBase { $accountData = $accountDetailsResponse->getAccountVData(); - $acccountAclDto = new AccountAclDto(); - $acccountAclDto->setAccountId($accountData->getId()); - $acccountAclDto->setDateEdit(strtotime($accountData->getDateEdit())); - $acccountAclDto->setUserId($accountData->getUserId()); - $acccountAclDto->setUserGroupId($accountData->getUserGroupId()); - $acccountAclDto->setUsersId($accountDetailsResponse->getUsers()); - $acccountAclDto->setUserGroupsId($accountDetailsResponse->getUserGroups()); + $accountAclDto = new AccountAclDto(); + $accountAclDto->setAccountId($accountData->getId()); + $accountAclDto->setDateEdit(strtotime($accountData->getDateEdit())); + $accountAclDto->setUserId($accountData->getUserId()); + $accountAclDto->setUserGroupId($accountData->getUserGroupId()); + $accountAclDto->setUsersId($accountDetailsResponse->getUsers()); + $accountAclDto->setUserGroupsId($accountDetailsResponse->getUserGroups()); + $accountAclDto->setOtherUserEdit($accountData->getOtherUserEdit()); + $accountAclDto->setOtherUserGroupEdit($accountData->getOtherUserGroupEdit()); - $accountAcl = $this->accountAcl->getAcl($acccountAclDto); + $accountAcl = $this->dic->get(AccountAclService::class)->getAcl($this->actionId, $accountAclDto); - if ($accountAcl === null || !$accountAcl->checkAccountAccess()) { - throw new AccountPermissionException(SPException::INFO); + if ($accountAcl === null || $accountAcl->checkAccountAccess($this->actionId) === false) { + throw new AccountPermissionException(AccountPermissionException::INFO); } return $accountAcl; @@ -209,19 +215,15 @@ class AccountHelper extends HelperBase */ protected function setViewCommon() { - $userProfileData = $this->session->getUserProfile(); - $this->view->assign('actionId', $this->actionId); $this->view->assign('isView', $this->isView); $this->view->assign('accountIsHistory', false); $this->view->assign('customFields', $this->getCustomFieldsForItem(ActionsInterface::ACCOUNT, $this->accountId)); - $this->view->assign('categories', SelectItemAdapter::factory(CategoryService::getItemsBasic())->getItemsFromModel()); - $this->view->assign('clients', SelectItemAdapter::factory(ClientService::getItemsBasic())->getItemsFromModel()); + $this->view->assign('categories', SelectItemAdapter::factory($this->dic->get(CategoryService::class)->getAllBasic())->getItemsFromModel()); + $this->view->assign('clients', SelectItemAdapter::factory($this->dic->get(ClientService::class)->getAllForUser())->getItemsFromModel()); - $this->view->assign('allowPrivate', $userProfileData->isAccPrivate()); - $this->view->assign('allowPrivateGroup', $userProfileData->isAccPrivateGroup()); $this->view->assign('mailRequestEnabled', $this->configData->isMailRequestsEnabled()); $this->view->assign('passToImageEnabled', $this->configData->isAccountPassToImage()); @@ -240,7 +242,7 @@ class AccountHelper extends HelperBase $this->view->assign('readonly', $this->isView ? 'readonly' : ''); $this->view->assign('showViewCustomPass', $this->accountAcl->isShowViewPass()); - $this->view->assign('accountAcl', $this->accountAcl->getStoredAcl() ?: $this->accountAcl); + $this->view->assign('accountAcl', $this->accountAcl ?: $this->accountAcl); } /** @@ -252,8 +254,6 @@ class AccountHelper extends HelperBase * @throws UpdatedMasterPassException * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface - * @throws \ReflectionException - * @throws \SP\Core\Dic\ContainerException * @throws \SP\Services\Config\ParameterNotFoundException */ public function setViewForBlank($actionId) @@ -273,10 +273,15 @@ class AccountHelper extends HelperBase $this->view->assign('userGroups', $selectUserGroups->getItemsFromModel()); $this->view->assign('tags', $selectTags->getItemsFromModel()); + $userProfileData = $this->session->getUserProfile(); + + $this->view->assign('allowPrivate', $userProfileData->isAccPrivate()); + $this->view->assign('allowPrivateGroup', $userProfileData->isAccPrivateGroup()); + $this->view->assign('accountId', 0); $this->view->assign('gotData', false); - $this->view->assign('actions', Bootstrap::getContainer()->get(AccountActionsHelper::class)->getActionsForAccount($this->accountAcl, new AccountActionsDto($this->accountId))); + $this->view->assign('accountActions', Bootstrap::getContainer()->get(AccountActionsHelper::class)->getActionsForAccount($this->accountAcl, new AccountActionsDto($this->accountId))); $this->setViewCommon(); } @@ -291,8 +296,6 @@ class AccountHelper extends HelperBase * @throws UpdatedMasterPassException * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface - * @throws \ReflectionException - * @throws \SP\Core\Dic\ContainerException * @throws \SP\Services\Config\ParameterNotFoundException */ public function setViewForRequest(AccountDetailsResponse $accountDetailsResponse, $actionId) @@ -308,7 +311,7 @@ class AccountHelper extends HelperBase $this->view->assign('accountId', $accountData->getId()); $this->view->assign('accountData', $accountDetailsResponse->getAccountVData()); - $this->view->assign('actions', Bootstrap::getContainer()->get(AccountActionsHelper::class)->getActionsForAccount($this->accountAcl->getStoredAcl(), new AccountActionsDto($this->accountId, null, $accountData->getParentId()))); + $this->view->assign('accountActions', Bootstrap::getContainer()->get(AccountActionsHelper::class)->getActionsForAccount($this->accountAcl, new AccountActionsDto($this->accountId, null, $accountData->getParentId()))); return true; } diff --git a/app/modules/web/Controllers/Helpers/Account/AccountHistoryHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountHistoryHelper.php index 35e4908c..c34dd5c5 100644 --- a/app/modules/web/Controllers/Helpers/Account/AccountHistoryHelper.php +++ b/app/modules/web/Controllers/Helpers/Account/AccountHistoryHelper.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -27,16 +27,18 @@ namespace SP\Modules\Web\Controllers\Helpers\Account; use SP\Account\AccountAcl; use SP\Core\Acl\AccountPermissionException; use SP\Core\Acl\Acl; +use SP\Core\Acl\UnauthorizedPageException; use SP\Core\Exceptions\SPException; use SP\DataModel\AccountHistoryData; use SP\DataModel\Dto\AccountAclDto; use SP\Modules\Web\Controllers\Helpers\HelperBase; use SP\Mvc\View\Components\SelectItemAdapter; +use SP\Services\Account\AccountAclService; use SP\Services\Account\AccountHistoryService; use SP\Services\Category\CategoryService; use SP\Services\Client\ClientService; use SP\Services\Crypt\MasterPassService; -use SP\Util\ErrorUtil; +use SP\Services\User\UpdatedMasterPassException; /** * Class AccountHistoryHelper @@ -73,27 +75,26 @@ class AccountHistoryHelper extends HelperBase /** * @param AccountHistoryData $accountHistoryData * @param int $actionId + * @throws AccountPermissionException + * @throws UnauthorizedPageException + * @throws UpdatedMasterPassException * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface - * @throws \ReflectionException - * @throws \SP\Core\Dic\ContainerException - * @throws AccountPermissionException + * @throws \SP\Services\Config\ParameterNotFoundException */ public function setView(AccountHistoryData $accountHistoryData, $actionId) { $this->actionId = $actionId; $this->accountHistoryId = $accountHistoryData->getId(); $this->accountId = $accountHistoryData->getAccountId(); - $this->accountAcl = new AccountAcl($actionId, true); - if (!$this->checkActionAccess() || !$this->checkAccess($accountHistoryData)) { - throw new AccountPermissionException(SPException::INFO); - } + $this->checkActionAccess(); + $this->checkAccess($accountHistoryData); $this->view->assign('isView', true); $this->view->assign('accountIsHistory', true); $this->view->assign('accountData', $accountHistoryData); - $this->view->assign('accountAcl', $this->accountAcl->getStoredAcl()); + $this->view->assign('accountAcl', $this->accountAcl); $this->view->assign('actionId', $this->actionId); $this->view->assign('accountId', $this->accountId); $this->view->assign('accountHistoryId', $this->accountHistoryId); @@ -106,35 +107,30 @@ class AccountHistoryHelper extends HelperBase $actions = $this->dic->get(AccountActionsHelper::class); - $this->view->assign('actions', $actions->getActionsForAccount($this->accountAcl->getStoredAcl(), new AccountActionsDto($this->accountId, $this->accountHistoryId))); + $this->view->assign('accountActions', $actions->getActionsForAccount($this->accountAcl, new AccountActionsDto($this->accountId, $this->accountHistoryId))); } /** - * @return bool + * @throws UnauthorizedPageException * @throws \SP\Services\Config\ParameterNotFoundException + * @throws UpdatedMasterPassException */ protected function checkActionAccess() { if (!$this->acl->checkUserAccess($this->actionId)) { - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_PAGE_NO_PERMISSION); - - return false; + throw new UnauthorizedPageException(UnauthorizedPageException::INFO); } if (!$this->dic->get(MasterPassService::class)->checkUserUpdateMPass($this->session->getUserData()->getLastUpdateMPass())) { - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_UPDATE_MPASS); - - return false; + throw new UpdatedMasterPassException(UpdatedMasterPassException::INFO); } - - return true; } /** * Comprobar si el usuario dispone de acceso al módulo * * @param AccountHistoryData $accountHistoryData - * @return bool + * @throws AccountPermissionException */ protected function checkAccess(AccountHistoryData $accountHistoryData) { @@ -146,13 +142,11 @@ class AccountHistoryHelper extends HelperBase $acccountAclDto->setUsersId($this->accountHistoryService->getUsersByAccountId($this->accountId)); $acccountAclDto->setUserGroupsId($this->accountHistoryService->getUserGroupsByAccountId($this->accountId)); - if (!$this->accountAcl->getAcl($acccountAclDto)->getStoredAcl()->checkAccountAccess()) { - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_ACCOUNT_NO_PERMISSION); + $this->accountAcl = $this->dic->get(AccountAclService::class)->getAcl($this->actionId, $acccountAclDto, true); - return false; + if ($this->accountAcl === null || $this->accountAcl->checkAccountAccess($this->actionId) === false) { + throw new AccountPermissionException(SPException::INFO); } - - return true; } /** diff --git a/app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php index c4afa1b3..1653ff76 100644 --- a/app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php +++ b/app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -50,15 +50,25 @@ use SP\Services\Tag\TagService; */ class AccountSearchHelper extends HelperBase { - /** @var bool Indica si el filtrado de cuentas está activo */ + /** + * @var bool Indica si el filtrado de cuentas está activo + */ private $filterOn = false; - /** @var string */ + /** + * @var string + */ private $sk; - /** @var int */ + /** + * @var int + */ private $queryTimeStart = 0; - /** @var bool */ + /** + * @var bool + */ private $isAjax = false; - /** @var AccountSearchFilter */ + /** + * @var AccountSearchFilter + */ private $accountSearchFilter; /** @@ -89,7 +99,6 @@ class AccountSearchHelper extends HelperBase * * @throws \Psr\Container\ContainerExceptionInterface * @throws \SP\Core\Exceptions\SPException - * @throws \ReflectionException */ public function getAccountSearch() { @@ -141,7 +150,6 @@ class AccountSearchHelper extends HelperBase * Devuelve la matriz a utilizar en la vista * * @return DataGrid - * @throws \ReflectionException * @throws \SP\Core\Dic\ContainerException */ private function getGrid() diff --git a/app/modules/web/Controllers/Helpers/ItemsGridHelper.php b/app/modules/web/Controllers/Helpers/ItemsGridHelper.php index 47bae90e..d746418e 100644 --- a/app/modules/web/Controllers/Helpers/ItemsGridHelper.php +++ b/app/modules/web/Controllers/Helpers/ItemsGridHelper.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -1257,11 +1257,14 @@ class ItemsGridHelper extends HelperBase $value = preg_replace('/\\d+\\.\\d+\\.\\d+\\.\\d+/', "*.*.*.*", $value); } - $text = str_replace(';;', PHP_EOL, utf8_decode($value)); + $text = str_replace(';;', PHP_EOL, $value); if (preg_match('/^SQL.*/m', $text)) { - $text = preg_replace('/([[:alpha:]_]+),/m', '\\1,
', $text); - $text = preg_replace('/(UPDATE|DELETE|TRUNCATE|INSERT|SELECT|WHERE|LEFT|ORDER|LIMIT|FROM)/m', '
\\1', $text); + $text = preg_replace([ + '/([[:alpha:]_]+),/m', + '/(UPDATE|DELETE|TRUNCATE|INSERT|SELECT|WHERE|LEFT|ORDER|LIMIT|FROM)/m'], + ['\\1,
', '
\\1'], + $text); } if (strlen($text) >= 150) { @@ -1294,6 +1297,18 @@ class ItemsGridHelper extends HelperBase $Grid->setDataActions($GridActionSearch); + $GridActionRefresh = new DataGridAction(); + $GridActionRefresh->setId(ActionsInterface::EVENTLOG_SEARCH); + $GridActionRefresh->setType(DataGridActionType::MENUBAR_ITEM); + $GridActionRefresh->setName(__('Refrescar')); + $GridActionRefresh->setTitle(__('Refrescar')); + $GridActionRefresh->setIcon($this->icons->getIconRefresh()); + $GridActionRefresh->setOnClickFunction('eventlog/search'); + $GridActionRefresh->addData('action-route', Acl::getActionRoute(ActionsInterface::EVENTLOG_SEARCH)); + $GridActionRefresh->addData('target', '#data-table-tblEventLog'); + + $Grid->setDataActions($GridActionRefresh); + $GridActionClear = new DataGridAction(); $GridActionClear->setId(ActionsInterface::EVENTLOG_CLEAR); $GridActionClear->setType(DataGridActionType::MENUBAR_ITEM); diff --git a/app/modules/web/Controllers/IndexController.php b/app/modules/web/Controllers/IndexController.php index 23278cb4..012616ca 100644 --- a/app/modules/web/Controllers/IndexController.php +++ b/app/modules/web/Controllers/IndexController.php @@ -47,8 +47,7 @@ class IndexController extends ControllerBase if (!$this->session->isLoggedIn()) { Response::redirect('index.php?r=login'); } else { - $LayoutHelper = $this->dic->get(LayoutHelper::class); - $LayoutHelper->getFullLayout('main', $this->acl); + $this->dic->get(LayoutHelper::class)->getFullLayout('main', $this->acl); $this->view(); } @@ -58,6 +57,7 @@ class IndexController extends ControllerBase * Updates checking action * * @throws \Psr\Container\ContainerExceptionInterface + * @throws \SP\Services\Auth\AuthException */ public function checkUpdatesAction() { diff --git a/app/modules/web/Controllers/LoginController.php b/app/modules/web/Controllers/LoginController.php index 9a94625f..8e7a6a20 100644 --- a/app/modules/web/Controllers/LoginController.php +++ b/app/modules/web/Controllers/LoginController.php @@ -26,9 +26,9 @@ namespace SP\Modules\Web\Controllers; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; +use SP\Core\Session\Session; use SP\Core\SessionFactory; use SP\Core\SessionUtil; -use SP\Html\Html; use SP\Http\Request; use SP\Http\Response; use SP\Modules\Web\Controllers\Helpers\LayoutHelper; @@ -98,7 +98,7 @@ class LoginController extends ControllerBase SessionUtil::cleanSession(); - $this->session->setLoggedOut(true); + $this->session->setAppStatus(Session::APP_STATUS_LOGGEDOUT); $layoutHelper = $this->dic->get(LayoutHelper::class); $layoutHelper->getCustomLayout('logout', 'logout'); @@ -132,18 +132,6 @@ class LoginController extends ControllerBase $this->view->assign('mailEnabled', $this->configData->isMailEnabled()); $this->view->assign('updated', SessionFactory::getAppUpdated()); - SessionFactory::setAppUpdated(false); - - $getParams = []; - - // Comprobar y parsear los parámetros GET para pasarlos como POST en los inputs - if (count($_GET) > 0) { - foreach ($_GET as $param => $value) { - $getParams['g_' . Html::sanitizeFull($param)] = Html::sanitizeFull($value); - } - } - - $this->view->assign('getParams', $getParams); $this->view(); } } \ No newline at end of file diff --git a/app/modules/web/Controllers/NotificationController.php b/app/modules/web/Controllers/NotificationController.php index b06df9e4..6e6fc3c8 100644 --- a/app/modules/web/Controllers/NotificationController.php +++ b/app/modules/web/Controllers/NotificationController.php @@ -94,7 +94,7 @@ class NotificationController extends ControllerBase implements CrudControllerInt */ public function viewAction($id) { - if (!$this->acl->checkUserAccess(ActionsInterface::NOTIFICATION_CREATE)) { + if (!$this->acl->checkUserAccess(ActionsInterface::NOTIFICATION_VIEW)) { return; } diff --git a/app/modules/web/Controllers/UserController.php b/app/modules/web/Controllers/UserController.php index f3b05d74..6db2180d 100644 --- a/app/modules/web/Controllers/UserController.php +++ b/app/modules/web/Controllers/UserController.php @@ -39,7 +39,7 @@ use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Modules\Web\Forms\UserForm; use SP\Mvc\Controller\CrudControllerInterface; use SP\Mvc\View\Components\SelectItemAdapter; -use SP\Providers\Mail\Mailer; +use SP\Providers\Mail\MailHandler; use SP\Services\User\UserService; use SP\Services\UserGroup\UserGroupService; use SP\Services\UserPassRecover\UserPassRecoverService; @@ -308,14 +308,14 @@ class UserController extends ControllerBase implements CrudControllerInterface * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException - * @throws \SP\Providers\Mail\MailerException + * @throws \SP\Providers\Mail\MailHandlerException * @throws \SP\Services\ServiceException */ protected function checkChangeUserPass(UserData $userData) { if ($userData->isChangePass()) { $hash = $this->dic->get(UserPassRecoverService::class)->requestForUserId($userData->getId()); - $this->dic->get(Mailer::class)->send(__('Cambio de Clave'), $userData->getEmail(), UserPassRecoverService::getMailMessage($hash)); + $this->dic->get(MailHandler::class)->send(__('Cambio de Clave'), $userData->getEmail(), UserPassRecoverService::getMailMessage($hash)); // $this->returnJsonResponse( // JsonResponse::JSON_WARNING, diff --git a/app/modules/web/Controllers/UserPassResetController.php b/app/modules/web/Controllers/UserPassResetController.php index 5f39bc2f..3d338a93 100644 --- a/app/modules/web/Controllers/UserPassResetController.php +++ b/app/modules/web/Controllers/UserPassResetController.php @@ -32,7 +32,7 @@ use SP\Http\JsonResponse; use SP\Http\Request; use SP\Modules\Web\Controllers\Helpers\LayoutHelper; use SP\Modules\Web\Controllers\Traits\JsonTrait; -use SP\Providers\Mail\Mailer; +use SP\Providers\Mail\MailHandler; use SP\Repositories\Track\TrackRequest; use SP\Services\Track\TrackService; use SP\Services\User\UserService; @@ -103,7 +103,7 @@ class UserPassResetController extends ControllerBase ->addDetail(__u('Solicitado para'), sprintf('%s (%s)', $login, $email))) ); - $this->dic->get(Mailer::class)->send(__('Cambio de Clave'), $email, UserPassRecoverService::getMailMessage($hash)); + $this->dic->get(MailHandler::class)->send(__('Cambio de Clave'), $email, UserPassRecoverService::getMailMessage($hash)); $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Solicitud enviada'), [__u('En breve recibirá un correo para completar la solicitud.')]); } catch (\Exception $e) { diff --git a/app/modules/web/themes/material-blue/views/_layouts/main.inc b/app/modules/web/themes/material-blue/views/_layouts/main.inc index 5c7154a1..a50d14ca 100644 --- a/app/modules/web/themes/material-blue/views/_layouts/main.inc +++ b/app/modules/web/themes/material-blue/views/_layouts/main.inc @@ -1,6 +1,6 @@ - + <?php echo $appInfo['appname'], ' :: ', $appInfo['appdesc']; ?> @@ -21,7 +21,7 @@
-
+
includePartial('fixed-header'); diff --git a/app/modules/web/themes/material-blue/views/_partials/fixed-header.inc b/app/modules/web/themes/material-blue/views/_partials/fixed-header.inc index 2f98d19d..d61e948b 100644 --- a/app/modules/web/themes/material-blue/views/_partials/fixed-header.inc +++ b/app/modules/web/themes/material-blue/views/_partials/fixed-header.inc @@ -159,13 +159,13 @@
- hashContentTemplates()): - foreach ($this->getContentTemplates() as $template): - include $template; - endforeach; - else: ?> -
- +
+ hashContentTemplates()): + foreach ($this->getContentTemplates() as $template): + include $template; + endforeach; + endif; ?> +
diff --git a/app/modules/web/themes/material-blue/views/account/account-permissions.inc b/app/modules/web/themes/material-blue/views/account/account-permissions.inc index 0c57fbd3..df05668d 100644 --- a/app/modules/web/themes/material-blue/views/account/account-permissions.inc +++ b/app/modules/web/themes/material-blue/views/account/account-permissions.inc @@ -67,6 +67,7 @@ + @@ -84,7 +85,7 @@ - + @@ -97,7 +98,7 @@ - + diff --git a/app/modules/web/themes/material-blue/views/account/account.inc b/app/modules/web/themes/material-blue/views/account/account.inc index bbe26aca..4538d488 100644 --- a/app/modules/web/themes/material-blue/views/account/account.inc +++ b/app/modules/web/themes/material-blue/views/account/account.inc @@ -1,6 +1,9 @@
@@ -238,7 +241,7 @@ - isShowPermission()): ?> + isShowPermission() || $allowPrivate || $allowPrivateGroup)): ?> includeTemplate('account-permissions'); ?> @@ -264,7 +267,7 @@ isShowFiles()) { + if ($gotData && $configData->isFilesEnabled() && $accountAcl->isShowFiles()) { include $this->includeTemplate('files'); } diff --git a/app/modules/web/themes/material-blue/views/account/actions.inc b/app/modules/web/themes/material-blue/views/account/actions.inc index fd2282a6..ca0ff377 100644 --- a/app/modules/web/themes/material-blue/views/account/actions.inc +++ b/app/modules/web/themes/material-blue/views/account/actions.inc @@ -4,7 +4,7 @@
    + foreach ($accountActions as $action): ?>
diff --git a/lib/Definitions.php b/lib/Definitions.php index 2f8f33b4..db6949c8 100644 --- a/lib/Definitions.php +++ b/lib/Definitions.php @@ -44,12 +44,11 @@ return [ \SP\Core\Acl\Actions::class => object(\SP\Core\Acl\Actions::class) ->constructor(object(\SP\Storage\FileCache::class), object(\SP\Storage\XmlHandler::class) ->constructor(ACTIONS_FILE)), - \SP\Core\Acl\Acl::class => object(\SP\Core\Acl\Acl::class) - ->constructor(get(\SP\Core\Session\Session::class), get(\SP\Core\Acl\Actions::class)), - \SP\Core\UI\Theme::class => object(\SP\Core\UI\Theme::class) - ->constructor(APP_MODULE), \SP\Core\Events\EventDispatcher::class => object(\SP\Core\Events\EventDispatcher::class), - \SP\Log\Log::class => object(\SP\Log\Log::class)->scope(\DI\Scope::PROTOTYPE), + \SP\Core\Acl\Acl::class => object(\SP\Core\Acl\Acl::class) + ->constructor(get(\SP\Core\Session\Session::class), get(\SP\Core\Events\EventDispatcher::class), get(\SP\Core\Acl\Actions::class)), + \SP\Core\UI\Theme::class => object(\SP\Core\UI\Theme::class) + ->constructor(APP_MODULE, get(\SP\Config\Config::class), get(\SP\Core\Session\Session::class)), \PHPMailer\PHPMailer\PHPMailer::class => object(\PHPMailer\PHPMailer\PHPMailer::class) ->constructor(true) ]; \ No newline at end of file diff --git a/lib/SP/Account/AccountAcl.php b/lib/SP/Account/AccountAcl.php index 35ecdd44..4e601dc4 100644 --- a/lib/SP/Account/AccountAcl.php +++ b/lib/SP/Account/AccountAcl.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -24,15 +24,8 @@ namespace SP\Account; -use SP\Config\ConfigData; use SP\Core\Acl\Acl; use SP\Core\Acl\ActionsInterface; -use SP\Core\Session\Session; -use SP\Core\Traits\InjectableTrait; -use SP\DataModel\Dto\AccountAclDto; -use SP\Repositories\UserGroup\UserToUserGroupRepository; -use SP\Services\User\UserLoginResponse; -use SP\Util\ArrayUtil; /** * Class AccountAcl @@ -42,158 +35,116 @@ use SP\Util\ArrayUtil; class AccountAcl { /** - * @var AccountAclDto + * @var bool */ - protected $accountAclDto; + public $userInGroups = false; + /** + * @var bool + */ + public $userInUsers = false; + /** + * @var bool + */ + public $resultView = false; + /** + * @var bool + */ + public $resultEdit = false; + /** + * @var bool + */ + public $modified = false; + /** + * @var bool + */ + public $showView = false; + /** + * @var bool + */ + public $showHistory = false; + /** + * @var bool + */ + public $showDetails = false; + /** + * @var bool + */ + public $showPass = false; + /** + * @var bool + */ + public $showFiles = false; + /** + * @var bool + */ + public $showViewPass = false; + /** + * @var bool + */ + public $showSave = false; + /** + * @var bool + */ + public $showEdit = false; + /** + * @var bool + */ + public $showEditPass = false; + /** + * @var bool + */ + public $showDelete = false; + /** + * @var bool + */ + public $showRestore = false; + /** + * @var bool + */ + public $showLink = false; + /** + * @var bool + */ + public $showCopy = false; + /** + * @var bool + */ + public $showPermission = false; + /** + * @var bool + */ + private $compiledAccountAccess = false; + /** + * @var bool + */ + private $compiledShowAccess = false; /** * @var int */ - protected $accountId; + private $accountId; /** * @var int */ - protected $action; + private $actionId; /** * @var int */ - protected $time = 0; + private $time = 0; /** * @var bool */ - protected $userInGroups = false; - /** - * @var bool - */ - protected $userInUsers = false; - /** - * @var bool - */ - protected $resultView = false; - /** - * @var bool - */ - protected $resultEdit = false; - /** - * @var bool - */ - protected $modified = false; - /** - * @var bool - */ - protected $showView = false; - /** - * @var bool - */ - protected $showHistory = false; - /** - * @var bool - */ - protected $showDetails = false; - /** - * @var bool - */ - protected $showPass = false; - /** - * @var bool - */ - protected $showFiles = false; - /** - * @var bool - */ - protected $showViewPass = false; - /** - * @var bool - */ - protected $showSave = false; - /** - * @var bool - */ - protected $showEdit = false; - /** - * @var bool - */ - protected $showEditPass = false; - /** - * @var bool - */ - protected $showDelete = false; - /** - * @var bool - */ - protected $showRestore = false; - /** - * @var bool - */ - protected $showLink = false; - /** - * @var bool - */ - protected $showCopy = false; - /** - * @var bool - */ - protected $showPermission = false; - /** - * @var UserLoginResponse - */ - protected $userData; - /** - * @var bool - */ - protected $compiled = false; - /** - * @var ConfigData; - */ - protected $configData; - /** - * @var Session - */ - protected $session; - /** - * @var \SP\Core\Acl\Acl - */ - protected $acl; - /** - * @var bool - */ - protected $isHistory; - - use InjectableTrait; + private $isHistory; /** * AccountAcl constructor. * - * @param int $action + * @param int $actionId * @param bool $isHistory - * @throws \SP\Core\Dic\ContainerException */ - public function __construct($action, $isHistory = false) + public function __construct($actionId, $isHistory = false) { - $this->injectDependencies(); - - $this->action = $action; + $this->actionId = (int)$actionId; $this->isHistory = $isHistory; - $this->userData = $this->session->getUserData(); - } - - /** - * Resetaear los datos de ACL en la sesión - */ - public static function resetData() - { - unset($_SESSION['accountAcl']); - } - - /** - * @param ConfigData $configData - * @param Session $session - * @param \SP\Core\Acl\Acl $acl - */ - public function inject(ConfigData $configData, Session $session, Acl $acl) - { - $this->configData = $configData; - $this->session = $session; - $this->acl = $acl; } /** @@ -201,9 +152,9 @@ class AccountAcl */ public function isShowDetails() { - return $this->action === Acl::ACCOUNT_VIEW - || $this->action === Acl::ACCOUNT_VIEW_HISTORY - || $this->action === Acl::ACCOUNT_DELETE; + return $this->actionId === Acl::ACCOUNT_VIEW + || $this->actionId === Acl::ACCOUNT_VIEW_HISTORY + || $this->actionId === Acl::ACCOUNT_DELETE; } /** @@ -211,8 +162,8 @@ class AccountAcl */ public function isShowPass() { - return ($this->action === Acl::ACCOUNT_CREATE - || $this->action === Acl::ACCOUNT_COPY); + return ($this->actionId === Acl::ACCOUNT_CREATE + || $this->actionId === Acl::ACCOUNT_COPY); } /** @@ -220,10 +171,9 @@ class AccountAcl */ public function isShowFiles() { - return $this->configData->isFilesEnabled() && - ($this->action === Acl::ACCOUNT_EDIT - || $this->action === Acl::ACCOUNT_VIEW - || $this->action === Acl::ACCOUNT_VIEW_HISTORY) + return ($this->actionId === Acl::ACCOUNT_EDIT + || $this->actionId === Acl::ACCOUNT_VIEW + || $this->actionId === Acl::ACCOUNT_VIEW_HISTORY) && $this->showFiles; } @@ -232,11 +182,11 @@ class AccountAcl */ public function isShowViewPass() { - return ($this->action === Acl::ACCOUNT_SEARCH - || $this->action === Acl::ACCOUNT_VIEW - || $this->action === Acl::ACCOUNT_VIEW_PASS - || $this->action === Acl::ACCOUNT_VIEW_HISTORY - || $this->action === Acl::ACCOUNT_EDIT) + return ($this->actionId === Acl::ACCOUNT_SEARCH + || $this->actionId === Acl::ACCOUNT_VIEW + || $this->actionId === Acl::ACCOUNT_VIEW_PASS + || $this->actionId === Acl::ACCOUNT_VIEW_HISTORY + || $this->actionId === Acl::ACCOUNT_EDIT) && $this->showViewPass; } @@ -245,9 +195,9 @@ class AccountAcl */ public function isShowSave() { - return $this->action === Acl::ACCOUNT_EDIT - || $this->action === Acl::ACCOUNT_CREATE - || $this->action === Acl::ACCOUNT_COPY; + return $this->actionId === Acl::ACCOUNT_EDIT + || $this->actionId === Acl::ACCOUNT_CREATE + || $this->actionId === Acl::ACCOUNT_COPY; } /** @@ -255,8 +205,8 @@ class AccountAcl */ public function isShowEdit() { - return ($this->action === Acl::ACCOUNT_SEARCH - || $this->action === Acl::ACCOUNT_VIEW) + return ($this->actionId === Acl::ACCOUNT_SEARCH + || $this->actionId === Acl::ACCOUNT_VIEW) && $this->showEdit; } @@ -265,8 +215,8 @@ class AccountAcl */ public function isShowEditPass() { - return ($this->action === Acl::ACCOUNT_EDIT - || $this->action === Acl::ACCOUNT_VIEW) + return ($this->actionId === Acl::ACCOUNT_EDIT + || $this->actionId === Acl::ACCOUNT_VIEW) && $this->showEditPass; } @@ -275,9 +225,9 @@ class AccountAcl */ public function isShowDelete() { - return ($this->action === Acl::ACCOUNT_SEARCH - || $this->action === Acl::ACCOUNT_DELETE - || $this->action === Acl::ACCOUNT_EDIT) + return ($this->actionId === Acl::ACCOUNT_SEARCH + || $this->actionId === Acl::ACCOUNT_DELETE + || $this->actionId === Acl::ACCOUNT_EDIT) && $this->showDelete; } @@ -286,7 +236,7 @@ class AccountAcl */ public function isShowRestore() { - return $this->action === Acl::ACCOUNT_VIEW_HISTORY && $this->showRestore; + return $this->actionId === Acl::ACCOUNT_VIEW_HISTORY && $this->showRestore; } /** @@ -294,7 +244,7 @@ class AccountAcl */ public function isShowLink() { - return $this->configData->isPublinksEnabled() && $this->showLink; + return $this->showLink; } /** @@ -302,8 +252,8 @@ class AccountAcl */ public function isShowHistory() { - return ($this->action === Acl::ACCOUNT_VIEW - || $this->action === Acl::ACCOUNT_VIEW_HISTORY) + return ($this->actionId === Acl::ACCOUNT_VIEW + || $this->actionId === Acl::ACCOUNT_VIEW_HISTORY) && $this->showHistory; } @@ -315,57 +265,20 @@ class AccountAcl return ($this->showView || $this->showEdit || $this->showViewPass || $this->showCopy || $this->showDelete); } - /** - * Obtener la ACL de una cuenta - * - * @param AccountAclDto $accountAclDto - * @return $this - */ - public function getAcl(AccountAclDto $accountAclDto) - { - $this->accountAclDto = $accountAclDto; - $this->accountId = $accountAclDto->getAccountId(); - $sessionAcl = $this->getStoredAcl(); - - if (null !== $sessionAcl - && !($this->modified = (int)strtotime($this->accountAclDto->getDateEdit()) > $sessionAcl->getTime()) - ) { - return $sessionAcl; - } - - return $this->updateAcl(); - } - - /** - * Devolver una ACL almacenada - * - * @return AccountAcl - */ - public function getStoredAcl() - { - $sessionAcl = $this->session->getAccountAcl($this->accountId); - - if (null !== $sessionAcl && $sessionAcl->getAction() !== $this->action) { - $sessionAcl->setAction($this->action); - } - - return $sessionAcl; - } - /** * @return int */ - public function getAction() + public function getActionId() { - return (int)$this->action; + return $this->actionId; } /** - * @param int $action + * @param int $actionId */ - public function setAction($action) + public function setActionId($actionId) { - $this->action = (int)$action; + $this->actionId = (int)$actionId; } /** @@ -377,132 +290,11 @@ class AccountAcl } /** - * Actualizar la ACL - * - * @return $this + * @param int $time */ - public function updateAcl() + public function setTime($time) { - if ($this->checkComponents()) { - $this->makeAcl(); - } - - return $this; - } - - /** - * @return bool - */ - protected function checkComponents() - { - return null !== $this->accountId && null !== $this->accountAclDto; - } - - /** - * Crear la ACL de una cuenta - */ - protected function makeAcl() - { - $this->compileAccountAccess(); - - // Mostrar historial - $this->showHistory = $this->acl->checkUserAccess(Acl::ACCOUNT_VIEW_HISTORY); - - // Mostrar lista archivos - $this->showFiles = $this->acl->checkUserAccess(Acl::ACCOUNT_FILE); - - // Mostrar acción de ver clave - $this->showViewPass = $this->checkAccountAccess(Acl::ACCOUNT_VIEW_PASS) - && $this->acl->checkUserAccess(Acl::ACCOUNT_VIEW_PASS); - - // Mostrar acción de editar - $this->showEdit = $this->checkAccountAccess(Acl::ACCOUNT_EDIT) - && $this->acl->checkUserAccess(Acl::ACCOUNT_EDIT) - && !$this->isHistory; - - // Mostrar acción de editar clave - $this->showEditPass = $this->checkAccountAccess(Acl::ACCOUNT_EDIT_PASS) - && $this->acl->checkUserAccess(Acl::ACCOUNT_EDIT_PASS) - && !$this->isHistory; - - // Mostrar acción de eliminar - $this->showDelete = $this->checkAccountAccess(Acl::ACCOUNT_DELETE) - && $this->acl->checkUserAccess(Acl::ACCOUNT_DELETE); - - // Mostrar acción de restaurar - $this->showRestore = $this->checkAccountAccess(Acl::ACCOUNT_EDIT) - && $this->acl->checkUserAccess(Acl::ACCOUNT_EDIT); - - // Mostrar acción de enlace público - $this->showLink = $this->acl->checkUserAccess(Acl::PUBLICLINK_CREATE); - - // Mostrar acción de ver cuenta - $this->showView = $this->checkAccountAccess(Acl::ACCOUNT_VIEW) - && $this->acl->checkUserAccess(Acl::ACCOUNT_VIEW); - - // Mostrar acción de copiar cuenta - $this->showCopy = $this->checkAccountAccess(Acl::ACCOUNT_COPY) - && $this->acl->checkUserAccess(Acl::ACCOUNT_COPY); - } - - /** - * Evaluar la ACL - */ - protected function compileAccountAccess() - { - if ($this->userData->getIsAdminApp() - || $this->userData->getIsAdminAcc() - ) { - $this->resultView = true; - $this->resultEdit = true; - - return; - } - - $this->userInGroups = $this->getIsUserInGroups(); - $this->userInUsers = in_array($this->userData->getId(), $this->accountAclDto->getUsersId()); - - $this->resultView = ($this->userData->getId() === $this->accountAclDto->getUserId() - || $this->userData->getUserGroupId() === $this->accountAclDto->getUserGroupId() - || $this->userInUsers - || $this->userInGroups); - - $this->resultEdit = ($this->userData->getId() === $this->accountAclDto->getUserId() - || $this->userData->getUserGroupId() === $this->accountAclDto->getUserGroupId() - || ($this->userInUsers && $this->accountAclDto->getOtherUserEdit()) - || ($this->userInGroups && $this->accountAclDto->getOtherUserGroupEdit())); - } - - /** - * Comprobar si el usuario o el grupo del usuario se encuentran los grupos asociados a la - * cuenta. - * - * @return bool - */ - protected function getIsUserInGroups() - { - // Comprobar si el usuario está vinculado desde el grupo principal de la cuenta - if (UserToUserGroupRepository::checkUserInGroup($this->accountAclDto->getUserGroupId(), $this->userData->getId())) { - return true; - } - - // Grupos en los que se encuentra el usuario - $groupsId = UserToUserGroupRepository::getGroupsForUser($this->userData->getId()); - - // Comprobar si el grupo del usuario está vinculado desde los grupos secundarios de la cuenta - foreach ($this->accountAclDto->getUserGroupsId() as $groupId) { - // Consultar el grupo principal del usuario - if ($groupId === $this->userData->getUserGroupId() - // o... permitir los grupos que no sean el principal del usuario? - || ($this->configData->isAccountFullGroupAccess() - // Comprobar si el usuario está vinculado desde los grupos secundarios de la cuenta - && ArrayUtil::checkInObjectArray($groupsId, 'groupId', $groupId)) - ) { - return true; - } - } - - return false; + $this->time = (int)$time; } /** @@ -511,11 +303,13 @@ class AccountAcl * @param null $actionId * @return bool */ - public function checkAccountAccess($actionId = null) + public function checkAccountAccess($actionId) { - $action = null === $actionId ? $this->getAction() : $actionId; + if ($this->compiledAccountAccess === false) { + return false; + } - switch ($action) { + switch ($actionId) { case ActionsInterface::ACCOUNT_VIEW: case ActionsInterface::ACCOUNT_SEARCH: case ActionsInterface::ACCOUNT_VIEW_PASS: @@ -560,9 +354,9 @@ class AccountAcl */ public function isShowCopy() { - return ($this->action === Acl::ACCOUNT_SEARCH - || $this->action === Acl::ACCOUNT_VIEW - || $this->action === Acl::ACCOUNT_EDIT) + return ($this->actionId === Acl::ACCOUNT_SEARCH + || $this->actionId === Acl::ACCOUNT_VIEW + || $this->actionId === Acl::ACCOUNT_EDIT) && $this->showCopy; } @@ -571,22 +365,7 @@ class AccountAcl */ public function isShowPermission() { - $userProfile = $this->session->getUserProfile(); - $userData = $this->session->getUserData(); - - return $userData->getIsAdminApp() - || $userData->getIsAdminAcc() - || $userProfile->isAccPermission() - || $userProfile->isAccPrivateGroup() - || $userProfile->isAccPrivate(); - } - - /** - * @param boolean $showPermission - */ - public function setShowPermission($showPermission) - { - $this->showPermission = $showPermission; + return $this->showPermission; } /** @@ -598,50 +377,50 @@ class AccountAcl } /** - * unserialize() checks for the presence of a function with the magic name __wakeup. - * If present, this function can reconstruct any resources that the object may have. - * The intended use of __wakeup is to reestablish any database connections that may have been lost during - * serialization and perform other reinitialization tasks. - * - * @return void - * @link http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.sleep - * @throws \SP\Core\Dic\ContainerException - * @throws \ReflectionException + * @param int $accountId */ - public function __wakeup() + public function setAccountId($accountId) { - $this->injectDependencies(); + $this->accountId = (int)$accountId; } /** - * serialize() checks if your class has a function with the magic name __sleep. - * If so, that function is executed prior to any serialization. - * It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized. - * If the method doesn't return anything then NULL is serialized and E_NOTICE is issued. - * The intended use of __sleep is to commit pending data or perform similar cleanup tasks. - * Also, the function is useful if you have very large objects which do not need to be saved completely. - * - * @return string[] - * @link http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.sleep + * @return bool */ - public function __sleep() + public function isHistory() { - $this->time = time(); + return $this->isHistory; + } - unset($this->accountAclDto, $this->userData, $this->session, $this->acl, $this->configData); + /** + * @return bool + */ + public function isCompiledShowAccess() + { + return $this->compiledShowAccess; + } - $props = []; + /** + * @param bool $compiledShowAccess + */ + public function setCompiledShowAccess($compiledShowAccess) + { + $this->compiledShowAccess = (bool)$compiledShowAccess; + } - foreach ((array)$this as $prop => $value) { - if ($prop !== "\0*\0configData" - && $prop !== "\0*\0accountAclDto" - && $prop !== "\0*\0userData" - && $prop !== "\0*\0acl" - && $prop !== "\0*\0session") { - $props[] = $prop; - } - } + /** + * @return bool + */ + public function isCompiledAccountAccess() + { + return $this->compiledAccountAccess; + } - return $props; + /** + * @param bool $compiledAccountAccess + */ + public function setCompiledAccountAccess($compiledAccountAccess) + { + $this->compiledAccountAccess = (bool)$compiledAccountAccess; } } \ No newline at end of file diff --git a/lib/SP/Account/AccountSearchItem.php b/lib/SP/Account/AccountSearchItem.php index 8067b58d..e1659b04 100644 --- a/lib/SP/Account/AccountSearchItem.php +++ b/lib/SP/Account/AccountSearchItem.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -27,8 +27,8 @@ namespace SP\Account; defined('APP_ROOT') || die(); use SP\Config\ConfigData; -use SP\Core\Traits\InjectableTrait; use SP\DataModel\AccountSearchVData; +use SP\DataModel\ItemData; use SP\Html\Html; /** @@ -38,19 +38,33 @@ use SP\Html\Html; */ class AccountSearchItem { - /** @var bool */ + /** + * @var bool + */ public static $accountLink = false; - /** @var bool */ + /** + * @var bool + */ public static $topNavbar = false; - /** @var bool */ + /** + * @var bool + */ public static $optionalActions = false; - /** @var bool */ + /** + * @var bool + */ public static $requestEnabled = true; - /** @var bool */ + /** + * @var bool + */ public static $wikiEnabled = false; - /** @var bool */ + /** + * @var bool + */ public static $dokuWikiEnabled = false; - /** @var bool */ + /** + * @var bool + */ public static $isDemoMode = false; /** @@ -82,15 +96,15 @@ class AccountSearchItem */ protected $textMaxLength = 60; /** - * @var array + * @var ItemData[] */ protected $users; /** - * @var array + * @var ItemData[] */ protected $tags; /** - * @var array + * @var ItemData[] */ protected $userGroups; /** @@ -102,28 +116,17 @@ class AccountSearchItem */ private $accountAcl; - use InjectableTrait; - /** * AccountsSearchItem constructor. * * @param AccountSearchVData $accountSearchVData * @param AccountAcl $accountAcl - * @throws \SP\Core\Dic\ContainerException + * @param ConfigData $configData */ - public function __construct(AccountSearchVData $accountSearchVData, AccountAcl $accountAcl) + public function __construct(AccountSearchVData $accountSearchVData, AccountAcl $accountAcl, ConfigData $configData) { - $this->injectDependencies(); - $this->accountSearchVData = $accountSearchVData; $this->accountAcl = $accountAcl; - } - - /** - * @param ConfigData $configData - */ - public function inject(ConfigData $configData) - { $this->configData = $configData; } @@ -257,18 +260,24 @@ class AccountSearchItem } /** - * @return string + * @return array */ public function getAccesses() { - $accesses = sprintf('(G) %s*
', $this->accountSearchVData->getUserGroupName()); + $accesses = [ + '(G*) ' . $this->accountSearchVData->getUserGroupName() . '', + '(U*) ' . $this->accountSearchVData->getUserLogin() . '' + ]; + + $userLabel = $this->accountSearchVData->getOtherUserEdit() === 1 ? 'U+' : 'U'; + $userGroupLabel = $this->accountSearchVData->getOtherUserGroupEdit() === 1 ? 'G+' : 'G'; foreach ($this->userGroups as $group) { - $accesses .= sprintf('(G) %s
', $group->name); + $accesses[] = sprintf('(%s) %s', $userGroupLabel, $group->getName()); } foreach ($this->users as $user) { - $accesses .= sprintf('(U) %s
', $user->login); + $accesses[] = sprintf('(%s) %s', $userLabel, $user->login); } return $accesses; @@ -364,7 +373,7 @@ class AccountSearchItem } /** - * @param array $userGroups + * @param ItemData[] $userGroups */ public function setUserGroups(array $userGroups) { @@ -372,7 +381,7 @@ class AccountSearchItem } /** - * @param array $users + * @param ItemData[] $users */ public function setUsers(array $users) { @@ -380,7 +389,7 @@ class AccountSearchItem } /** - * @return array + * @return ItemData[] */ public function getTags() { @@ -388,7 +397,7 @@ class AccountSearchItem } /** - * @param array $tags + * @param ItemData[] $tags */ public function setTags(array $tags) { diff --git a/lib/SP/Account/AccountUtil.php b/lib/SP/Account/AccountUtil.php index 9a1f5e37..0169e629 100644 --- a/lib/SP/Account/AccountUtil.php +++ b/lib/SP/Account/AccountUtil.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -256,10 +256,10 @@ class AccountUtil // Filtro usuario y grupo $filter = /** @lang SQL */ - 'A.userId = ? + '(A.userId = ? OR A.userGroupId = ? OR A.id IN (SELECT accountId AS accountId FROM AccountToUser WHERE accountId = A.id AND userId = ? UNION ALL SELECT accountId FROM AccountToUserGroup WHERE accountId = A.id AND userGroupId = ?) - OR A.userGroupId IN (SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = Account.userGroupId AND userId = ?)'; + OR A.userGroupId IN (SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = A.userGroupId AND userId = ?))'; $params = [$userData->getId(), $userData->getUserGroupId(), $userData->getId(), $userData->getUserGroupId(), $userData->getId()]; @@ -300,10 +300,10 @@ class AccountUtil // Filtro usuario y grupo $filter = /** @lang SQL */ - 'AH.userId = ? + '(AH.userId = ? OR AH.userGroupId = ? OR AH.accountId IN (SELECT accountId AS accountId FROM AccountToUser WHERE accountId = AH.accountId AND userId = ? UNION ALL SELECT accountId FROM AccountToUserGroup WHERE accountId = AH.accountId AND userGroupId = ?) - OR AH.userGroupId IN (SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = Account.userGroupId AND userId = ?)'; + OR AH.userGroupId IN (SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = AH.userGroupId AND userId = ?))'; $params = [$userData->getId(), $userData->getUserGroupId(), $userData->getId(), $userData->getUserGroupId(), $userData->getId()]; diff --git a/lib/SP/Bootstrap.php b/lib/SP/Bootstrap.php index eeb8a2d8..935fc4f1 100644 --- a/lib/SP/Bootstrap.php +++ b/lib/SP/Bootstrap.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -48,6 +48,8 @@ use SP\Core\Upgrade\Upgrade; use SP\Http\Request; use SP\Log\Log; use SP\Providers\Log\LogHandler; +use SP\Providers\Notification\NotificationHandler; +use SP\Services\UserProfile\UserProfileService; use SP\Storage\Database; use SP\Storage\DBUtil; use SP\Util\Checks; @@ -143,7 +145,9 @@ class Bootstrap $this->language = $container->get(Language::class); $this->upgrade = $container->get(Upgrade::class); - $container->get(EventDispatcher::class)->attach($container->get(LogHandler::class)); + $eventDispatcher = $container->get(EventDispatcher::class); + $eventDispatcher->attach($container->get(LogHandler::class)); + $eventDispatcher->attach($container->get(NotificationHandler::class)); $this->initRouter(); } @@ -272,26 +276,23 @@ class Bootstrap $this->initSession($this->configData->isEncryptSession()); // Volver a cargar la configuración si se recarga la página - if (!Request::checkReload()) { + if (Request::checkReload($this->router) === false) { // Cargar la configuración $this->config->loadConfig(); // Cargar el lenguaje $this->language->setLanguage(); } else { + debugLog('Browser reload'); + + $this->session->setAppStatus(Session::APP_STATUS_RELOADED); + // Cargar la configuración $this->config->loadConfig(true); // Restablecer el idioma y el tema visual $this->language->setLanguage(true); $this->theme->initTheme(true); - - if ($this->session->isLoggedIn()) { - // Recargar los permisos del perfil de usuario -// $this->session->setUserProfile(Profile::getItem()->getById($this->session->getUserData()->getUserProfileId())); - // Reset de los datos de ACL de cuentas - $this->session->resetAccountAcl(); - } } // Comprobar si es necesario cambiar a HTTPS @@ -495,6 +496,12 @@ class Bootstrap // Comprobar acciones en URL // $this->checkPreLoginActions(); + + if ($this->session->isLoggedIn() && $this->session->getAppStatus() === Session::APP_STATUS_RELOADED) { + debugLog('Reload user profile'); + // Recargar los permisos del perfil de usuario + $this->session->setUserProfile(self::$container->get(UserProfileService::class)->getById($this->session->getUserData()->getUserProfileId())->getProfile()); + } } /** @@ -625,7 +632,7 @@ class Bootstrap /** * @param Container $container - * @param string $module + * @param string $module * @throws InitializationException * @throws \DI\DependencyException * @throws \DI\NotFoundException diff --git a/lib/SP/Controller/AccountController.php b/lib/SP/Controller/AccountController.php index c5613215..76f3dc53 100644 --- a/lib/SP/Controller/AccountController.php +++ b/lib/SP/Controller/AccountController.php @@ -62,7 +62,7 @@ use SP\Util\Json; class AccountController extends ControllerBase implements ActionsInterface { /** - * @var AccountAcl + * @var \SP\Account\AccountAcl */ protected $AccountAcl; /** diff --git a/lib/SP/Controller/ItemListController.php b/lib/SP/Controller/ItemListController.php index 28f9a8ed..c8f8d2a1 100644 --- a/lib/SP/Controller/ItemListController.php +++ b/lib/SP/Controller/ItemListController.php @@ -89,7 +89,7 @@ class ItemListController extends GridTabControllerBase implements ActionsInterfa $this->view->assign('deleteEnabled', Request::analyze('del', 0)); $this->view->assign('files', FileUtil::getAccountFiles($this->view->accountId)); - if (!is_array($this->view->files) || count($this->view->files) === 0) { + if (!is_array($this->view->templates) || count($this->view->templates) === 0) { return; } } diff --git a/lib/SP/Controller/ItemShowController.php b/lib/SP/Controller/ItemShowController.php index 0327dad8..e6d6a316 100644 --- a/lib/SP/Controller/ItemShowController.php +++ b/lib/SP/Controller/ItemShowController.php @@ -600,7 +600,7 @@ class ItemShowController extends ControllerBase implements ActionsInterface, Ite $this->view->assign('deleteEnabled', Request::analyze('del', 0)); $this->view->assign('files', FileUtil::getAccountFiles($this->view->accountId)); - if (!is_array($this->view->files) || count($this->view->files) === 0) { + if (!is_array($this->view->templates) || count($this->view->templates) === 0) { return; } diff --git a/lib/SP/Core/Acl/Acl.php b/lib/SP/Core/Acl/Acl.php index 6f05795f..14517cae 100644 --- a/lib/SP/Core/Acl/Acl.php +++ b/lib/SP/Core/Acl/Acl.php @@ -3,8 +3,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -25,6 +25,9 @@ namespace SP\Core\Acl; +use SP\Core\Events\Event; +use SP\Core\Events\EventDispatcher; +use SP\Core\Events\EventMessage; use SP\Core\Session\Session; defined('APP_ROOT') || die(); @@ -42,16 +45,22 @@ class Acl implements ActionsInterface * @var Session */ private $session; + /** + * @var EventDispatcher + */ + private $eventDispatcher; /** * Acl constructor. * - * @param Session $session - * @param Actions|null $action + * @param Session $session + * @param EventDispatcher $eventDispatcher + * @param Actions|null $action */ - public function __construct(Session $session, Actions $action = null) + public function __construct(Session $session, EventDispatcher $eventDispatcher, Actions $action = null) { $this->session = $session; + $this->eventDispatcher = $eventDispatcher; self::$action = $action; } @@ -105,11 +114,7 @@ class Acl implements ActionsInterface */ public function checkUserAccess($action, $userId = 0) { - $userProfile = $this->session->getUserProfile(); - - // Comprobamos si la cache de permisos está inicializada - if (!is_object($userProfile)) { -// error_log('ACL_CACHE_MISS'); + if (!($userProfile = $this->session->getUserProfile())) { return false; } @@ -161,6 +166,7 @@ class Acl implements ActionsInterface case self::PUBLICLINK_SEARCH: return $userProfile->isMgmPublicLinks(); case self::PUBLICLINK_CREATE: + case self::PUBLICLINK_REFRESH: return ($userProfile->isMgmPublicLinks() || $userProfile->isAccPublicLinks()); case self::ACCOUNTMGR: case self::ACCOUNTMGR_SEARCH: @@ -199,18 +205,26 @@ class Acl implements ActionsInterface case self::EVENTLOG: case self::EVENTLOG_SEARCH: return $userProfile->isEvl(); + case self::ACCOUNT_REQUEST: case self::NOTIFICATION: + case self::NOTIFICATION_VIEW: case self::NOTIFICATION_SEARCH: case self::NOTIFICATION_CHECK: return true; } -// $Log = new Log(); -// $Log->getLogMessage() -// ->setAction(__FUNCTION__) -// ->addDetails(__('Acceso denegado', false), self::getActionInfo($action, false)); -// $Log->setLogLevel(Log::NOTICE); -// $Log->writeLog(); + try { + $actionName = self::$action->getActionById($action)->getName(); + } catch (ActionNotFoundException $e) { + $actionName = __u('N/D'); + } + + $this->eventDispatcher->notifyEvent('acl.deny', + new Event($this, EventMessage::factory() + ->addDescription(__u('Acceso denegado')) + ->addDetail(__u('Acción'), $actionName) + ->addDetail(__u('Usuario'), $userData->getLogin())) + ); return false; } diff --git a/lib/SP/Core/DiFactory.php b/lib/SP/Core/DiFactory.php deleted file mode 100644 index 77002ce8..00000000 --- a/lib/SP/Core/DiFactory.php +++ /dev/null @@ -1,132 +0,0 @@ -. - */ - -namespace SP\Core; - -use SP\Core\Events\EventDispatcher; -use SP\Core\Events\EventDispatcherInterface; -use SP\Core\Exceptions\InvalidClassException; -use SP\Core\UI\ThemeInterface; -use SP\Mgmt\ItemBaseInterface; -use SP\Storage\DBStorageInterface; -use SP\Storage\MySQLHandler; -use SP\Storage\XmlFileStorageInterface; -use SP\Storage\XmlHandler; - -/** - * Class SingleFactory - * - * @package SP\Core - */ -class DiFactory -{ - /** - * @var XmlFileStorageInterface - */ - private static $ConfigFactory; - /** - * @var DBStorageInterface - */ - private static $DBFactory; - /** - * @var ItemBaseInterface[] - */ - private static $ItemFactory = []; - /** - * @var ThemeInterface - */ - private static $ThemeFactory; - /** - * @var EventDispatcherInterface - */ - private static $EventDispatcher; - - /** - * Devuelve el almacenamiento para la configuración - * - * @return XmlFileStorageInterface - */ - final public static function getConfigStorage() - { - if (!self::$ConfigFactory instanceof XmlFileStorageInterface) { - self::$ConfigFactory = new XmlHandler(CONFIG_FILE); - } - - return self::$ConfigFactory; - } - - /** - * Devuelve el manejador para la BD - * - * @return DBStorageInterface - */ - final public static function getDBStorage() - { - if (!self::$DBFactory instanceof DBStorageInterface) { - self::$DBFactory = new MySQLHandler(); - } - - return self::$DBFactory; - } - - /** - * Devuelve la instancia de la clase del elemento solicitado - * - * @param string $caller La clase del objeto - * @param mixed $itemData Los datos del elemento - * @return ItemBaseInterface - */ - final public static function getItem($caller, $itemData = null) - { -// error_log(count(self::$ItemFactory) . '-' . (memory_get_usage() / 1000)); - - try { - if (!isset(self::$ItemFactory[$caller])) { - self::$ItemFactory[$caller] = new $caller($itemData); - - return self::$ItemFactory[$caller]; - } - - return (null !== $itemData) ? self::$ItemFactory[$caller]->setItemData($itemData) : self::$ItemFactory[$caller]; - } catch (InvalidClassException $e) { - debugLog('Invalid class for item data: ' . $e->getMessage(), true); - } - - return self::$ItemFactory[$caller]; - } - - /** - * Devuelve el manejador de eventos - * - * @return EventDispatcherInterface - */ - final public static function getEventDispatcher() - { - if (!self::$EventDispatcher instanceof EventDispatcher) { - self::$EventDispatcher = new EventDispatcher(); - } - - return self::$EventDispatcher; - } -} \ No newline at end of file diff --git a/lib/SP/Core/Events/EventMessage.php b/lib/SP/Core/Events/EventMessage.php index 31ee95a9..814a9604 100644 --- a/lib/SP/Core/Events/EventMessage.php +++ b/lib/SP/Core/Events/EventMessage.php @@ -24,6 +24,7 @@ namespace SP\Core\Events; +use SP\Core\Messages\MessageInterface; use SP\Html\Html; /** @@ -31,7 +32,7 @@ use SP\Html\Html; * * @package SP\Core\Events */ -class EventMessage +class EventMessage implements MessageInterface { /** * @var array Detalles de la acción en formato "detalle : descripción" @@ -49,6 +50,10 @@ class EventMessage * @var array */ protected $description = []; + /** + * @var array + */ + protected $data = []; /** * @return static @@ -255,4 +260,28 @@ class EventMessage { return $this->detailsCounter; } + + /** + * @return array + */ + public function getData() + { + return $this->data; + } + + /** + * @param string $type + * @param mixed $data + * @return EventMessage + */ + public function addData($type, $data) + { + if (isset($this->data[$type]) && in_array($data, $this->data[$type])) { + return $this; + } + + $this->data[$type][] = $data; + + return $this; + } } \ No newline at end of file diff --git a/lib/SP/Core/Init.php b/lib/SP/Core/Init.php deleted file mode 100644 index 70eb0c40..00000000 --- a/lib/SP/Core/Init.php +++ /dev/null @@ -1,758 +0,0 @@ -. - */ - -namespace SP\Core; - -use Defuse\Crypto\Exception\CryptoException; -use SP\Account\AccountAcl; -use SP\Config\Config; -use SP\Core\Crypt\CryptSessionHandler; -use SP\Core\Crypt\SecureKeyCookie; -use SP\Core\Crypt\Session as CryptSession; -use SP\Core\Exceptions\SPException; -use SP\Core\Upgrade\Upgrade; -use SP\Http\JsonResponse; -use SP\Http\Request; -use SP\Log\Email; -use SP\Log\Log; -use SP\Mgmt\Profiles\Profile; -use SP\Modules\Web\Controllers\MainController; -use SP\Providers\Auth\Browser\Browser; -use SP\Storage\DBUtil; -use SP\Util\Checks; -use SP\Util\HttpUtil; -use SP\Util\Json; -use SP\Util\Util; - -defined('APP_ROOT') || die(); - -/** - * Clase Init para la inicialización del entorno de sysPass - * - * @package SP - */ -class Init -{ - /** - * @var string The installation path on the server (e.g. /srv/www/syspass) - */ - public static $SERVERROOT = ''; - - /** - * @var string The current request path relative to the sysPass root (e.g. files/index.php) - */ - public static $WEBROOT = ''; - - /** - * @var string The full URL to reach sysPass (e.g. https://sub.example.com/syspass/) - */ - public static $WEBURI = ''; - - /** - * @var bool True if sysPass has been updated. Only for notices. - */ - public static $UPDATED = false; - /** - * @var int - */ - public static $LOCK = 0; - /** - * @var string - */ - private static $SUBURI = ''; - /** - * @var bool Indica si la versión de PHP es correcta - */ - private static $checkPhpVersion; - /** - * @var bool Indica si el script requiere inicialización - */ - private static $checkInitSourceInclude; - /** - * @var string - */ - private static $sourceScript; - - /** - * Inicializar la aplicación. - * Esta función inicializa las variables de la aplicación y muestra la página - * según el estado en el que se encuentre. - * - * @throws \SP\Core\Exceptions\SPException - * @throws \phpmailer\phpmailerException - * @throws \Defuse\Crypto\Exception\BadFormatException - * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException - */ - public static function start() - { - self::$checkPhpVersion = Checks::checkPhpVersion(); - self::$checkInitSourceInclude = self::checkInitSourceInclude(); - - if (date_default_timezone_get() === 'UTC') { - date_default_timezone_set('UTC'); - } - - // Variables de autentificación - self::setAuth(); - - // Establecer el nivel de logging - self::setLogging(); - - // Cargar las extensiones -// self::loadExtensions(); - - // Establecer el lenguaje por defecto - Language::setLocales('en_US'); - - // Establecer las rutas de la aplicación - self::setPaths(); - - if (!self::$checkPhpVersion && !self::$checkInitSourceInclude) { - self::initError( - __('Versión de PHP requerida >= ') . ' 5.6.0 <= 7.0', - __('Actualice la versión de PHP para que la aplicación funcione correctamente')); - } - - // Comprobar la configuración - self::checkConfig(); - - // Iniciar la sesión de PHP - self::startSession(Config::getConfig()->isEncryptSession()); - - // Volver a cargar la configuración si se recarga la página - if (!Request::checkReload()) { - // Cargar la configuración - Config::loadConfig(); - - // Cargar el lenguaje - Language::setLanguage(); - - // Establecer el tema de sysPass - DiFactory::getTheme(); - } else { - // Cargar la configuración - Config::loadConfig(true); - - // Restablecer el idioma y el tema visual - Language::setLanguage(true); - DiFactory::getTheme()->initTheme(true); - - if (CryptSession::isLoggedIn() === true) { - // Recargar los permisos del perfil de usuario - SessionFactory::setUserProfile(Profile::getItem()->getById(SessionFactory::getUserData()->getUserProfileId())); - // Reset de los datos de ACL de cuentas - AccountAcl::resetData(); - } - } - - // Comprobar si es necesario cambiar a HTTPS - HttpUtil::checkHttps(); - - // Comprobar si es necesario inicialización - if (self::$checkInitSourceInclude || - ((defined('IS_INSTALLER') || defined('IS_UPGRADE')) && Checks::isAjax()) - ) { - return; - } - - // Comprobar si está instalado - self::checkInstalled(); - - // Comprobar si el modo mantenimiento está activado - self::checkMaintenanceMode(); - - // Comprobar si la Base de datos existe - if (!DBUtil::checkDatabaseExist()) { - self::initError(__('Error en la verificación de la base de datos')); - } - - // Comprobar si es cierre de sesión - self::checkLogout(); - - // Comprobar si es necesario actualizar componentes - self::checkUpgrade(); - - // Inicializar la sesión - self::initSession(); - - // Cargar los plugins - CryptSession::loadPlugins(); - - // Comprobar acciones en URL - self::checkPreLoginActions(); - - // Si es una petición AJAX - if (Checks::isAjax()) { - return; - } - - if (CryptSession::isLoggedIn() === true && SessionFactory::getAuthCompleted() === true) { - $AuthBrowser = new Browser(); - - // Comprobar si se ha identificado mediante el servidor web y el usuario coincide - if ($AuthBrowser->checkServerAuthUser(SessionFactory::getUserData()->getLogin()) === false - && $AuthBrowser->checkServerAuthUser(SessionFactory::getUserData()->getSsoLogin()) === false - ) { - self::goLogout(); - } - - return; - } - - // El usuario no está logado y no es una petición, redirigir al login - self::goLogin(); - } - - /** - * Comprobar el archivo que realiza el include necesita inicialización. - * - * @returns bool - */ - private static function checkInitSourceInclude() - { - self::$sourceScript = pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_BASENAME); - $skipInit = ['js.php', 'css.php', 'api.php', 'ajax_getEnvironment.php', 'ajax_task.php']; - - return in_array(self::$sourceScript, $skipInit, true); - } - - /** - * Establecer variables de autentificación - */ - private static function setAuth() - { - // Copiar la cabecera http de autentificación para apache+php-fcgid - if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) { - $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION']; - } - - // Establecer las cabeceras de autentificación para apache+php-cgi - if (isset($_SERVER['HTTP_AUTHORIZATION']) - && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches) - ) { - list($name, $password) = explode(':', base64_decode($matches[1]), 2); - $_SERVER['PHP_AUTH_USER'] = strip_tags($name); - $_SERVER['PHP_AUTH_PW'] = strip_tags($password); - } - - // Establecer las cabeceras de autentificación para que apache+php-cgi funcione si la variable es renombrada por apache - if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) - && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches) - ) { - list($name, $password) = explode(':', base64_decode($matches[1]), 2); - $_SERVER['PHP_AUTH_USER'] = strip_tags($name); - $_SERVER['PHP_AUTH_PW'] = strip_tags($password); - } - } - - /** - * Establecer el nivel de logging - */ - public static function setLogging() - { - // Establecer el modo debug si una sesión de xdebug está activa - if (isset($_COOKIE['XDEBUG_SESSION']) && !defined('DEBUG')) { - define('DEBUG', true); - } - - if (defined('DEBUG') && DEBUG) { - error_reporting(E_ALL); - ini_set('display_errors', 'On'); - } else { - error_reporting(E_ALL & ~(E_DEPRECATED | E_STRICT | E_NOTICE)); - ini_set('display_errors', 'Off'); - } - - if (!file_exists(LOG_FILE) && touch(LOG_FILE) && chmod(LOG_FILE, 0600)) { - debugLog('Setup log file: ' . LOG_FILE); - } - } - - /** - * Cargar las clases de las extensiones de sysPass - */ - private static function loadExtensions() - { - $CryptoLoader = new \SplClassLoader('Defuse\Crypto', EXTENSIONS_PATH); - $CryptoLoader->setPrepend(false); - $CryptoLoader->register(); - - $PhpSecLoader = new \SplClassLoader('phpseclib', EXTENSIONS_PATH); - $PhpSecLoader->setPrepend(false); - $PhpSecLoader->register(); - - $PhpMailerLoader = new \SplClassLoader('phpmailer', EXTENSIONS_PATH); - $PhpMailerLoader->setPrepend(false); - $PhpMailerLoader->register(); - - $ExtsLoader = new \SplClassLoader('Exts', BASE_PATH); - $ExtsLoader->setFileExtension('.class.php'); - $ExtsLoader->setPrepend(false); - $ExtsLoader->register(); - - $PluginsLoader = new \SplClassLoader('Plugins', BASE_PATH); - $PluginsLoader->setFileExtension('.class.php'); - $PluginsLoader->setPrepend(false); - $PluginsLoader->register(); - } - - /** - * Establecer las rutas de la aplicación. - * Esta función establece las rutas del sistema de archivos y web de la aplicación. - * La variables de clase definidas son $SERVERROOT, $WEBROOT y $SUBURI - */ - private static function setPaths() - { - // Calcular los directorios raíz -// $dir = substr(__DIR__, 0, strpos(__DIR__, str_replace('\\', '/', __NAMESPACE__)) - 1); -// self::$SERVERROOT = substr($dir, 0, strripos($dir, DIRECTORY_SEPARATOR)); - - self::$SERVERROOT = dirname(BASE_PATH); - - self::$SUBURI = str_replace("\\", '/', substr(realpath($_SERVER['SCRIPT_FILENAME']), strlen(self::$SERVERROOT))); - - $scriptName = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; - - if (substr($scriptName, -1) === '/') { - $scriptName .= 'index.php'; - // Asegurar que suburi sigue las mismas reglas que scriptName - if (substr(self::$SUBURI, -9) !== 'index.php') { - if (substr(self::$SUBURI, -1) !== '/') { - self::$SUBURI .= '/'; - } - self::$SUBURI .= 'index.php'; - } - } - - $pos = strpos($scriptName, self::$SUBURI); - - if ($pos === false) { - $pos = strpos($scriptName, '?'); - } - - self::$WEBROOT = substr($scriptName, 0, $pos); - - if (self::$WEBROOT !== '' && self::$WEBROOT[0] !== '/') { - self::$WEBROOT = '/' . self::$WEBROOT; - } - - self::$WEBURI = HttpUtil::getHttpHost() . self::$WEBROOT; - } - - - /** - * Devuelve un error utilizando la plantilla de error o en formato JSON - * - * @param string $message con la descripción del error - * @param string $hint opcional, con una ayuda sobre el error - * @param bool $headers - */ - public static function initError($message, $hint = '', $headers = false) - { - debugLog(__FUNCTION__); - debugLog(__($message)); - debugLog(__($hint)); - - if (Checks::isJson()) { - $JsonResponse = new JsonResponse(); - $JsonResponse->setDescription($message); - $JsonResponse->addMessage($hint); - Json::returnJson($JsonResponse); - } elseif ($headers === true) { - header('HTTP/1.1 503 Service Temporarily Unavailable'); - header('Status: 503 Service Temporarily Unavailable'); - header('Retry-After: 120'); - } - - SessionUtil::cleanSession(); - - $Tpl = new Template(); - $Tpl->append('errors', ['type' => SPException::CRITICAL, 'description' => __($message), 'hint' => __($hint)]); - - $Controller = new MainController($Tpl, 'error', !Checks::isAjax()); - $Controller->getError(); - } - - /** - * Cargar la configuración - * - * @throws \SP\Core\Exceptions\SPException - */ - private static function checkConfig() - { - // Comprobar si es una versión antigua - self::checkConfigVersion(); - - // Comprobar la configuración y cargar - self::checkConfigDir(); - } - - /** - * Comprobar la versión de configuración y actualizarla - */ - private static function checkConfigVersion() - { - $appVersion = Util::getVersionStringNormalized(); - - if (file_exists(OLD_CONFIG_FILE) && Upgrade::upgradeOldConfigFile($appVersion)) { - self::logConfigUpgrade($appVersion); - - self::$UPDATED = true; - - return; - } - - $configVersion = Upgrade::fixVersionNumber(Config::getConfig()->getConfigVersion()); - - if (Config::getConfig()->isInstalled() - && Util::checkVersion($configVersion, Util::getVersionArrayNormalized()) - && Upgrade::needConfigUpgrade($configVersion) - && Upgrade::upgradeConfig($configVersion) - ) { - self::logConfigUpgrade($appVersion); - - self::$UPDATED = true; - } - } - - /** - * Registrar la actualización de la configuración - * - * @param $version - */ - private static function logConfigUpgrade($version) - { - $Log = new Log(); - $LogMessage = $Log->getLogMessage(); - $LogMessage->setAction(__('Actualización', false)); - $LogMessage->addDescription(__('Actualización de versión realizada.', false)); - $LogMessage->addDetails(__('Versión', false), $version); - $LogMessage->addDetails(__('Tipo', false), 'config'); - $Log->writeLog(); - - Email::sendEmail($LogMessage); - } - - /** - * Comprobar el archivo de configuración. - * Esta función comprueba que el archivo de configuración exista y los permisos sean correctos. - * - * @throws \SP\Core\Exceptions\SPException - */ - private static function checkConfigDir() - { - if (self::$checkInitSourceInclude) { - return; - } - - if (!is_dir(self::$SERVERROOT . DIRECTORY_SEPARATOR . 'config')) { - clearstatcache(); - self::initError(__('El directorio "/config" no existe')); - } - - if (!is_writable(self::$SERVERROOT . DIRECTORY_SEPARATOR . 'config')) { - clearstatcache(); - self::initError(__('No es posible escribir en el directorio "config"')); - } - - $configPerms = decoct(fileperms(self::$SERVERROOT . DIRECTORY_SEPARATOR . 'config') & 0777); - - if ($configPerms !== '750' && !Checks::checkIsWindows()) { - clearstatcache(); - self::initError(__('Los permisos del directorio "/config" son incorrectos'), __('Actual:') . ' ' . $configPerms . ' - ' . __('Necesario: 750')); - } - } - - /** - * Iniciar la sesión PHP - * - * @param bool $encrypt Encriptar la sesión de PHP - */ - private static function startSession($encrypt = false) - { - // Evita que javascript acceda a las cookies de sesion de PHP - ini_set('session.cookie_httponly', '1'); - ini_set('session.save_handler', 'files'); - - if ($encrypt === true) { - $Key = SecureKeyCookie::getKey(); - - if ($Key !== false && self::$checkPhpVersion) { - session_set_save_handler(new CryptSessionHandler($Key), true); - } - } - - // Si la sesión no puede ser iniciada, devolver un error 500 - if (session_start() === false) { - Log::writeNewLog(__('Sesión', false), __('La sesión no puede ser inicializada', false)); - - header('HTTP/1.1 500 Internal Server Error'); - - self::initError(__('La sesión no puede ser inicializada'), __('Consulte con el administrador')); - } - } - - /** - * Comprueba que la aplicación esté instalada - * Esta función comprueba si la aplicación está instalada. Si no lo está, redirige al instalador. - * - * @throws \SP\Core\Exceptions\SPException - * @throws \Defuse\Crypto\Exception\BadFormatException - */ - private static function checkInstalled() - { - // Redirigir al instalador si no está instalada - if (!Config::getConfig()->isInstalled()) { - if (self::$SUBURI !== '/index.php') { - $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://'; - - $url = $protocol . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . self::$WEBROOT . '/index.php'; - header("Location: $url"); - exit(); - } - - if (SessionFactory::getAuthCompleted()) { - session_destroy(); - - self::start(); - return; - } - - // Comprobar si sysPass está instalada o en modo mantenimiento - $Controller = new MainController(); - $Controller->getInstaller(); - $Controller->view(); - exit(); - } - } - - /** - * Comprobar si el modo mantenimiento está activado - * Esta función comprueba si el modo mantenimiento está activado. - * Devuelve un error 503 y un reintento de 120s al cliente. - * - * @param bool $check sólo comprobar si está activado el modo - * @return bool - */ - public static function checkMaintenanceMode($check = false) - { - if (Config::getConfig()->isMaintenance()) { - self::$LOCK = Util::getAppLock(); - - if ($check === true - || Checks::isAjax() - || Request::analyze('nodbupgrade', 0) === 1 - || (Request::analyze('a') === 'upgrade' && Request::analyze('type') !== '') - || (self::$LOCK > 0 && Util::isLoggedIn() && self::$LOCK === SessionFactory::getUserData()->getId()) - ) { - return true; - } - - self::initError(__('Aplicación en mantenimiento'), __('En breve estará operativa')); - } - - return false; - } - - /** - * Comprobar si es necesario cerrar la sesión - */ - private static function checkLogout() - { - if (Request::analyze('logout', false, true)) { - self::goLogout(); - } - } - - /** - * Deslogar el usuario actual y eliminar la información de sesión. - */ - private static function goLogout() - { - self::wrLogoutInfo(); - - SessionUtil::cleanSession(); - - SessionFactory::setLoggedOut(true); - - $Controller = new MainController(); - $Controller->getLogout(); - } - - /** - * Escribir la información de logout en el registro de eventos. - */ - private static function wrLogoutInfo() - { - $inactiveTime = abs(round((time() - SessionFactory::getLastActivity()) / 60, 2)); - $totalTime = abs(round((time() - SessionFactory::getStartActivity()) / 60, 2)); - - $Log = new Log(); - $LogMessage = $Log->getLogMessage(); - $LogMessage->setAction(__('Finalizar sesión', false)); - $LogMessage->addDetails(__('Usuario', false), SessionFactory::getUserData()->getLogin()); - $LogMessage->addDetails(__('Tiempo inactivo', false), $inactiveTime . ' min.'); - $LogMessage->addDetails(__('Tiempo total', false), $totalTime . ' min.'); - $Log->writeLog(); - } - - /** - * Mostrar la página de login - */ - private static function goLogin() - { - SessionUtil::cleanSession(); - - $Controller = new MainController(); - $Controller->getLogin(); - } - - /** - * Comprobar si es necesario actualizar componentes - */ - private static function checkUpgrade() - { - return self::$SUBURI === '/index.php' && (Upgrade::checkDbVersion() || Upgrade::checkAppVersion()); - } - - /** - * Inicializar la sesión de usuario - * - */ - private static function initSession() - { - $lastActivity = SessionFactory::getLastActivity(); - $inMaintenance = Config::getConfig()->isMaintenance(); - - // Timeout de sesión - if ($lastActivity > 0 - && !$inMaintenance - && (time() - $lastActivity) > self::getSessionLifeTime() - ) { - if (isset($_COOKIE[session_name()])) { - setcookie(session_name(), '', time() - 42000, '/'); - } - - self::wrLogoutInfo(); - - SessionUtil::restart(); - return; - } - - $sidStartTime = SessionFactory::getSidStartTime(); - - // Regenerar el Id de sesión periódicamente para evitar fijación - if ($sidStartTime === 0) { - // Intentar establecer el tiempo de vida de la sesión en PHP - @ini_set('session.gc_maxlifetime', self::getSessionLifeTime()); - - SessionFactory::setSidStartTime(time()); - SessionFactory::setStartActivity(time()); - } else if (!$inMaintenance - && time() - $sidStartTime > 120 - && SessionFactory::getUserData()->getId() > 0 - ) { - try { - CryptSession::reKey(); - - // Recargar los permisos del perfil de usuario - SessionFactory::setUserProfile(Profile::getItem()->getById(SessionFactory::getUserData()->getUserProfileId())); - } catch (CryptoException $e) { - debugLog($e->getMessage()); - - SessionUtil::restart(); - return; - } - } - - SessionFactory::setLastActivity(time()); - } - - /** - * Obtener el timeout de sesión desde la configuración. - * - * @return int con el tiempo en segundos - */ - private static function getSessionLifeTime() - { - $timeout = SessionFactory::getSessionTimeout(); - - if (null === $timeout) { - $configTimeout = Config::getConfig()->getSessionTimeout(); - SessionFactory::setSessionTimeout($configTimeout); - - return $configTimeout; - } - - return $timeout; - } - - /** - * Comprobar si hay que ejecutar acciones de URL antes de presentar la pantalla de login. - * - * @return bool - * @throws phpmailerException - */ - public static function checkPreLoginActions() - { - $action = Request::analyze('a'); - - if ($action === '') { - return false; - } - - $Controller = new MainController(); - $Controller->doAction('prelogin.' . $action); - - return true; - } - - /** - * Establecer las rutas de sysPass en el PATH de PHP - */ - public static function setIncludes() - { - set_include_path(MODEL_PATH . PATH_SEPARATOR . CONTROLLER_PATH . PATH_SEPARATOR . EXTENSIONS_PATH . PATH_SEPARATOR . PLUGINS_PATH . PATH_SEPARATOR . get_include_path()); - } - - /** - * Comprobar si hay que ejecutar acciones de URL después de realizar login. - * - * @return bool - * @throws \phpmailer\phpmailerException - */ - public static function checkPostLoginActions() - { - $action = Request::analyze('a'); - - if ($action === '') { - return false; - } - - $Controller = new MainController(); - $Controller->doAction('postlogin.' . $action); - - return false; - } -} diff --git a/lib/SP/Core/Session/Session.php b/lib/SP/Core/Session/Session.php index 66da52a7..f7eee7d7 100644 --- a/lib/SP/Core/Session/Session.php +++ b/lib/SP/Core/Session/Session.php @@ -24,7 +24,6 @@ namespace SP\Core\Session; -use SP\Account\AccountAcl; use SP\Account\AccountSearchFilter; use SP\Config\ConfigData; use SP\DataModel\ProfileData; @@ -37,6 +36,11 @@ use SP\Services\User\UserLoginResponse; */ class Session { + const APP_STATUS_UPDATED = 'updated'; + const APP_STATUS_RELOADED = 'reloaded'; + const APP_STATUS_INSTALLED = 'installed'; + const APP_STATUS_LOGGEDOUT = 'loggedout'; + private static $isReset = false; private static $isLocked = false; @@ -202,32 +206,6 @@ class Session $this->setSessionKey('searchFilters', $searchFilters); } - /** - * Establecer la ACL de una cuenta - * - * @param AccountAcl $AccountAcl - */ - public function setAccountAcl(AccountAcl $AccountAcl) - { - $_SESSION['accountAcl'][$AccountAcl->getAccountId()] = $AccountAcl; - } - - /** - * Devolver la ACL de una cuenta - * - * @param $accountId - * - * @return null|AccountAcl - */ - public function getAccountAcl($accountId) - { - if (isset($_SESSION['accountAcl'][$accountId])) { - return $_SESSION['accountAcl'][$accountId]; - } - - return null; - } - public function resetAccountAcl() { $this->setSessionKey('accountAcl', null); @@ -477,22 +455,32 @@ class Session } /** - * Devuelve si se ha realizado un cierre de sesión + * Devuelve el estado de la aplicación * * @return bool */ - public function getLoggedOut() + public function getAppStatus() { - return $this->getSessionKey('loggedout', false); + return $this->getSessionKey('status'); } /** - * Establecer si se ha realizado un cierre de sesión + * Establecer el estado de la aplicación * - * @param bool $loggedout + * @param string $status */ - public function setLoggedOut($loggedout = false) + public function setAppStatus($status) { - $this->setSessionKey('loggedout', $loggedout); + $this->setSessionKey('status', $status); + } + + /** + * Reset del estado de la aplicación + * + * @return bool + */ + public function resetAppStatus() + { + return $this->setSessionKey('status', null); } } diff --git a/lib/SP/Core/UI/Theme.php b/lib/SP/Core/UI/Theme.php index 917d1818..a4b9248e 100644 --- a/lib/SP/Core/UI/Theme.php +++ b/lib/SP/Core/UI/Theme.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -24,12 +24,10 @@ namespace SP\Core\UI; -use Pimple\Container; +use SP\Bootstrap; use SP\Config\Config; use SP\Config\ConfigData; -use SP\Core\Init; use SP\Core\Session\Session; -use SP\Core\Traits\InjectableTrait; use Theme\Icons; defined('APP_ROOT') || die(); @@ -41,8 +39,6 @@ defined('APP_ROOT') || die(); */ class Theme implements ThemeInterface { - use InjectableTrait; - /** * @var string */ @@ -83,12 +79,14 @@ class Theme implements ThemeInterface /** * Theme constructor. * - * @param $module - * @throws \SP\Core\Dic\ContainerException + * @param $module + * @param Config $config + * @param Session $session */ - public function __construct($module) + public function __construct($module, Config $config, Session $session) { - $this->injectDependencies(); + $this->configData = $config->getConfigData(); + $this->session = $session; if (is_dir(VIEW_PATH)) { $this->initTheme(); @@ -111,7 +109,7 @@ class Theme implements ThemeInterface $this->session->setTheme($this->themeName); } - $this->themeUri = Init::$WEBURI . '/app/modules/' . $this->module . 'themes' . $this->themeName; + $this->themeUri = Bootstrap::$WEBURI . '/app/modules/' . $this->module . 'themes' . $this->themeName; $this->themePath = str_replace(APP_ROOT, '', VIEW_PATH) . DIRECTORY_SEPARATOR . $this->themeName; $this->themePathFull = VIEW_PATH . DIRECTORY_SEPARATOR . $this->themeName; $this->viewsPath = $this->themePathFull . DIRECTORY_SEPARATOR . 'views'; @@ -155,16 +153,6 @@ class Theme implements ThemeInterface return $this->icons; } - /** - * @param Config $config - * @param Session $session - */ - public function inject(Config $config, Session $session) - { - $this->configData = $config->getConfigData(); - $this->session = $session; - } - /** * Obtener los temas disponibles desde el directorio de temas * @@ -172,7 +160,7 @@ class Theme implements ThemeInterface */ public function getThemesAvailable() { - $themesAvailable = array(); + $themesAvailable = []; $themesDirs = dir(VIEW_PATH); diff --git a/lib/SP/DataModel/Dto/AccountAclDto.php b/lib/SP/DataModel/Dto/AccountAclDto.php index d3d2f51c..d877120c 100644 --- a/lib/SP/DataModel/Dto/AccountAclDto.php +++ b/lib/SP/DataModel/Dto/AccountAclDto.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -24,6 +24,8 @@ namespace SP\DataModel\Dto; +use SP\DataModel\ItemData; + /** * Class AccountAclDto * @@ -40,7 +42,7 @@ class AccountAclDto */ private $userId; /** - * @var int[] + * @var ItemData[] */ private $usersId; /** @@ -48,7 +50,7 @@ class AccountAclDto */ private $userGroupId; /** - * @var int[] + * @var ItemData[] */ private $userGroupsId; /** @@ -81,7 +83,7 @@ class AccountAclDto } /** - * @return int[] + * @return ItemData[] */ public function getUsersId() { @@ -89,7 +91,7 @@ class AccountAclDto } /** - * @param int[] $usersId + * @param ItemData[] $usersId */ public function setUsersId(array $usersId) { @@ -113,7 +115,7 @@ class AccountAclDto } /** - * @return int[] + * @return ItemData[] */ public function getUserGroupsId() { @@ -121,7 +123,7 @@ class AccountAclDto } /** - * @param int[] $userGroupsId + * @param ItemData[] $userGroupsId */ public function setUserGroupsId(array $userGroupsId) { @@ -141,7 +143,7 @@ class AccountAclDto */ public function setDateEdit($dateEdit) { - $this->dateEdit = (int)$dateEdit; + $this->dateEdit = $dateEdit; } /** diff --git a/lib/SP/DataModel/Dto/AccountCache.php b/lib/SP/DataModel/Dto/AccountCache.php index 5dcc0995..1b5299d4 100644 --- a/lib/SP/DataModel/Dto/AccountCache.php +++ b/lib/SP/DataModel/Dto/AccountCache.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -24,6 +24,8 @@ namespace SP\DataModel\Dto; +use SP\DataModel\ItemData; + /** * Class AccountCacheDto * @@ -40,20 +42,20 @@ class AccountCache */ private $accountId; /** - * @var array + * @var ItemData[] */ private $users; /** - * @var array + * @var ItemData[] */ private $userGroups; /** * AccountCacheDto constructor. * - * @param int $accountId - * @param array $users - * @param array $userGroups + * @param int $accountId + * @param ItemData[] $users + * @param ItemData[] $userGroups */ public function __construct($accountId, array $users, array $userGroups) { @@ -72,7 +74,7 @@ class AccountCache } /** - * @return array + * @return ItemData[] */ public function getUsers() { @@ -80,7 +82,7 @@ class AccountCache } /** - * @return array + * @return ItemData[] */ public function getUserGroups() { diff --git a/lib/SP/DataModel/Dto/AccountDetailsResponse.php b/lib/SP/DataModel/Dto/AccountDetailsResponse.php index 331f2b37..a3fc5a13 100644 --- a/lib/SP/DataModel/Dto/AccountDetailsResponse.php +++ b/lib/SP/DataModel/Dto/AccountDetailsResponse.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -25,6 +25,7 @@ namespace SP\DataModel\Dto; use SP\DataModel\AccountVData; +use SP\DataModel\ItemData; /** * Class AccountDto @@ -42,15 +43,15 @@ class AccountDetailsResponse */ private $accountVData; /** - * @var array Los Ids de los usuarios secundarios de la cuenta. + * @var ItemData[] Los usuarios secundarios de la cuenta. */ private $users = []; /** - * @var array Los Ids de los grupos secundarios de la cuenta. + * @var ItemData[] Los grupos secundarios de la cuenta. */ private $userGroups = []; /** - * @var array + * @var ItemData[] Las etiquetas de la cuenta. */ private $tags = []; @@ -67,7 +68,7 @@ class AccountDetailsResponse } /** - * @return array + * @return ItemData[] */ public function getUsers() { @@ -75,7 +76,7 @@ class AccountDetailsResponse } /** - * @param array $users + * @param ItemData[] $users */ public function setUsers(array $users) { @@ -83,7 +84,7 @@ class AccountDetailsResponse } /** - * @return array + * @return ItemData[] */ public function getUserGroups() { @@ -91,7 +92,7 @@ class AccountDetailsResponse } /** - * @param array $userGroups + * @param ItemData[] $userGroups */ public function setUserGroups(array $userGroups) { @@ -99,7 +100,7 @@ class AccountDetailsResponse } /** - * @return array + * @return ItemData[] */ public function getTags() { @@ -107,7 +108,7 @@ class AccountDetailsResponse } /** - * @param array $tags + * @param ItemData[] $tags */ public function setTags(array $tags) { diff --git a/lib/SP/Http/Request.php b/lib/SP/Http/Request.php index a710302a..83573851 100644 --- a/lib/SP/Http/Request.php +++ b/lib/SP/Http/Request.php @@ -24,6 +24,7 @@ namespace SP\Http; +use Klein\Klein; use SP\Core\CryptPKI; use SP\Core\Init; use SP\Html\Html; @@ -285,11 +286,12 @@ class Request /** * Comprobar si se realiza una recarga de la página * + * @param Klein $router * @return bool */ - public static function checkReload() + public static function checkReload(Klein $router) { - return (self::getRequestHeaders('Cache-Control') === 'max-age=0'); + return $router->request()->headers()->get('Cache-Control') === 'max-age=0'; } /** diff --git a/lib/SP/Mvc/View/Template.php b/lib/SP/Mvc/View/Template.php index a0774adc..e80210bd 100644 --- a/lib/SP/Mvc/View/Template.php +++ b/lib/SP/Mvc/View/Template.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -28,7 +28,6 @@ defined('APP_ROOT') || die(); use SP\Core\Exceptions\FileNotFoundException; use SP\Core\Exceptions\InvalidArgumentException; -use SP\Core\Traits\InjectableTrait; use SP\Core\UI\Theme; use SP\Core\UI\ThemeInterface; @@ -43,8 +42,6 @@ use SP\Core\UI\ThemeInterface; */ class Template { - use InjectableTrait; - const TEMPLATE_EXTENSION = '.inc'; const PARTIALS_DIR = '_partials'; const LAYOUTS_DIR = '_layouts'; @@ -56,7 +53,7 @@ class Template /** * @var array Variable con los archivos de plantilla a cargar */ - private $files = []; + private $templates = []; /** * @var array Variable con las variables a incluir en la plantilla */ @@ -69,23 +66,17 @@ class Template * @var array */ private $contentTemplates = []; + /** + * @var bool + */ + private $upgraded = false; /** - * @param null $file Archivo de plantilla a añadir - * @param array $vars Variables a inicializar - * @throws \SP\Core\Dic\ContainerException + * @param Theme $theme */ - public function __construct($file = null, array $vars = []) + public function __construct(Theme $theme) { - $this->injectDependencies(); - - if (null !== $file) { - $this->addTemplate($file); - } - - if (!empty($vars)) { - $this->setVars($vars); - } + $this->theme = $theme; } /** @@ -95,11 +86,11 @@ class Template * @param string $base Directorio base para la plantilla * @return bool */ - public function addTemplate($name, $base = null) + public function addContentTemplate($name, $base = null) { try { $template = $this->checkTemplate($name, $base); - $this->setTemplate($template, $name); + $this->setContentTemplate($template, $name); } catch (FileNotFoundException $e) { return ''; } @@ -134,48 +125,6 @@ class Template return $templateFile; } - /** - * Añadir un nuevo archivo de plantilla al array de plantillas - * - * @param string $file Con el nombre del archivo - * @param string $name Nombre de la plantilla - */ - private function setTemplate($file, $name) - { - $this->files[$name] = $file; - } - - /** - * Establecer los atributos de la clase a partir de un array. - * - * @param array $vars Con los atributos de la clase - */ - private function setVars(&$vars) - { - foreach ($vars as $name => $value) { - $this->{$name} = $value; - } - } - - /** - * Añadir una nueva plantilla al array de plantillas de la clase - * - * @param string $name Con el nombre del archivo de plantilla - * @param string $base Directorio base para la plantilla - * @return bool - */ - public function addContentTemplate($name, $base = null) - { - try { - $template = $this->checkTemplate($name, $base); - $this->setContentTemplate($template, $name); - } catch (FileNotFoundException $e) { - return ''; - } - - return $template; - } - /** * Añadir un nuevo archivo de plantilla al array de plantillas de contenido * @@ -195,7 +144,7 @@ class Template */ public function removeTemplate($name) { - unset($this->files[$name]); + unset($this->templates[$name]); return $this; } @@ -234,14 +183,6 @@ class Template return $this->contentTemplates[$dst]; } - /** - * @param Theme $theme - */ - public function inject(Theme $theme) - { - $this->theme = $theme; - } - /** * Add partial template * @@ -252,6 +193,36 @@ class Template $this->addTemplate($partial, self::PARTIALS_DIR); } + /** + * Añadir una nueva plantilla al array de plantillas de la clase + * + * @param string $name Con el nombre del archivo de plantilla + * @param string $base Directorio base para la plantilla + * @return bool + */ + public function addTemplate($name, $base = null) + { + try { + $template = $this->checkTemplate($name, $base); + $this->setTemplate($template, $name); + } catch (FileNotFoundException $e) { + return ''; + } + + return $template; + } + + /** + * Añadir un nuevo archivo de plantilla al array de plantillas + * + * @param string $file Con el nombre del archivo + * @param string $name Nombre de la plantilla + */ + private function setTemplate($file, $name) + { + $this->templates[$name] = $file; + } + /** * Añadir una nueva plantilla dentro de una plantilla * @@ -352,7 +323,7 @@ class Template */ public function render() { - if (count($this->files) === 0) { + if (count($this->templates) === 0) { throw new FileNotFoundException(__u('La plantilla no contiene archivos')); } @@ -361,29 +332,13 @@ class Template ob_start(); // Añadimos las plantillas - foreach ($this->files as $template) { + foreach ($this->templates as $template) { include_once $template; } return ob_get_clean(); } - /** - * Crear la variable y asignarle un valor en el array de variables - * - * @param $name string nombre de la variable - * @param $value mixed valor de la variable - * @param null $scope string ámbito de la variable - */ - public function assign($name, $value = '', $scope = null) - { - if (null !== $scope) { - $name = $scope . '_' . $name; - } - - $this->vars[$name] = $value; - } - /** * Anexar el valor de la variable al array de la misma en el array de variables * @@ -410,7 +365,7 @@ class Template */ public function resetTemplates() { - $this->files = []; + $this->templates = []; return $this; } @@ -480,4 +435,66 @@ class Template { return count($this->contentTemplates) > 0; } + + /** + * @return array + */ + public function getTemplates() + { + return $this->templates; + } + + /** + * Assigns the current templates to contentTemplates + * + * @return $this + */ + public function upgrade() + { + if (count($this->templates) > 0) { + $this->contentTemplates = $this->templates; + + $this->templates = []; + + $this->upgraded = true; + } + + return $this; + } + + /** + * Crear la variable y asignarle un valor en el array de variables + * + * @param $name string nombre de la variable + * @param $value mixed valor de la variable + * @param null $scope string ámbito de la variable + */ + public function assign($name, $value = '', $scope = null) + { + if (null !== $scope) { + $name = $scope . '_' . $name; + } + + $this->vars[$name] = $value; + } + + /** + * @return bool + */ + public function isUpgraded() + { + return $this->upgraded; + } + + /** + * Establecer los atributos de la clase a partir de un array. + * + * @param array $vars Con los atributos de la clase + */ + private function setVars(&$vars) + { + foreach ($vars as $name => $value) { + $this->{$name} = $value; + } + } } \ No newline at end of file diff --git a/lib/SP/Providers/Log/LogHandler.php b/lib/SP/Providers/Log/LogHandler.php index 25f158ac..cc9e0004 100644 --- a/lib/SP/Providers/Log/LogHandler.php +++ b/lib/SP/Providers/Log/LogHandler.php @@ -49,7 +49,8 @@ class LogHandler extends Provider implements EventReceiver 'clear.eventlog', 'login.', 'logout', - 'track.' + 'track.', + 'acl.deny' ]; /** diff --git a/lib/SP/Providers/Mail/Mailer.php b/lib/SP/Providers/Mail/MailHandler.php similarity index 92% rename from lib/SP/Providers/Mail/Mailer.php rename to lib/SP/Providers/Mail/MailHandler.php index 4f18456e..b2245f33 100644 --- a/lib/SP/Providers/Mail/Mailer.php +++ b/lib/SP/Providers/Mail/MailHandler.php @@ -41,7 +41,7 @@ use SP\Util\Util; * * @package SP\Providers\Mail */ -class Mailer extends Provider +class MailHandler extends Provider { /** * @var PHPMailer @@ -56,7 +56,7 @@ class Mailer extends Provider * @param string $subject * @param string $to * @param MailMessage $mailMessage - * @throws MailerException + * @throws MailHandlerException */ public function send($subject, $to, MailMessage $mailMessage) { @@ -84,7 +84,7 @@ class Mailer extends Provider } /** - * @throws MailerException + * @throws MailHandlerException */ private function sendMail() { @@ -101,14 +101,14 @@ class Mailer extends Provider $this->eventDispatcher->notifyEvent('exception', new Event($e)); - throw new MailerException(__u('Error al enviar correo')); + throw new MailHandlerException(__u('Error al enviar correo')); } } /** * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface - * @throws MailerException + * @throws MailHandlerException */ protected function initialize() { @@ -122,7 +122,7 @@ class Mailer extends Provider * @return PHPMailer * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface - * @throws MailerException + * @throws MailHandlerException */ private function getMailer() { @@ -154,9 +154,9 @@ class Mailer extends Provider } catch (\Exception $e) { processException($e); - throw new MailerException( + throw new MailHandlerException( __u('No es posible inicializar'), - MailerException::ERROR, + MailHandlerException::ERROR, $e->getMessage(), $e->getCode(), $e diff --git a/lib/SP/Providers/Mail/MailerException.php b/lib/SP/Providers/Mail/MailHandlerException.php similarity index 95% rename from lib/SP/Providers/Mail/MailerException.php rename to lib/SP/Providers/Mail/MailHandlerException.php index 508f66ab..0733359b 100644 --- a/lib/SP/Providers/Mail/MailerException.php +++ b/lib/SP/Providers/Mail/MailHandlerException.php @@ -31,7 +31,7 @@ use SP\Core\Exceptions\SPException; * * @package SP\Providers\Mail */ -class MailerException extends SPException +class MailHandlerException extends SPException { } \ No newline at end of file diff --git a/lib/SP/Providers/Notification/NotificationHandler.php b/lib/SP/Providers/Notification/NotificationHandler.php new file mode 100644 index 00000000..1d9c665f --- /dev/null +++ b/lib/SP/Providers/Notification/NotificationHandler.php @@ -0,0 +1,128 @@ +. + */ + +namespace SP\Providers\Notification; + + +use SP\Core\Events\Event; +use SP\Core\Events\EventReceiver; +use SP\DataModel\NotificationData; +use SP\Providers\Provider; +use SP\Services\Notification\NotificationService; +use SplSubject; + +/** + * Class NotificationHandler + * + * @package SP\Providers\Notification + */ +class NotificationHandler extends Provider implements EventReceiver +{ + const EVENTS = ['request.account']; + + /** + * @var NotificationService + */ + protected $notificationService; + /** + * @var string + */ + protected $events; + + /** + * Inicialización del observador + */ + public function init() + { + // TODO: Implement init() method. + } + + /** + * Evento de actualización + * + * @param string $eventType Nombre del evento + * @param Event $event Objeto del evento + */ + public function updateEvent($eventType, Event $event) + { + $eventMessage = $event->getEventMessage(); + $data = $eventMessage->getData(); + + foreach ($data['userId'] as $userId) { + $notificationData = new NotificationData(); + $notificationData->setType(__('Solicitud')); + $notificationData->setComponent(__('Cuentas')); + $notificationData->setUserId($userId); + $notificationData->setDescription($eventMessage); + + try { + $this->notificationService->create($notificationData); + } catch (\Exception $e) { + processException($e); + } + } + } + + /** + * Devuelve los eventos que implementa el observador + * + * @return array + */ + public function getEvents() + { + return self::EVENTS; + } + + /** + * Devuelve los eventos que implementa el observador en formato cadena + * + * @return string + */ + public function getEventsString() + { + return $this->events; + } + + /** + * Receive update from subject + * + * @link http://php.net/manual/en/splobserver.update.php + * @param SplSubject $subject

+ * The SplSubject notifying the observer of an update. + *

+ * @return void + * @since 5.1.0 + */ + public function update(SplSubject $subject) + { + // TODO: Implement update() method. + } + + protected function initialize() + { + $this->notificationService = $this->dic->get(NotificationService::class); + + $this->events = str_replace('.', '\\.', implode('|', self::EVENTS)); + } +} \ No newline at end of file diff --git a/lib/SP/Repositories/Account/AccountToTagRepository.php b/lib/SP/Repositories/Account/AccountToTagRepository.php index d42d067c..74f9aa38 100644 --- a/lib/SP/Repositories/Account/AccountToTagRepository.php +++ b/lib/SP/Repositories/Account/AccountToTagRepository.php @@ -25,6 +25,7 @@ namespace SP\Repositories\Account; use SP\Account\AccountRequest; +use SP\DataModel\ItemData; use SP\Repositories\Repository; use SP\Repositories\RepositoryItemTrait; use SP\Storage\DbWrapper; @@ -43,7 +44,7 @@ class AccountToTagRepository extends Repository * Devolver las etiquetas de una cuenta * * @param int $id - * @return array + * @return ItemData[] */ public function getTagsByAccountId($id) { @@ -57,6 +58,7 @@ class AccountToTagRepository extends Repository $queryData = new QueryData(); $queryData->setQuery($query); $queryData->addParam($id); + $queryData->setMapClassName(ItemData::class); return DbWrapper::getResultsArray($queryData, $this->db); } diff --git a/lib/SP/Repositories/Account/AccountToUserGroupRepository.php b/lib/SP/Repositories/Account/AccountToUserGroupRepository.php index a1db64cf..f71ca34a 100644 --- a/lib/SP/Repositories/Account/AccountToUserGroupRepository.php +++ b/lib/SP/Repositories/Account/AccountToUserGroupRepository.php @@ -25,7 +25,7 @@ namespace SP\Repositories\Account; use SP\Account\AccountRequest; -use SP\DataModel\UserGroupData; +use SP\DataModel\ItemData; use SP\Repositories\Repository; use SP\Repositories\RepositoryItemTrait; use SP\Storage\DbWrapper; @@ -44,7 +44,7 @@ class AccountToUserGroupRepository extends Repository * Obtiene el listado con el nombre de los grupos de una cuenta. * * @param int $id con el Id de la cuenta - * @return array + * @return ItemData[] */ public function getUserGroupsByAccountId($id) { @@ -58,6 +58,7 @@ class AccountToUserGroupRepository extends Repository $queryData = new QueryData(); $queryData->setQuery($query); $queryData->addParam($id); + $queryData->setMapClassName(ItemData::class); return DbWrapper::getResultsArray($queryData, $this->db); } @@ -66,7 +67,7 @@ class AccountToUserGroupRepository extends Repository * Obtiene el listado con el nombre de los grupos de una cuenta. * * @param $id - * @return UserGroupData[] + * @return ItemData[] */ public function getUserGroupsByUserGroupId($id) { @@ -80,6 +81,7 @@ class AccountToUserGroupRepository extends Repository $queryData = new QueryData(); $queryData->setQuery($query); $queryData->addParam($id); + $queryData->setMapClassName(ItemData::class); return DbWrapper::getResultsArray($queryData, $this->db); } diff --git a/lib/SP/Repositories/Account/AccountToUserRepository.php b/lib/SP/Repositories/Account/AccountToUserRepository.php index a117c75a..56ff02f3 100644 --- a/lib/SP/Repositories/Account/AccountToUserRepository.php +++ b/lib/SP/Repositories/Account/AccountToUserRepository.php @@ -25,6 +25,7 @@ namespace SP\Repositories\Account; use SP\Account\AccountRequest; +use SP\DataModel\ItemData; use SP\Repositories\Repository; use SP\Repositories\RepositoryItemTrait; use SP\Storage\DbWrapper; @@ -104,7 +105,7 @@ class AccountToUserRepository extends Repository * Obtiene el listado de usuarios de una cuenta. * * @param int $id con el id de la cuenta - * @return array con los id de usuarios de la cuenta + * @return ItemData[] con los id de usuarios de la cuenta */ public function getUsersByAccountId($id) { @@ -118,6 +119,7 @@ class AccountToUserRepository extends Repository $queryData = new QueryData(); $queryData->setQuery($query); $queryData->addParam($id); + $queryData->setMapClassName(ItemData::class); return DbWrapper::getResultsArray($queryData, $this->db); } diff --git a/lib/SP/Repositories/EventLog/EventlogRepository.php b/lib/SP/Repositories/EventLog/EventlogRepository.php index 8679968e..f7e0e125 100644 --- a/lib/SP/Repositories/EventLog/EventlogRepository.php +++ b/lib/SP/Repositories/EventLog/EventlogRepository.php @@ -68,12 +68,10 @@ class EventlogRepository extends Repository $queryData->setOrder('id DESC'); if ($itemSearchData->getSeachString() !== '') { - $queryData->setWhere('action LIKE ? OR ipAddress LIKE ? OR description LIKE ?'); + $queryData->setWhere('action LIKE ? OR login LIKE ? OR ipAddress LIKE ? OR description LIKE ?'); $search = '%' . $itemSearchData->getSeachString() . '%'; - $queryData->addParam($search); - $queryData->addParam($search); - $queryData->addParam($search); + $queryData->setParams(array_fill(0, 4, $search)); } $queryData->setLimit('?,?'); diff --git a/lib/SP/Repositories/PublicLink/PublicLinkRepository.php b/lib/SP/Repositories/PublicLink/PublicLinkRepository.php index 4317dd50..68c3b3be 100644 --- a/lib/SP/Repositories/PublicLink/PublicLinkRepository.php +++ b/lib/SP/Repositories/PublicLink/PublicLinkRepository.php @@ -472,14 +472,11 @@ class PublicLinkRepository extends Repository implements RepositoryItemInterface $queryData->setMapClassName(PublicLinkData::class); $queryData->setQuery($query); $queryData->addParam($hash); + $queryData->setOnErrorMessage(__u('Error al obtener enlace')); /** @var PublicLinkData $queryRes */ $queryRes = DbWrapper::getResults($queryData, $this->db); - if ($queryRes === false) { - throw new SPException(__u('Error al obtener enlace'), SPException::ERROR); - } - if ($queryData->getQueryNumRows() === 0) { throw new SPException(__u('El enlace no existe'), SPException::ERROR); } diff --git a/lib/SP/Repositories/UserGroup/UserToUserGroupRepository.php b/lib/SP/Repositories/UserGroup/UserToUserGroupRepository.php index 0aa2f0fe..e722ea8b 100644 --- a/lib/SP/Repositories/UserGroup/UserToUserGroupRepository.php +++ b/lib/SP/Repositories/UserGroup/UserToUserGroupRepository.php @@ -46,19 +46,16 @@ class UserToUserGroupRepository extends Repository * @param $groupId * @return bool */ - public static function checkUserInGroup($groupId, $userId) + public function checkUserInGroup($groupId, $userId) { - $query = /** @lang SQL */ - 'SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = ? AND userId = ?'; + $queryData = new QueryData(); + $queryData->setQuery('SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = ? AND userId = ?'); + $queryData->addParam($groupId); + $queryData->addParam($userId); - $Data = new QueryData(); - $Data->setQuery($query); - $Data->addParam($groupId); - $Data->addParam($userId); + DbWrapper::getResults($queryData, $this->db); - DbWrapper::getResults($Data); - - return ($Data->getQueryNumRows() === 1); + return ($queryData->getQueryNumRows() === 1); } /** @@ -67,16 +64,13 @@ class UserToUserGroupRepository extends Repository * @param $userId * @return array */ - public static function getGroupsForUser($userId) + public function getGroupsForUser($userId) { - $query = /** @lang SQL */ - 'SELECT userGroupId AS groupId FROM UserToUserGroup WHERE userId = ?'; + $queryData = new QueryData(); + $queryData->setQuery('SELECT userGroupId AS groupId FROM UserToUserGroup WHERE userId = ?'); + $queryData->addParam($userId); - $Data = new QueryData(); - $Data->setQuery($query); - $Data->addParam($userId); - - return DbWrapper::getResultsArray($Data); + return DbWrapper::getResultsArray($queryData, $this->db); } /** @@ -104,15 +98,12 @@ class UserToUserGroupRepository extends Repository */ public function delete($id) { - $query = /** @lang SQL */ - 'DELETE FROM UserToUserGroup WHERE userGroupId = ?'; + $queryData = new QueryData(); + $queryData->setQuery('DELETE FROM UserToUserGroup WHERE userGroupId = ?'); + $queryData->addParam($id); + $queryData->setOnErrorMessage(__u('Error al eliminar los usuarios del grupo')); - $Data = new QueryData(); - $Data->setQuery($query); - $Data->addParam($id); - $Data->setOnErrorMessage(__u('Error al eliminar los usuarios del grupo')); - - DbWrapper::getQuery($Data, $this->db); + DbWrapper::getQuery($queryData, $this->db); return $this; } @@ -131,17 +122,17 @@ class UserToUserGroupRepository extends Repository $query = /** @lang SQL */ 'INSERT INTO UserToUserGroup (userId, userGroupId) VALUES ' . $this->getParamsFromArray($users, '(?,?)'); - $Data = new QueryData(); - $Data->setQuery($query); + $queryData = new QueryData(); + $queryData->setQuery($query); foreach ($users as $user) { - $Data->addParam($user); - $Data->addParam($groupId); + $queryData->addParam($user); + $queryData->addParam($groupId); } - $Data->setOnErrorMessage(__u('Error al asignar los usuarios al grupo')); + $queryData->setOnErrorMessage(__u('Error al asignar los usuarios al grupo')); - DbWrapper::getQuery($Data, $this->db); + DbWrapper::getQuery($queryData, $this->db); return $this; } @@ -154,14 +145,11 @@ class UserToUserGroupRepository extends Repository */ public function getById($id) { - $query = /** @lang SQL */ - 'SELECT userGroupId, userId FROM UserToUserGroup WHERE userGroupId = ?'; + $queryData = new QueryData(); + $queryData->setQuery('SELECT userGroupId, userId FROM UserToUserGroup WHERE userGroupId = ?'); + $queryData->addParam($id); + $queryData->setMapClassName(UserToUserGroupData::class); - $Data = new QueryData(); - $Data->setMapClassName(UserToUserGroupData::class); - $Data->setQuery($query); - $Data->addParam($id); - - return DbWrapper::getResultsArray($Data, $this->db); + return DbWrapper::getResultsArray($queryData, $this->db); } } \ No newline at end of file diff --git a/lib/SP/Services/Account/AccountAclService.php b/lib/SP/Services/Account/AccountAclService.php new file mode 100644 index 00000000..7ac1f780 --- /dev/null +++ b/lib/SP/Services/Account/AccountAclService.php @@ -0,0 +1,324 @@ +. + */ + +namespace SP\Services\Account; + +use SP\Account\AccountAcl; +use SP\Core\Acl\Acl; +use SP\DataModel\Dto\AccountAclDto; +use SP\DataModel\ProfileData; +use SP\Services\Service; +use SP\Services\User\UserLoginResponse; +use SP\Services\UserGroup\UserToUserGroupService; +use SP\Storage\FileCache; +use SP\Util\ArrayUtil; +use SP\Util\FileUtil; + +/** + * Class AccountAclService + * + * @package SP\Services\Account + */ +class AccountAclService extends Service +{ + /** + * ACL's file base path + */ + const ACL_PATH = CACHE_PATH . DIRECTORY_SEPARATOR . 'accountAcl' . DIRECTORY_SEPARATOR; + /** + * @var AccountAclDto + */ + protected $accountAclDto; + /** + * @var AccountAcl + */ + protected $accountAcl; + /** + * @var Acl + */ + protected $acl; + /** + * @var FileCache + */ + protected $fileCache; + + /** + * @param $userId + */ + public static function clearAcl($userId) + { + if (FileUtil::rmdir_recursive(self::ACL_PATH . $userId) === false) { + debugLog(sprintf('Unable to delete %s directory', self::ACL_PATH . $userId)); + } + + debugLog(__FUNCTION__); + } + + /** + * Obtener la ACL de una cuenta + * + * @param int $actionId + * @param AccountAclDto $accountAclDto + * @param bool $isHistory + * @return AccountAcl + */ + public function getAcl($actionId, AccountAclDto $accountAclDto = null, $isHistory = false) + { + $this->accountAcl = new AccountAcl($actionId, $isHistory); + + $this->accountAcl->showPermission = self::getShowPermission($this->session->getUserData(), $this->session->getUserProfile()); + + if ($accountAclDto !== null) { + $this->accountAclDto = $accountAclDto; + $accountAcl = $this->getAclFromCache($accountAclDto->getAccountId(), $actionId); + + if (null !== $accountAcl + && !($this->accountAcl->modified = (int)strtotime($accountAclDto->getDateEdit()) > $accountAcl->getTime()) + ) { + debugLog('Account ACL HIT'); + + return $accountAcl; + } + + debugLog('Account ACL MISS'); + + $this->accountAcl->setAccountId($accountAclDto->getAccountId()); + + return $this->updateAcl(); + } + + return $this->accountAcl; + } + + /** + * Sets grants which don't need the account's data + * + * @param UserLoginResponse $userData + * @param ProfileData $profileData + * @return bool + */ + public static function getShowPermission(UserLoginResponse $userData, ProfileData $profileData) + { + return $userData->getIsAdminApp() + || $userData->getIsAdminAcc() + || $profileData->isAccPermission(); + } + + /** + * Resturns an stored ACL + * + * @param int $accountId + * @param int $actionId + * @return AccountAcl + */ + public function getAclFromCache($accountId, $actionId) + { + try { + return $this->fileCache->load($this->getCacheFileForAcl($accountId, $actionId)); + } catch (\RuntimeException $e) { + return null; + } + } + + /** + * @param int $accountId + * @param int $actionId + * @return string + */ + public function getCacheFileForAcl($accountId, $actionId) + { + $userId = $this->session->getUserData()->getId(); + return self::ACL_PATH . $userId . DIRECTORY_SEPARATOR . $accountId . DIRECTORY_SEPARATOR . md5($userId . $accountId . $actionId) . '.cache'; + } + + /** + * Actualizar la ACL + * + * @return AccountAcl + */ + public function updateAcl() + { + if ($this->checkComponents()) { + $this->makeAcl(); + } + + $this->saveAclInCache($this->accountAcl); + + return $this->accountAcl; + } + + /** + * @return bool + */ + protected function checkComponents() + { + return null !== $this->accountAclDto; + } + + /** + * Crear la ACL de una cuenta + */ + protected function makeAcl() + { + $this->compileAccountAccess(); + $this->accountAcl->setCompiledAccountAccess(true); + + $this->compileShowAccess(); + $this->accountAcl->setCompiledShowAccess(true); + + $this->accountAcl->setTime(time()); + } + + /** + * compileAccountAccess + */ + protected function compileAccountAccess() + { + $userData = $this->session->getUserData(); + + if ($userData->getIsAdminApp() + || $userData->getIsAdminAcc() + ) { + $this->accountAcl->resultView = true; + $this->accountAcl->resultEdit = true; + + return; + } + + $this->accountAcl->userInGroups = $this->getIsUserInGroups(); + $this->accountAcl->userInUsers = ArrayUtil::checkInObjectArray($this->accountAclDto->getUsersId(), 'id', $userData->getId()); + + $this->accountAcl->resultView = ($userData->getId() === $this->accountAclDto->getUserId() + || $userData->getUserGroupId() === $this->accountAclDto->getUserGroupId() + || $this->accountAcl->userInUsers + || $this->accountAcl->userInGroups); + + $this->accountAcl->resultEdit = ($userData->getId() === $this->accountAclDto->getUserId() + || $userData->getUserGroupId() === $this->accountAclDto->getUserGroupId() + || ($this->accountAcl->userInUsers && $this->accountAclDto->getOtherUserEdit() === 1) + || ($this->accountAcl->userInGroups && $this->accountAclDto->getOtherUserGroupEdit() === 1)); + } + + /** + * Comprobar si el usuario o el grupo del usuario se encuentran los grupos asociados a la + * cuenta. + * + * @return bool + */ + protected function getIsUserInGroups() + { + $userData = $this->session->getUserData(); + $userToUserGroupService = $this->dic->get(UserToUserGroupService::class); + + // Comprobar si el usuario está vinculado desde el grupo principal de la cuenta + if ($userToUserGroupService->checkUserInGroup($this->accountAclDto->getUserGroupId(), $userData->getId())) { + return true; + } + + // Grupos en los que se encuentra el usuario + $userGroupIds = $userToUserGroupService->getGroupsForUser($userData->getId()); + $isAccountFullGroupAccess = $this->config->getConfigData()->isAccountFullGroupAccess(); + + // Comprobar si el grupo del usuario está vinculado desde los grupos secundarios de la cuenta + foreach ($this->accountAclDto->getUserGroupsId() as $userGroup) { + // Consultar el grupo principal del usuario + if ((int)$userGroup->id === $userData->getUserGroupId() + // o... permitir los grupos que no sean el principal del usuario? + || ($isAccountFullGroupAccess + // Comprobar si el usuario está vinculado desde los grupos secundarios de la cuenta + && ArrayUtil::checkInObjectArray($userGroupIds, 'userGroupId', $userGroup->id)) + ) { + return true; + } + } + + return false; + } + + /** + * compileShowAccess + */ + protected function compileShowAccess() + { + // Mostrar historial + $this->accountAcl->showHistory = $this->acl->checkUserAccess(Acl::ACCOUNT_VIEW_HISTORY); + + // Mostrar lista archivos + $this->accountAcl->showFiles = $this->acl->checkUserAccess(Acl::ACCOUNT_FILE); + + // Mostrar acción de ver clave + $this->accountAcl->showViewPass = $this->accountAcl->checkAccountAccess(Acl::ACCOUNT_VIEW_PASS) + && $this->acl->checkUserAccess(Acl::ACCOUNT_VIEW_PASS); + + // Mostrar acción de editar + $this->accountAcl->showEdit = $this->accountAcl->checkAccountAccess(Acl::ACCOUNT_EDIT) + && $this->acl->checkUserAccess(Acl::ACCOUNT_EDIT) + && !$this->accountAcl->isHistory(); + + // Mostrar acción de editar clave + $this->accountAcl->showEditPass = $this->accountAcl->checkAccountAccess(Acl::ACCOUNT_EDIT_PASS) + && $this->acl->checkUserAccess(Acl::ACCOUNT_EDIT_PASS) + && !$this->accountAcl->isHistory(); + + // Mostrar acción de eliminar + $this->accountAcl->showDelete = $this->accountAcl->checkAccountAccess(Acl::ACCOUNT_DELETE) + && $this->acl->checkUserAccess(Acl::ACCOUNT_DELETE); + + // Mostrar acción de restaurar + $this->accountAcl->showRestore = $this->accountAcl->checkAccountAccess(Acl::ACCOUNT_EDIT) + && $this->acl->checkUserAccess(Acl::ACCOUNT_EDIT); + + // Mostrar acción de enlace público + $this->accountAcl->showLink = $this->acl->checkUserAccess(Acl::PUBLICLINK_CREATE); + + // Mostrar acción de ver cuenta + $this->accountAcl->showView = $this->accountAcl->checkAccountAccess(Acl::ACCOUNT_VIEW) + && $this->acl->checkUserAccess(Acl::ACCOUNT_VIEW); + + // Mostrar acción de copiar cuenta + $this->accountAcl->showCopy = $this->accountAcl->checkAccountAccess(Acl::ACCOUNT_COPY) + && $this->acl->checkUserAccess(Acl::ACCOUNT_COPY); + } + + /** + * Saves the ACL + * + * @param AccountAcl $accountAcl + * @return null|\SP\Storage\FileStorageInterface + */ + public function saveAclInCache(AccountAcl $accountAcl) + { + try { + return $this->fileCache->save($this->getCacheFileForAcl($accountAcl->getAccountId(), $accountAcl->getActionId()), $accountAcl); + } catch (\RuntimeException $e) { + return null; + } + } + + public function initialize() + { + $this->acl = $this->dic->get(Acl::class); + $this->fileCache = $this->dic->get(FileCache::class); + } +} \ No newline at end of file diff --git a/lib/SP/Services/Account/AccountCryptService.php b/lib/SP/Services/Account/AccountCryptService.php index 327e8fd5..e0a2bc3b 100644 --- a/lib/SP/Services/Account/AccountCryptService.php +++ b/lib/SP/Services/Account/AccountCryptService.php @@ -62,7 +62,6 @@ class AccountCryptService extends Service * * @param UpdateMasterPassRequest $updateMasterPassRequest * @throws ServiceException - * @throws \SP\Core\Exceptions\InvalidArgumentException */ public function updateOldPass(UpdateMasterPassRequest $updateMasterPassRequest) { @@ -77,14 +76,14 @@ class AccountCryptService extends Service $this->eventDispatcher->notifyEvent('update.masterPassword.accounts.start', new Event($this, [__u('Actualizar Clave Maestra')])); if (!OldCrypt::checkCryptModule()) { - throw new ServiceException(__u('Error en el módulo de encriptación'), SPException::ERROR); + throw new ServiceException(__u('Error en el módulo de encriptación'), ServiceException::ERROR); } $accountsPass = $this->accountService->getAccountsPassData(); $numAccounts = count($accountsPass); if ($numAccounts === 0) { - throw new ServiceException(__u('Error al obtener las claves de las cuentas'), SPException::ERROR); + throw new ServiceException(__u('Error al obtener las claves de las cuentas'), ServiceException::ERROR); } $taskId = $this->request->getTask()->getTaskId(); @@ -171,7 +170,7 @@ class AccountCryptService extends Service $this->eventDispatcher->notifyEvent('update.masterPassword.accounts.end', new Event($this, $process)); } catch (\Exception $e) { - throw new ServiceException(__u('Errores al actualizar las claves de las cuentas'), SPException::ERROR, null, $e->getCode(), $e); + throw new ServiceException(__u('Errores al actualizar las claves de las cuentas'), ServiceException::ERROR, null, $e->getCode(), $e); } } @@ -193,7 +192,7 @@ class AccountCryptService extends Service $numAccounts = count($accounts); if ($numAccounts === 0) { - throw new ServiceException(__u('Error al obtener las claves de las cuentas'), SPException::ERROR); + throw new ServiceException(__u('Error al obtener las claves de las cuentas'), ServiceException::ERROR); } $configData = $this->config->getConfigData(); @@ -292,7 +291,7 @@ class AccountCryptService extends Service $this->eventDispatcher->notifyEvent('update.masterPassword.accountsHistory.end', new Event($this, $process)); } catch (\Exception $e) { - throw new ServiceException(__u('Errores al actualizar las claves de las cuentas del histórico'), SPException::ERROR, null, $e->getCode(), $e); + throw new ServiceException(__u('Errores al actualizar las claves de las cuentas del histórico'), ServiceException::ERROR, null, $e->getCode(), $e); } } diff --git a/lib/SP/Services/Account/AccountHistoryService.php b/lib/SP/Services/Account/AccountHistoryService.php index 5ee9f629..fa40431a 100644 --- a/lib/SP/Services/Account/AccountHistoryService.php +++ b/lib/SP/Services/Account/AccountHistoryService.php @@ -27,6 +27,7 @@ namespace SP\Services\Account; use SP\Core\Exceptions\QueryException; use SP\Core\Exceptions\SPException; use SP\DataModel\AccountHistoryData; +use SP\DataModel\ItemData; use SP\DataModel\ItemSearchData; use SP\Repositories\Account\AccountHistoryRepository; use SP\Repositories\Account\AccountToUserGroupRepository; @@ -90,7 +91,7 @@ class AccountHistoryService extends Service /** * @param $id - * @return array + * @return ItemData[] */ public function getUsersByAccountId($id) { @@ -99,7 +100,7 @@ class AccountHistoryService extends Service /** * @param $id - * @return array + * @return ItemData[] */ public function getUserGroupsByAccountId($id) { diff --git a/lib/SP/Services/Account/AccountSearchService.php b/lib/SP/Services/Account/AccountSearchService.php index 84dff3ec..9f24bfe6 100644 --- a/lib/SP/Services/Account/AccountSearchService.php +++ b/lib/SP/Services/Account/AccountSearchService.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -24,12 +24,10 @@ namespace SP\Services\Account; -use SP\Account\AccountAcl; use SP\Account\AccountSearchFilter; use SP\Account\AccountSearchItem; use SP\Config\ConfigData; use SP\Core\Acl\Acl; -use SP\Core\Session\Session; use SP\DataModel\AccountSearchVData; use SP\DataModel\Dto\AccountAclDto; use SP\DataModel\Dto\AccountCache; @@ -49,11 +47,14 @@ defined('APP_ROOT') || die(); class AccountSearchService extends Service { /** - * Colores para resaltar las cuentas - * - * @var array + * Regex filter for special searching */ - private static $colors = [ + const FILTERS_REGEX = '^(?:(?Puser|group|file|owner|maingroup|expired|private):(?:"(?P[\w\.]+)")?)$'; + + /** + * Colores para resaltar las cuentas + */ + const COLORS = [ '2196F3', '03A9F4', '00BCD4', @@ -72,10 +73,6 @@ class AccountSearchService extends Service '673AB7', '3F51B5', ]; - /** - * @var Session - */ - protected $session; /** * @var ConfigData */ @@ -97,19 +94,6 @@ class AccountSearchService extends Service */ private $accountRepository; - /** - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface - */ - protected function initialize() - { - $this->accountRepository = $this->dic->get(AccountRepository::class); - $this->accountToTagRepository = $this->dic->get(AccountToTagRepository::class); - $this->accountToUserRepository = $this->dic->get(AccountToUserRepository::class); - $this->accountToUserGroupRepository = $this->dic->get(AccountToUserGroupRepository::class); - $this->configData = $this->config->getConfigData(); - } - /** * Procesar los resultados de la búsqueda y crear la variable que contiene los datos de cada cuenta * a mostrar. @@ -118,7 +102,6 @@ class AccountSearchService extends Service * @return array * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface - * @throws \SP\Core\Dic\ContainerException * @throws \SP\Core\Exceptions\SPException */ public function processSearchResults(AccountSearchFilter $accountSearchFilter) @@ -133,25 +116,26 @@ class AccountSearchService extends Service $accountLinkEnabled = $this->session->getUserData()->getPreferences()->isAccountLink() || $this->configData->isAccountLink(); $favorites = $this->dic->get(AccountFavoriteService::class)->getForUserId($this->session->getUserData()->getId()); + $accountAclService = $this->dic->get(AccountAclService::class); + foreach ($accountSearchResponse->getData() as $accountSearchData) { $cache = $this->getCacheForAccount($accountSearchData); - $acccountAclDto = new AccountAclDto(); - $acccountAclDto->setAccountId($accountSearchData->getId()); - $acccountAclDto->setDateEdit($accountSearchData->getDateEdit()); - $acccountAclDto->setUserId($accountSearchData->getUserId()); - $acccountAclDto->setUserGroupId($accountSearchData->getUserGroupId()); - $acccountAclDto->setUsersId($cache->getUsers()); - $acccountAclDto->setUserGroupsId($cache->getUserGroups()); + $accountAclDto = new AccountAclDto(); + $accountAclDto->setAccountId($accountSearchData->getId()); + $accountAclDto->setDateEdit($accountSearchData->getDateEdit()); + $accountAclDto->setUserId($accountSearchData->getUserId()); + $accountAclDto->setUserGroupId($accountSearchData->getUserGroupId()); + $accountAclDto->setUsersId($cache->getUsers()); + $accountAclDto->setUserGroupsId($cache->getUserGroups()); + $accountAclDto->setOtherUserEdit($accountSearchData->getOtherUserEdit()); + $accountAclDto->setOtherUserGroupEdit($accountSearchData->getOtherUserGroupEdit()); // Obtener la ACL de la cuenta - $accountAcl = (new AccountAcl(Acl::ACCOUNT_SEARCH))->getAcl($acccountAclDto); - - // Guardar la ACL - $this->session->setAccountAcl($accountAcl); + $accountAcl = $accountAclService->getAcl(Acl::ACCOUNT_SEARCH, $accountAclDto); // Propiedades de búsqueda de cada cuenta - $accountsSearchItem = new AccountSearchItem($accountSearchData, $accountAcl); + $accountsSearchItem = new AccountSearchItem($accountSearchData, $accountAcl, $this->configData); if (!$accountSearchData->getIsPrivate()) { $accountsSearchItem->setUsers($cache->getUsers()); @@ -184,17 +168,16 @@ class AccountSearchService extends Service */ private function analyzeQueryString($txt) { - if (!preg_match('/^(?Puser|group|file|owner|maingroup):"(?P[\w\.]+)"$/i', $txt, $filters) - && !preg_match('/^(?Pexpired|private):$/i', $txt, $filters) - ) { + if (!preg_match('/' . self::FILTERS_REGEX . '/i', $txt, $filters)) { return []; } + $text = isset($filters['text']) && empty($filters['text']) === false ? $filters['text'] : false; + switch ($filters['filter']) { case 'user': - $userData = $this->dic->get(UserService::class)->getByLogin($filters['text']); - - if (!is_object($userData)) { + if ($text === false + || is_object(($userData = $this->dic->get(UserService::class)->getByLogin($text))) === false) { return []; } @@ -205,22 +188,19 @@ class AccountSearchService extends Service ]; break; case 'owner': - $userData = $this->dic->get(UserService::class)->getByLogin($filters['text']); - - if (!is_object($userData)) { + if ($text === false) { return []; } return [ 'type' => 'user', - 'query' => 'A.userId = ?', - 'values' => [$userData->getId()] + 'query' => 'A.userLogin LIKE ?', + 'values' => ['%' . $text . '%'] ]; break; case 'group': - $userGroupData = $this->dic->get(UserGroupService::class)->getByName($filters['text']); - - if (!is_object($userGroupData)) { + if ($text === false + || is_object(($userGroupData = $this->dic->get(UserGroupService::class)->getByName($text))) === false) { return []; } @@ -231,23 +211,21 @@ class AccountSearchService extends Service ]; break; case 'maingroup': - $userGroupData = $this->dic->get(UserGroupService::class)->getByName($filters['text']); - - if (!is_object($userGroupData)) { + if ($text === false) { return []; } return [ 'type' => 'group', - 'query' => 'A.userGroupId = ?', - 'values' => [$userGroupData->getId()] + 'query' => 'A.userGroupName = ?', + 'values' => ['%' . $text . '%'] ]; break; case 'file': return [ 'type' => 'file', 'query' => 'A.id IN (SELECT AF.accountId FROM AccountFile AF WHERE AF.name LIKE ?)', - 'values' => ['%' . $filters[2] . '%'] + 'values' => ['%' . $text . '%'] ]; break; case 'expired': @@ -308,12 +286,25 @@ class AccountSearchService extends Service || !isset($accountColor[$id]) ) { // Se asigna el color de forma aleatoria a cada id - $color = array_rand(self::$colors); + $color = array_rand(self::COLORS); - $accountColor[$id] = '#' . self::$colors[$color]; + $accountColor[$id] = '#' . self::COLORS[$color]; $this->session->setAccountColor($accountColor); } return $accountColor[$id]; } + + /** + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + */ + protected function initialize() + { + $this->accountRepository = $this->dic->get(AccountRepository::class); + $this->accountToTagRepository = $this->dic->get(AccountToTagRepository::class); + $this->accountToUserRepository = $this->dic->get(AccountToUserRepository::class); + $this->accountToUserGroupRepository = $this->dic->get(AccountToUserGroupRepository::class); + $this->configData = $this->config->getConfigData(); + } } \ No newline at end of file diff --git a/lib/SP/Services/Account/AccountService.php b/lib/SP/Services/Account/AccountService.php index 99c097dd..8c5294bc 100644 --- a/lib/SP/Services/Account/AccountService.php +++ b/lib/SP/Services/Account/AccountService.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -25,11 +25,8 @@ namespace SP\Services\Account; use Defuse\Crypto\Exception\CryptoException; -use SP\Account\AccountAcl; use SP\Account\AccountRequest; use SP\Account\AccountUtil; -use SP\Core\Acl\Acl; -use SP\Core\Acl\ActionsInterface; use SP\Core\Crypt\Crypt; use SP\Core\Crypt\Session as CryptSession; use SP\Core\Exceptions\QueryException; @@ -38,7 +35,6 @@ use SP\Core\Session\Session; use SP\DataModel\AccountData; use SP\DataModel\Dto\AccountDetailsResponse; use SP\DataModel\ItemSearchData; -use SP\Log\Log; use SP\Repositories\Account\AccountRepository; use SP\Repositories\Account\AccountToTagRepository; use SP\Repositories\Account\AccountToUserGroupRepository; @@ -171,13 +167,12 @@ class AccountService extends Service implements AccountServiceInterface * @return int * @throws QueryException * @throws SPException - * @throws \SP\Core\Dic\ContainerException * @throws \SP\Core\Exceptions\ConstraintException */ public function create(AccountRequest $accountRequest) { - $accountRequest->changePermissions = (new AccountAcl(ActionsInterface::ACCOUNT_EDIT))->isShowPermission(); - $accountRequest->userGroupId ?: $this->session->getUserData()->getUserGroupId(); + $accountRequest->changePermissions = AccountAclService::getShowPermission($this->session->getUserData(), $this->session->getUserProfile()); + $accountRequest->userGroupId = $accountRequest->userGroupId ?: $this->session->getUserData()->getUserGroupId(); $pass = $this->getPasswordEncrypted($accountRequest->pass); @@ -250,13 +245,12 @@ class AccountService extends Service implements AccountServiceInterface * @throws SPException * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface - * @throws \SP\Core\Dic\ContainerException * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Services\Config\ParameterNotFoundException */ public function update(AccountRequest $accountRequest) { - $accountRequest->changePermissions = (new AccountAcl(ActionsInterface::ACCOUNT_EDIT))->isShowPermission(); + $accountRequest->changePermissions = AccountAclService::getShowPermission($this->session->getUserData(), $this->session->getUserProfile()); // Cambiar el grupo principal si el usuario es Admin $accountRequest->changeUserGroup = ($accountRequest->userGroupId !== 0 @@ -405,29 +399,6 @@ class AccountService extends Service implements AccountServiceInterface return $this; } - /** - * Logs account action - * - * @param int $id - * @param int $actionId - * @return \SP\Core\Messages\LogMessage - * @throws SPException - * @throws \SP\Core\Dic\ContainerException - */ - public function logAction($id, $actionId) - { - $account = $this->accountRepository->getById($id); - - $Log = new Log(); - $LogMessage = $Log->getLogMessage(); - $LogMessage->setAction(Acl::getActionInfo($actionId)); - $LogMessage->addDetails(__u('ID'), $id); - $LogMessage->addDetails(__u('Cuenta'), $account->getClientName() . ' / ' . $account->getName()); - $Log->writeLog(); - - return $LogMessage; - } - /** * @param $accountId * @return array diff --git a/lib/SP/Services/Account/AccountToTagService.php b/lib/SP/Services/Account/AccountToTagService.php index 248027d6..3ea9a4ea 100644 --- a/lib/SP/Services/Account/AccountToTagService.php +++ b/lib/SP/Services/Account/AccountToTagService.php @@ -24,6 +24,7 @@ namespace SP\Services\Account; +use SP\DataModel\ItemData; use SP\Repositories\Account\AccountToTagRepository; use SP\Services\Service; @@ -50,7 +51,7 @@ class AccountToTagService extends Service /** * @param $id - * @return array + * @return ItemData[] */ public function getTagsByAccountId($id) { diff --git a/lib/SP/Services/Export/XmlExportService.php b/lib/SP/Services/Export/XmlExportService.php index b3312f64..6d0cbb47 100644 --- a/lib/SP/Services/Export/XmlExportService.php +++ b/lib/SP/Services/Export/XmlExportService.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -485,9 +485,9 @@ class XmlExportService extends Service $accountIV = $this->xml->createElement('key', $this->escapeChars($account->getKey())); $tags = $this->xml->createElement('tags'); - foreach ($accountToTagService->getTagsByAccountId($account->getId()) as $id => $name) { + foreach ($accountToTagService->getTagsByAccountId($account->getId()) as $itemData) { $tag = $this->xml->createElement('tag'); - $tag->setAttribute('id', $id); + $tag->setAttribute('id', $itemData->getId()); $tags->appendChild($tag); } diff --git a/lib/SP/Services/UserGroup/UserToUserGroupService.php b/lib/SP/Services/UserGroup/UserToUserGroupService.php index cd7b4c3d..cbbf828d 100644 --- a/lib/SP/Services/UserGroup/UserToUserGroupService.php +++ b/lib/SP/Services/UserGroup/UserToUserGroupService.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -39,15 +39,6 @@ class UserToUserGroupService extends Service */ protected $userToUserGroupRepository; - /** - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface - */ - protected function initialize() - { - $this->userToUserGroupRepository = $this->dic->get(UserToUserGroupRepository::class); - } - /** * @param $id * @return \SP\DataModel\UserToUserGroupData[] @@ -95,4 +86,36 @@ class UserToUserGroupService extends Service return $usersId; } + + /** + * Checks whether the user is included in the group + * + * @param $userId + * @param $groupId + * @return bool + */ + public function checkUserInGroup($groupId, $userId) + { + return $this->userToUserGroupRepository->checkUserInGroup($groupId, $userId); + } + + /** + * Returns the groups which the user belongs to + * + * @param $userId + * @return array + */ + public function getGroupsForUser($userId) + { + return $this->userToUserGroupRepository->getGroupsForUser($userId); + } + + /** + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + */ + protected function initialize() + { + $this->userToUserGroupRepository = $this->dic->get(UserToUserGroupRepository::class); + } } \ No newline at end of file diff --git a/lib/SP/Storage/FileCache.php b/lib/SP/Storage/FileCache.php index 3d06a129..b699a334 100644 --- a/lib/SP/Storage/FileCache.php +++ b/lib/SP/Storage/FileCache.php @@ -58,6 +58,12 @@ class FileCache implements FileStorageInterface */ public function save($path, $data) { + $dir = dirname($path); + + if (!is_dir($dir) && mkdir($dir, 0700, true) === false) { + throw new RuntimeException(sprintf(__('No es posible crear el directorio: %s'), $dir)); + } + if (file_exists($path) && !is_writable($path)) { throw new RuntimeException(sprintf(__('No es posible leer/escribir el archivo: %s'), $path)); } @@ -68,4 +74,22 @@ class FileCache implements FileStorageInterface return $this; } + + /** + * @param string $path + * + * @return FileStorageInterface + */ + public function delete($path) + { + if (file_exists($path) && !is_writable($path)) { + throw new RuntimeException(sprintf(__('No es posible leer/escribir el archivo: %s'), $path)); + } + + if (!unlink($path)) { + throw new RuntimeException(sprintf(__('Error al eliminar el archivo: %s'), $path)); + } + + return $this; + } } \ No newline at end of file diff --git a/lib/SP/Storage/FileStorageInterface.php b/lib/SP/Storage/FileStorageInterface.php index 67e893dc..7d17521f 100644 --- a/lib/SP/Storage/FileStorageInterface.php +++ b/lib/SP/Storage/FileStorageInterface.php @@ -44,4 +44,11 @@ interface FileStorageInterface * @return FileStorageInterface */ public function save($path, $data); + + /** + * @param string $path + * + * @return mixed + */ + public function delete($path); } \ No newline at end of file diff --git a/lib/SP/Util/ArrayUtil.php b/lib/SP/Util/ArrayUtil.php index e70c2f91..e56346d9 100644 --- a/lib/SP/Util/ArrayUtil.php +++ b/lib/SP/Util/ArrayUtil.php @@ -83,6 +83,10 @@ class ArrayUtil */ public static function checkInObjectArray(array $objectArray, $property, $value) { + if (empty($objectArray)) { + return false; + } + foreach ($objectArray as $object) { if (is_object($object) && isset($object->$property) diff --git a/lib/SP/Util/ErrorUtil.php b/lib/SP/Util/ErrorUtil.php index 5801c924..2543cd99 100644 --- a/lib/SP/Util/ErrorUtil.php +++ b/lib/SP/Util/ErrorUtil.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link https://syspass.org + * @author nuxsmin + * @link https://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -24,9 +24,12 @@ namespace SP\Util; +use SP\Core\Acl\AccountPermissionException; +use SP\Core\Acl\UnauthorizedPageException; use SP\Core\Exceptions\FileNotFoundException; use SP\Core\Exceptions\SPException; use SP\Mvc\View\Template; +use SP\Services\User\UpdatedMasterPassException; /** * Class ErrorUtil @@ -45,6 +48,72 @@ class ErrorUtil const ERR_OPERATION_NO_PERMISSION = 4; const ERR_EXCEPTION = 5; + /** + * Establecer la plantilla de error con el código indicado. + * + * @param \SP\Mvc\View\Template $view + * @param \Exception $e + * @param string $replace Template replacement + */ + public static function showExceptionInView(Template $view, \Exception $e, $replace = null) + { + switch (get_class($e)) { + case UpdatedMasterPassException::class: + self::showErrorInView($view, self::ERR_UPDATE_MPASS, $replace); + break; + case UnauthorizedPageException::class: + self::showErrorInView($view, self::ERR_PAGE_NO_PERMISSION, $replace); + break; + case AccountPermissionException::class: + self::showErrorInView($view, self::ERR_ACCOUNT_NO_PERMISSION, $replace); + break; + default; + self::showErrorInView($view, self::ERR_EXCEPTION, $replace); + } + } + + /** + * Establecer la plantilla de error con el código indicado. + * + * @param \SP\Mvc\View\Template $view + * @param int $type int con el tipo de error + * @param string $replace Template replacement + */ + public static function showErrorInView(Template $view, $type, $replace = null) + { + if ($replace === null) { + $view->resetTemplates(); + $view->resetContentTemplates(); + } else { + if ($view->hashContentTemplates()) { + $view->removeContentTemplate($replace); + $view->addContentTemplate('error', Template::PARTIALS_DIR); + } else { + $view->removeTemplate($replace); + $view->addTemplate('error', Template::PARTIALS_DIR); + } + } + + $error = self::getErrorTypes($type); + + $view->append('errors', + [ + 'type' => SPException::WARNING, + 'description' => $error['txt'], + 'hint' => $error['hint'] + ]); + + try { + echo $view->render(); + } catch (FileNotFoundException $e) { + processException($e); + + echo $e->getMessage(); + } + + die(); + } + /** * Return error message by type * @@ -80,43 +149,13 @@ class ErrorUtil ] ]; + if (!isset($errorTypes[$type])) { + return [ + 'txt' => __('Se ha producido una excepción'), + 'hint' => __('Consulte con el administrador') + ]; + } + return $errorTypes[$type]; } - - /** - * Establecer la plantilla de error con el código indicado. - * - * @param \SP\Mvc\View\Template $view - * @param int $type int con el tipo de error - * @param string $replace Template replacement - */ - public static function showErrorInView(Template $view, $type, $replace = null) - { - if ($replace === null) { - $view->resetContentTemplates(); - } else { - $view->removeContentTemplate($replace); - } - - $view->addContentTemplate('error', Template::PARTIALS_DIR); - - $error = self::getErrorTypes($type); - - $view->append('errors', - [ - 'type' => SPException::WARNING, - 'description' => $error['txt'], - 'hint' => $error['hint'] - ]); - - try { - echo $view->render(); - } catch (FileNotFoundException $e) { - processException($e); - - echo $e->getMessage(); - } - - die(); - } } \ No newline at end of file diff --git a/lib/SP/Util/FileUtil.php b/lib/SP/Util/FileUtil.php new file mode 100644 index 00000000..828bad44 --- /dev/null +++ b/lib/SP/Util/FileUtil.php @@ -0,0 +1,60 @@ +. + */ + +namespace SP\Util; + +use FilesystemIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; + +/** + * Class FileUtil + * + * @package SP\Util + */ +class FileUtil +{ + /** + * Removes a directory in a recursive way + * + * @param $dir + * @return bool + * @see https://stackoverflow.com/a/7288067 + */ + public static function rmdir_recursive($dir) + { + if (!is_dir($dir)) { + return true; + } + + $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST); + + foreach ($it as $file) { + if ($file->isDir()) rmdir($file->getPathname()); + else unlink($file->getPathname()); + } + + return rmdir($dir); + } +} \ No newline at end of file diff --git a/public/js/app-actions.js b/public/js/app-actions.js index 22802034..e495226f 100644 --- a/public/js/app-actions.js +++ b/public/js/app-actions.js @@ -245,7 +245,7 @@ sysPass.Actions = function (Common) { Common.appRequests().getActionCall(opts, function (json) { Common.msg.out(json); - account.search(); + account.search($obj); }); } } @@ -272,7 +272,7 @@ sysPass.Actions = function (Common) { if (json.status !== 0) { Common.msg.out(json); } else { - var $container = $(json.data.html); + const $container = $(json.data.html); showFloatingBox($container); @@ -296,10 +296,10 @@ sysPass.Actions = function (Common) { copyPass: function ($obj) { log.info("account:copypass"); - var parentId = $obj.data("parent-id"); - var id = parentId === 0 ? $obj.data("item-id") : parentId; + const parentId = $obj.data("parent-id"); + const id = parentId === 0 ? $obj.data("item-id") : parentId; - var opts = Common.appRequests().getRequestOpts(); + const opts = Common.appRequests().getRequestOpts(); opts.url = ajaxUrl.entrypoint; opts.method = "get"; opts.async = false; @@ -345,25 +345,29 @@ sysPass.Actions = function (Common) { request: function ($obj) { log.info("account:request"); - var opts = Common.appRequests().getRequestOpts(); - opts.url = ajaxUrl.entrypoint; + const opts = Common.appRequests().getRequestOpts(); + opts.url = ajaxUrl.entrypoint + "?r=" + $obj.data("action-route") + "/" + $obj.data("item-id"); opts.data = $obj.serialize(); Common.appRequests().getActionCall(opts, function (json) { Common.msg.out(json); + + if (json.status === 0 && json.data['nextAction'] !== undefined) { + getContent({r: json.data.nextAction['nextAction']}, "account"); + } }); }, // Mostrar los botones de acción en los resultados de búsqueda menu: function ($obj) { $obj.hide(); - var actions = $obj.parent().children(".actions-optional"); + const actions = $obj.parent().children(".actions-optional"); actions.show(250); }, sort: function ($obj) { log.info("account:sort"); - var $frmSearch = $("#frmSearch"); + const $frmSearch = $("#frmSearch"); $frmSearch.find("input[name=\"skey\"]").val($obj.data("key")); $frmSearch.find("input[name=\"sorder\"]").val($obj.data("dir")); @@ -374,8 +378,8 @@ sysPass.Actions = function (Common) { editPass: function ($obj) { log.info("account:editpass"); - var parentId = $obj.data("parent-id"); - var itemId = parentId === undefined ? $obj.data("item-id") : parentId; + const parentId = $obj.data("parent-id"); + const itemId = parentId === undefined ? $obj.data("item-id") : parentId; getContent(Common.appRequests().getRouteForQuery($obj.data("action-route"), itemId), "account"); }, @@ -425,7 +429,7 @@ sysPass.Actions = function (Common) { } const opts = Common.appRequests().getRequestOpts(); - opts.url = ajaxUrl.entrypoint + "?r=" + $obj.data("action-route"); + opts.url = ajaxUrl.entrypoint + "?r=" + $frmSearch.data("action-route"); opts.method = "get"; opts.data = $frmSearch.serialize(); @@ -1008,6 +1012,7 @@ sysPass.Actions = function (Common) { const opts = Common.appRequests().getRequestOpts(); opts.url = ajaxUrl.entrypoint; + opts.method = "get"; opts.data = { r: $obj.data("action-route") + "/" + itemId, sk: Common.sk.get(), @@ -1386,17 +1391,14 @@ sysPass.Actions = function (Common) { log.info("notification:delete"); grid.delete($obj, function (items) { - if (items.length > 0) { - items.join(","); - } else { - items = $obj.data("item-id"); - } + const itemId = $obj.data("item-id"); const opts = Common.appRequests().getRequestOpts(); opts.url = ajaxUrl.entrypoint; opts.method = "get"; opts.data = { - r: $obj.data("action-route") + "/" + items, + r: $obj.data("action-route") + (itemId ? "/" + itemId : ''), + items: items, sk: Common.sk.get(), isAjax: 1 }; diff --git a/public/js/app-actions.min.js b/public/js/app-actions.min.js index 12b85678..d06792ea 100644 --- a/public/js/app-actions.min.js +++ b/public/js/app-actions.min.js @@ -4,42 +4,42 @@ $jscomp.polyfill("Array.prototype.find",function(b){return b?b:function(b,l){ret sysPass.Actions=function(b){var e=b.log,l=0,f={entrypoint:"/index.php"};Object.freeze(f);var g=function(a,c){e.info("getContent");a.isAjax=1;var d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.method="get";d.type="html";d.addHistory=!0;d.data=a;b.appRequests().getActionCall(d,function(a){var d=$("#content");d.empty().html(a);a=b.triggers().views;a.common(d);if(void 0!==c&&"function"===typeof a[c])a[c]();d=$(".mdl-layout__content");0'+c+"
"),h=d.find("img");if(0===h.length)return m(c);h.hide();$.magnificPopup.open({items:{src:d,type:"inline"},callbacks:{open:function(){var a= this;h.on("click",function(){a.close()});setTimeout(function(){var a=b.resizeImage(h);d.css({backgroundColor:"#fff",width:a.width,height:"auto"});h.show("slow")},500)}}})},p={view:function(a){e.info("account:show");g(b.appRequests().getRouteForQuery(a.data("action-route"),a.data("item-id")),"account")},viewHistory:function(a){e.info("account:showHistory");g(b.appRequests().getRouteForQuery(a.data("action-route"),a.val()),"account")},edit:function(a){e.info("account:edit");g(b.appRequests().getRouteForQuery(a.data("action-route"), -a.data("item-id")),"account")},"delete":function(a){e.info("account:delete");var c='

'+b.config().LANG[3]+"

";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(d){d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.data={r:"account/saveDelete/"+a.data("item-id"),sk:b.sk.get()};b.appRequests().getActionCall(d,function(a){b.msg.out(a); -p.search()})}}})},viewPass:function(a){e.info("account:showpass");var c=a.data("parent-id")||0,c=0===c?a.data("item-id"):c,d=a.data("history")||0,h=b.appRequests().getRequestOpts();h.url=f.entrypoint;h.method="get";h.data={r:a.data("action-route")+"/"+c+"/"+d,sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(h,function(a){0!==a.status?b.msg.out(a):(a=$(a.data.html),m(a),l=setTimeout(function(){$.magnificPopup.close()},3E4),a.on("mouseleave",function(){clearTimeout(l);l=setTimeout(function(){$.magnificPopup.close()}, +a.data("item-id")),"account")},"delete":function(a){e.info("account:delete");var c='

'+b.config().LANG[3]+"

";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(d){d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.data={r:"account/saveDelete/"+a.data("item-id"),sk:b.sk.get()};b.appRequests().getActionCall(d,function(d){b.msg.out(d); +p.search(a)})}}})},viewPass:function(a){e.info("account:showpass");var c=a.data("parent-id")||0,c=0===c?a.data("item-id"):c,d=a.data("history")||0,h=b.appRequests().getRequestOpts();h.url=f.entrypoint;h.method="get";h.data={r:a.data("action-route")+"/"+c+"/"+d,sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(h,function(a){0!==a.status?b.msg.out(a):(a=$(a.data.html),m(a),l=setTimeout(function(){$.magnificPopup.close()},3E4),a.on("mouseleave",function(){clearTimeout(l);l=setTimeout(function(){$.magnificPopup.close()}, 3E4)}).on("mouseenter",function(){0!==l&&clearTimeout(l)}))})},copyPass:function(a){e.info("account:copypass");var c=a.data("parent-id"),c=0===c?a.data("item-id"):c,d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.method="get";d.async=!1;d.data={r:a.data("action-route")+"/"+c+"/"+a.data("history"),sk:b.sk.get(),isAjax:1};return b.appRequests().getActionCall(d)},copy:function(a){e.info("account:copy");g(b.appRequests().getRouteForQuery(a.data("action-route"),a.data("item-id")),"account")},saveFavorite:function(a, -c){e.info("account:saveFavorite");var d="on"===a.data("status"),h=d?a.data("action-route-off"):a.data("action-route-on"),q=b.appRequests().getRequestOpts();q.url=f.entrypoint;q.data={r:h+"/"+a.data("item-id"),sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(q,function(h){b.msg.out(h);0===h.status&&(a.data("status",d?"off":"on"),"function"===typeof c&&c())})},request:function(a){e.info("account:request");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.data=a.serialize();b.appRequests().getActionCall(c, -function(a){b.msg.out(a)})},menu:function(a){a.hide();a.parent().children(".actions-optional").show(250)},sort:function(a){e.info("account:sort");var b=$("#frmSearch");b.find('input[name="skey"]').val(a.data("key"));b.find('input[name="sorder"]').val(a.data("dir"));b.find('input[name="start"]').val(a.data("start"));p.search()},editPass:function(a){e.info("account:editpass");var c=a.data("parent-id"),c=void 0===c?a.data("item-id"):c;g(b.appRequests().getRouteForQuery(a.data("action-route"),c),"account")}, -saveEditRestore:function(a){e.info("account:restore");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route")+"/"+a.data("history-id")+"/"+a.data("item-id");c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);void 0!==a.data.itemId&&void 0!==a.data.nextAction&&g(b.appRequests().getRouteForQuery(a.data.nextAction,a.data.itemId),"account")})},listFiles:function(a){e.info("account:getfiles");var c=b.appRequests().getRequestOpts();c.method="get"; -c.type="html";c.url=f.entrypoint;c.data={r:a.data("action-route")+"/"+a.data("item-id"),del:a.data("delete"),sk:b.sk.get()};b.appRequests().getActionCall(c,function(b){a.html(b)})},search:function(a){e.info("account:search");var c=$("#frmSearch");c.find("input[name='sk']").val(b.sk.get());c.find("input[name='skey']").val();c.find("input[name='sorder']").val();void 0!==a&&c.find("input[name='start']").val(0);var d=b.appRequests().getRequestOpts();d.url=f.entrypoint+"?r="+a.data("action-route");d.method= -"get";d.data=c.serialize();b.appRequests().getActionCall(d,function(a){10===a.status&&b.msg.out(a);b.sk.set(a.data.sk);$("#res-content").empty().html(a.data.html)})},save:function(a){e.info("account:save");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route")+"/"+a.data("item-id");c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);void 0!==a.data.itemId&&void 0!==a.data.nextAction&&g(b.appRequests().getRouteForQuery(a.data.nextAction,a.data.itemId), -"account")})}},r={get:function(a){e.info("items:get");var c=a[0].selectize;c.clearOptions();c.load(function(d){var h=b.appRequests().getRequestOpts();h.url=f.entrypoint;h.method="get";h.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:a.data("sk")};b.appRequests().getActionCall(h,function(h){d(h.data);c.setValue(a.data("selected-id"),!0);b.appTriggers().updateFormHash()})})},update:function(a){e.info("items:update");var c=$("#"+a.data("item-dst"))[0].selectize;c.clearOptions();c.load(function(d){var c= -b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.data={r:a.data("item-route"),sk:b.sk.get()};b.appRequests().getActionCall(c,function(a){d(a)})})}},t={logout:function(){b.redirect("index.php?r=login/logout")},login:function(a){e.info("main:login");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("route");c.method="get";c.data=a.serialize();b.appRequests().getActionCall(c,function(d){var c=$(".extra-hidden");switch(d.status){case 0:b.redirect(d.data.url);break; -case 2:b.msg.out(d);a.find("input[type='text'],input[type='password']").val("");a.find("input:first").focus();0
";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault(); -b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c=a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(b.config().LANG[62]);if(0",e=a.data("selection"),f=[];if(e&&($(e).find(".is-selected").each(function(){f.push($(this).data("item-id"))}), -0===f.length))return;mdlDialog().show({text:d,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(a){a.preventDefault();"function"===typeof c&&c(f)}}})}};return{doAction:function(a,c){var d={r:a.r+(void 0!==a.itemId?"/"+a.itemId:""),isAjax:1},e=b.appRequests().getRequestOpts();e.url=f.entrypoint;e.method="get";e.type="html";e.addHistory=!0;e.data=d;b.appRequests().getActionCall(e,function(a){var d= -$("#content");d.empty().html(a);a=b.triggers().views;a.common(d);if(void 0!==c&&"function"===typeof a[c])a[c]();d=$(".mdl-layout__content");0";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get"; -c.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:b.sk.get()};b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&p.listFiles($("#list-account-files"))})}}})}},checks:{wiki:function(a){e.info("checks:wiki");a=$(a.data("src"));a.find("[name='sk']").val(b.sk.get());var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&$("#dokuWikiResCheck").html(a.data)})}},config:{save:function(a){e.info("config:save"); -k.save(a)},masterpass:function(a){var c='

'+b.config().LANG[59]+"

";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(c){c.preventDefault();b.msg.error(b.config().LANG[44]);a.find(":input[type=password]").val("")}},positive:{title:b.config().LANG[43],onClick:function(c){c=a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(b.config().LANG[62]);0";mdlDialog().show({text:h,negative:{title:b.config().LANG[44],onClick:function(e){e.preventDefault();b.appRequests().getActionCall(d,function(d){b.msg.out(d);0===d.status&&g({r:a.data("action-next")+"/"+c})})}},positive:{title:b.config().LANG[43],onClick:function(e){e.preventDefault(); -d.data.notify=1;b.appRequests().getActionCall(d,function(d){b.msg.out(d);0===d.status&&g({r:a.data("action-next")+"/"+c})})}}})},refresh:function(a){e.info("link:refresh");k.state.update(a);var c=a.data("item-id"),d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.data={r:a.data("action-route")+"/"+c,sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(d,function(d){b.msg.out(d);0===d.status&&((d=a.data("action-next"))?g({r:d+"/"+c}):g({r:k.state.tab.route,tabIndex:k.state.tab.index}))})}}, -eventlog:{search:function(a){e.info("eventlog:search");n.search(a)},nav:function(a){e.info("eventlog:nav");n.nav(a)},clear:function(a){var c='

'+b.config().LANG[20]+"

";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c.preventDefault();c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route"); -c.method="get";c.data={sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(c,function(c){b.msg.out(c);0===c.status&&g({r:a.data("nextaction")});b.sk.set(c.csrf)})}}})}},ajaxUrl:f,plugin:{toggle:function(a){e.info("plugin:enable");a={itemId:a.data("item-id"),actionId:a.data("action-id"),sk:b.sk.get(),activeTab:a.data("activetab")};var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.data=a;b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&setTimeout(function(){b.redirect("index.php")}, -2E3)})},reset:function(a){e.info("plugin:reset");var c='

'+b.config().LANG[58]+"

";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c.preventDefault();c={itemId:a.data("item-id"),actionId:a.data("action-id"),sk:b.sk.get(),activeTab:a.data("activetab")};var d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.data= -c;b.appRequests().getActionCall(d,function(a){b.msg.out(a)})}}})}},notification:{check:function(a){e.info("notification:check");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(c,function(c){b.msg.out(c);0===c.status&&g({r:a.data("nextaction")});b.sk.set(c.csrf)})},search:function(a){e.info("notification:search");n.search(a)},show:function(a){e.info("notification:show"); -u.show(a)},save:function(a){e.info("notification:save");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("route");c.data=a.serialize();b.appRequests().getActionCall(c,function(c){b.msg.out(c);0===c.status&&(g({r:a.data("nextaction")}),$.magnificPopup.close())})},"delete":function(a){e.info("notification:delete");n["delete"](a,function(c){0";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c= -$(a.data("src"));c.find("[name='sk']").val(b.sk.get());var d=b.appRequests().getRequestOpts();d.url=f.entrypoint+"?r="+a.data("action-route");d.data=c.serialize();b.appRequests().getActionCall(d,function(a){b.msg.out(a)})}}})}}}}; +c){e.info("account:saveFavorite");var d="on"===a.data("status"),h=d?a.data("action-route-off"):a.data("action-route-on"),q=b.appRequests().getRequestOpts();q.url=f.entrypoint;q.data={r:h+"/"+a.data("item-id"),sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(q,function(h){b.msg.out(h);0===h.status&&(a.data("status",d?"off":"on"),"function"===typeof c&&c())})},request:function(a){e.info("account:request");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route")+"/"+ +a.data("item-id");c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&void 0!==a.data.nextAction&&g({r:a.data.nextAction.nextAction},"account")})},menu:function(a){a.hide();a.parent().children(".actions-optional").show(250)},sort:function(a){e.info("account:sort");var b=$("#frmSearch");b.find('input[name="skey"]').val(a.data("key"));b.find('input[name="sorder"]').val(a.data("dir"));b.find('input[name="start"]').val(a.data("start"));p.search()},editPass:function(a){e.info("account:editpass"); +var c=a.data("parent-id"),c=void 0===c?a.data("item-id"):c;g(b.appRequests().getRouteForQuery(a.data("action-route"),c),"account")},saveEditRestore:function(a){e.info("account:restore");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route")+"/"+a.data("history-id")+"/"+a.data("item-id");c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);void 0!==a.data.itemId&&void 0!==a.data.nextAction&&g(b.appRequests().getRouteForQuery(a.data.nextAction, +a.data.itemId),"account")})},listFiles:function(a){e.info("account:getfiles");var c=b.appRequests().getRequestOpts();c.method="get";c.type="html";c.url=f.entrypoint;c.data={r:a.data("action-route")+"/"+a.data("item-id"),del:a.data("delete"),sk:b.sk.get()};b.appRequests().getActionCall(c,function(b){a.html(b)})},search:function(a){e.info("account:search");var c=$("#frmSearch");c.find("input[name='sk']").val(b.sk.get());c.find("input[name='skey']").val();c.find("input[name='sorder']").val();void 0!== +a&&c.find("input[name='start']").val(0);a=b.appRequests().getRequestOpts();a.url=f.entrypoint+"?r="+c.data("action-route");a.method="get";a.data=c.serialize();b.appRequests().getActionCall(a,function(a){10===a.status&&b.msg.out(a);b.sk.set(a.data.sk);$("#res-content").empty().html(a.data.html)})},save:function(a){e.info("account:save");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route")+"/"+a.data("item-id");c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a); +void 0!==a.data.itemId&&void 0!==a.data.nextAction&&g(b.appRequests().getRouteForQuery(a.data.nextAction,a.data.itemId),"account")})}},r={get:function(a){e.info("items:get");var c=a[0].selectize;c.clearOptions();c.load(function(d){var h=b.appRequests().getRequestOpts();h.url=f.entrypoint;h.method="get";h.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:a.data("sk")};b.appRequests().getActionCall(h,function(h){d(h.data);c.setValue(a.data("selected-id"),!0);b.appTriggers().updateFormHash()})})}, +update:function(a){e.info("items:update");var c=$("#"+a.data("item-dst"))[0].selectize;c.clearOptions();c.load(function(d){var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.data={r:a.data("item-route"),sk:b.sk.get()};b.appRequests().getActionCall(c,function(a){d(a)})})}},t={logout:function(){b.redirect("index.php?r=login/logout")},login:function(a){e.info("main:login");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("route");c.method="get";c.data=a.serialize(); +b.appRequests().getActionCall(c,function(d){var c=$(".extra-hidden");switch(d.status){case 0:b.redirect(d.data.url);break;case 2:b.msg.out(d);a.find("input[type='text'],input[type='password']").val("");a.find("input:first").focus();0";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c=a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(b.config().LANG[62]);if(0",e=a.data("selection"),f=[];if(e&&($(e).find(".is-selected").each(function(){f.push($(this).data("item-id"))}),0===f.length))return;mdlDialog().show({text:d,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(a){a.preventDefault();"function"===typeof c&&c(f)}}})}};return{doAction:function(a,c){var d={r:a.r+(void 0!==a.itemId?"/"+a.itemId:""),isAjax:1},e=b.appRequests().getRequestOpts(); +e.url=f.entrypoint;e.method="get";e.type="html";e.addHistory=!0;e.data=d;b.appRequests().getActionCall(e,function(a){var d=$("#content");d.empty().html(a);a=b.triggers().views;a.common(d);if(void 0!==c&&"function"===typeof a[c])a[c]();d=$(".mdl-layout__content");0";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault(); +b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:b.sk.get()};b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&p.listFiles($("#list-account-files"))})}}})}},checks:{wiki:function(a){e.info("checks:wiki");a=$(a.data("src"));a.find("[name='sk']").val(b.sk.get());var c=b.appRequests().getRequestOpts();c.url=f.entrypoint; +c.data=a.serialize();b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&$("#dokuWikiResCheck").html(a.data)})}},config:{save:function(a){e.info("config:save");k.save(a)},masterpass:function(a){var c='

'+b.config().LANG[59]+"

";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(c){c.preventDefault();b.msg.error(b.config().LANG[44]);a.find(":input[type=password]").val("")}},positive:{title:b.config().LANG[43], +onClick:function(c){c=a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(b.config().LANG[62]);0";mdlDialog().show({text:h,negative:{title:b.config().LANG[44], +onClick:function(e){e.preventDefault();b.appRequests().getActionCall(d,function(d){b.msg.out(d);0===d.status&&g({r:a.data("action-next")+"/"+c})})}},positive:{title:b.config().LANG[43],onClick:function(e){e.preventDefault();d.data.notify=1;b.appRequests().getActionCall(d,function(d){b.msg.out(d);0===d.status&&g({r:a.data("action-next")+"/"+c})})}}})},refresh:function(a){e.info("link:refresh");k.state.update(a);var c=a.data("item-id"),d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.method= +"get";d.data={r:a.data("action-route")+"/"+c,sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(d,function(d){b.msg.out(d);0===d.status&&((d=a.data("action-next"))?g({r:d+"/"+c}):g({r:k.state.tab.route,tabIndex:k.state.tab.index}))})}},eventlog:{search:function(a){e.info("eventlog:search");n.search(a)},nav:function(a){e.info("eventlog:nav");n.nav(a)},clear:function(a){var c='

'+b.config().LANG[20]+"

";mdlDialog().show({text:c,negative:{title:b.config().LANG[44], +onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c.preventDefault();c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("action-route");c.method="get";c.data={sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(c,function(c){b.msg.out(c);0===c.status&&g({r:a.data("nextaction")});b.sk.set(c.csrf)})}}})}},ajaxUrl:f,plugin:{toggle:function(a){e.info("plugin:enable");a={itemId:a.data("item-id"),actionId:a.data("action-id"), +sk:b.sk.get(),activeTab:a.data("activetab")};var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.data=a;b.appRequests().getActionCall(c,function(a){b.msg.out(a);0===a.status&&setTimeout(function(){b.redirect("index.php")},2E3)})},reset:function(a){e.info("plugin:reset");var c='

'+b.config().LANG[58]+"

";mdlDialog().show({text:c,negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43], +onClick:function(c){c.preventDefault();c={itemId:a.data("item-id"),actionId:a.data("action-id"),sk:b.sk.get(),activeTab:a.data("activetab")};var d=b.appRequests().getRequestOpts();d.url=f.entrypoint;d.data=c;b.appRequests().getActionCall(d,function(a){b.msg.out(a)})}}})}},notification:{check:function(a){e.info("notification:check");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(c, +function(c){b.msg.out(c);0===c.status&&g({r:a.data("nextaction")});b.sk.set(c.csrf)})},search:function(a){e.info("notification:search");n.search(a)},show:function(a){e.info("notification:show");u.show(a)},save:function(a){e.info("notification:save");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint+"?r="+a.data("route");c.data=a.serialize();b.appRequests().getActionCall(c,function(c){b.msg.out(c);0===c.status&&(g({r:a.data("nextaction")}),$.magnificPopup.close())})},"delete":function(a){e.info("notification:delete"); +n["delete"](a,function(c){var d=a.data("item-id"),e=b.appRequests().getRequestOpts();e.url=f.entrypoint;e.method="get";e.data={r:a.data("action-route")+(d?"/"+d:""),items:c,sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(e,function(c){b.msg.out(c);g({r:a.data("nextaction")})})})},getActive:function(){e.info("notification:getActive");var a=b.appRequests().getRequestOpts();a.url=f.entrypoint;a.method="get";a.data={r:"items/notifications",sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(a, +function(a){return a})},nav:function(a){e.info("eventlog:nav");n.nav(a)}},wiki:{show:function(a){e.info("wiki:show");var c=b.appRequests().getRequestOpts();c.url=f.entrypoint;c.method="get";c.data={pageName:a.data("pagename"),actionId:a.data("action-id"),sk:b.sk.get(),isAjax:1};b.appRequests().getActionCall(c,function(a){0!==a.status?b.msg.out(a):m(a.data.html)})}},items:r,ldap:{check:function(a){e.info("ldap:check");var c=$(a.data("src"));c.find("[name='sk']").val(b.sk.get());var d=b.appRequests().getRequestOpts(); +d.url=f.entrypoint+"?r="+a.data("action-route");d.data=c.serialize();b.appRequests().getActionCall(d,function(a){b.msg.out(a);0===a.status&&void 0!==a.data.template&&void 0!==a.data.items&&m(a.data.template,{open:function(){var c=$("#ldap-results").find(".list-wrap").empty();a.data.items.forEach(function(a){c.append(b.appTheme().html.getList(a.items,a.icon))})}})})},"import":function(a){e.info("ldap:import");var c='

'+b.config().LANG[57]+"

";mdlDialog().show({text:c, +negative:{title:b.config().LANG[44],onClick:function(a){a.preventDefault();b.msg.error(b.config().LANG[44])}},positive:{title:b.config().LANG[43],onClick:function(c){c=$(a.data("src"));c.find("[name='sk']").val(b.sk.get());var d=b.appRequests().getRequestOpts();d.url=f.entrypoint+"?r="+a.data("action-route");d.data=c.serialize();b.appRequests().getActionCall(d,function(a){b.msg.out(a)})}}})}}}}; diff --git a/public/js/app-main.js b/public/js/app-main.js index 93bd1e0d..e4214acf 100644 --- a/public/js/app-main.js +++ b/public/js/app-main.js @@ -653,10 +653,11 @@ sysPass.Main = function () { const setupCallbacks = function () { log.info("setupCallbacks"); - const page = $("#container").data("page"); + const $container = $("#container"); + const page = $container.data("page"); if (page !== "" && typeof appTriggers.views[page] === "function") { - appTriggers.views[page](); + appTriggers.views[page]($container); } if ($("footer").length > 0) { diff --git a/public/js/app-main.min.js b/public/js/app-main.min.js index f342e8ab..8728fc9b 100644 --- a/public/js/app-main.min.js +++ b/public/js/app-main.min.js @@ -1,5 +1,5 @@ var $jscomp={scope:{},findInternal:function(b,l,h){b instanceof String&&(b=String(b));for(var m=b.length,n=0;n"+a.messages.join("
"));switch(b){case 0:e.ok(d);break;case 1:e.error(d);break;case 2:e.warn(d);break;case 10:t.main.logout();break;case 100:e.ok(d);e.sticky(d);break;case 101:e.error(d);e.sticky(d);break;case 102:e.warn(d);e.sticky(d);break;default:e.error(d)}}},html:{error:function(a){return'

Oops...
'+c.LANG[1]+ -"
"+a+"

"}}};Object.freeze(e);String.format||(String.format=function(a){var b=Array.prototype.slice.call(arguments,1);return a.replace(/{(\d+)}/g,function(a,c){return"undefined"!==typeof b[c]?b[c]:a})});var M=function(){f.info("getEnvironment");var a=window.location.pathname.split("/");c.APP_ROOT=window.location.protocol+"//"+window.location.host+function(){for(var b="",c=1;c<=a.length-2;c++)b+="/"+a[c];return b}();var b=v.getRequestOpts();b.url="/index.php?r=bootstrap/getEnvironment";b.method= -"get";b.useLoading=!1;b.data={isAjax:1};return v.getActionCall(b,function(a){c.LANG=a.lang;c.PK=a.pk;c.CHECK_UPDATES=a.check_updates;c.CRYPT.setPublicKey(a.pk);c.TIMEZONE=a.timezone;c.LOCALE=a.locale;c.DEBUG=a.debug;c.MAX_FILE_SIZE=parseInt(a.max_file_size);c.COOKIES_ENABLED=a.cookies_enabled;c.PLUGINS=a.plugins;c.LOGGEDIN=a.loggedin;c.AUTHBASIC_AUTOLOGIN=a.authbasic_autologin;c.IMPORT_ALLOWED_EXTS=a.import_allowed_exts;c.FILES_ALLOWED_EXTS=a.files_allowed_exts;Object.freeze(c)})},H=function(a){for(var b= +hideEasing:"linear",showMethod:"fadeIn",hideMethod:"fadeOut"};var L=function(){f.info("setupCallbacks");var a=$("#container"),b=a.data("page");if(""!==b&&"function"===typeof p.views[b])p.views[b](a);0<$("footer").length&&p.views.footer();$("#btnBack").click(function(){A("index.php")});p.bodyHooks()},e={ok:function(a){toastr.success(a)},error:function(a){toastr.error(a)},warn:function(a){toastr.warning(a)},info:function(a){toastr.info(a)},sticky:function(a,b){var d={timeOut:0};"function"===typeof b&& +(d.onHidden=b);toastr.warning(a,c.LANG[60],d)},out:function(a){if("object"===typeof a){var b=a.status,d=a.description;void 0!==a.messages&&0"+a.messages.join("
"));switch(b){case 0:e.ok(d);break;case 1:e.error(d);break;case 2:e.warn(d);break;case 10:t.main.logout();break;case 100:e.ok(d);e.sticky(d);break;case 101:e.error(d);e.sticky(d);break;case 102:e.warn(d);e.sticky(d);break;default:e.error(d)}}},html:{error:function(a){return'

Oops...
'+ +c.LANG[1]+"
"+a+"

"}}};Object.freeze(e);String.format||(String.format=function(a){var b=Array.prototype.slice.call(arguments,1);return a.replace(/{(\d+)}/g,function(a,c){return"undefined"!==typeof b[c]?b[c]:a})});var M=function(){f.info("getEnvironment");var a=window.location.pathname.split("/");c.APP_ROOT=window.location.protocol+"//"+window.location.host+function(){for(var b="",c=1;c<=a.length-2;c++)b+="/"+a[c];return b}();var b=v.getRequestOpts();b.url="/index.php?r=bootstrap/getEnvironment"; +b.method="get";b.useLoading=!1;b.data={isAjax:1};return v.getActionCall(b,function(a){c.LANG=a.lang;c.PK=a.pk;c.CHECK_UPDATES=a.check_updates;c.CRYPT.setPublicKey(a.pk);c.TIMEZONE=a.timezone;c.LOCALE=a.locale;c.DEBUG=a.debug;c.MAX_FILE_SIZE=parseInt(a.max_file_size);c.COOKIES_ENABLED=a.cookies_enabled;c.PLUGINS=a.plugins;c.LOGGEDIN=a.loggedin;c.AUTHBASIC_AUTOLOGIN=a.authbasic_autologin;c.IMPORT_ALLOWED_EXTS=a.import_allowed_exts;c.FILES_ALLOWED_EXTS=a.files_allowed_exts;Object.freeze(c)})},H=function(a){for(var b= [],c,e=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),f=0;fform").each(function(){var a=$(this);a.find("button.btn-clear").on("click", -function(b){b.preventDefault();a.trigger("reset")})})},config:function(){d.info("views:config");var a=$("#drop-import-files");if(0form").each(function(){var a=$(this);a.find("button.btn-clear").on("click",function(b){b.preventDefault();a.trigger("reset")})})},config:function(){e.info("views:config");var a=$("#drop-import-files");if(0