From e2e39483b4bcf78b069c76aa3ab1314b0d1967da Mon Sep 17 00:00:00 2001 From: nuxsmin Date: Sun, 4 Feb 2018 18:52:00 +0100 Subject: [PATCH] * [MOD] Improved accounts management * [MOD] Code refactoring * [MOD] Minor fixes --- .../web/Controllers/AccountController.php | 121 +- .../Helpers/Account/AccountActionsDto.php | 120 ++ .../{ => Account}/AccountActionsHelper.php | 411 ++++-- .../Helpers/Account/AccountHelper.php | 337 +++++ .../Helpers/Account/AccountHistoryHelper.php | 173 +++ .../{ => Account}/AccountPasswordHelper.php | 26 +- .../{ => Account}/AccountSearchHelper.php | 10 +- .../web/Controllers/Helpers/AccountHelper.php | 505 ------- .../views/account/account-permissions.inc | 88 +- .../views/account/account-request.inc | 11 +- .../material-blue/views/account/account.inc | 73 +- .../material-blue/views/account/details.inc | 26 +- lib/SP/Account/AccountUtil.php | 55 +- lib/SP/Config/Config.php | 14 +- lib/SP/Controller/ControllerBase.php | 1 + lib/SP/Core/Acl/UnauthorizedPageException.php | 48 + lib/SP/Core/Session/Session.php | 48 +- .../DataModel/Dto/AccountDetailsResponse.php | 6 +- lib/SP/Forms/AccountForm.php | 16 +- lib/SP/Mvc/Model/QueryAssignment.php | 97 ++ .../{QueryFilter.php => QueryCondition.php} | 14 +- lib/SP/Mvc/View/Components/SelectItem.php | 20 + .../Mvc/View/Components/SelectItemAdapter.php | 69 +- .../Account/AccountRepository.php | 198 +-- .../Account/AccountToTagRepository.php | 10 +- .../Account/AccountToUserRepository.php | 10 +- .../Repositories/Client/ClientRepository.php | 6 +- lib/SP/Services/Account/AccountService.php | 42 +- .../Auth}/AuthException.php | 7 +- lib/SP/Services/Auth/LoginService.php | 9 +- .../User/UpdatedMasterPassException.php | 48 + lib/SP/Services/User/UserPassService.php | 2 + lib/SP/Services/User/UserService.php | 2 + public/js/app-actions.js | 10 +- public/js/app-actions.min.js | 4 +- public/js/app-main.js | 1180 +++++++++-------- public/js/app-main.min.js | 50 +- public/js/app-requests.js | 28 +- public/js/app-triggers.js | 155 ++- public/js/app-triggers.min.js | 20 +- public/js/app-util.js | 27 + public/js/app.js | 15 +- public/js/app.min.js | 2 +- 43 files changed, 2328 insertions(+), 1786 deletions(-) create mode 100644 app/modules/web/Controllers/Helpers/Account/AccountActionsDto.php rename app/modules/web/Controllers/Helpers/{ => Account}/AccountActionsHelper.php (65%) create mode 100644 app/modules/web/Controllers/Helpers/Account/AccountHelper.php create mode 100644 app/modules/web/Controllers/Helpers/Account/AccountHistoryHelper.php rename app/modules/web/Controllers/Helpers/{ => Account}/AccountPasswordHelper.php (76%) rename app/modules/web/Controllers/Helpers/{ => Account}/AccountSearchHelper.php (97%) delete mode 100644 app/modules/web/Controllers/Helpers/AccountHelper.php create mode 100644 lib/SP/Core/Acl/UnauthorizedPageException.php create mode 100644 lib/SP/Mvc/Model/QueryAssignment.php rename lib/SP/Mvc/Model/{QueryFilter.php => QueryCondition.php} (86%) rename lib/SP/{Core/Exceptions => Services/Auth}/AuthException.php (84%) create mode 100644 lib/SP/Services/User/UpdatedMasterPassException.php create mode 100644 public/js/app-util.js diff --git a/app/modules/web/Controllers/AccountController.php b/app/modules/web/Controllers/AccountController.php index 9d3f8c70..0d778284 100644 --- a/app/modules/web/Controllers/AccountController.php +++ b/app/modules/web/Controllers/AccountController.php @@ -35,14 +35,14 @@ use SP\DataModel\AccountExtData; use SP\Forms\AccountForm; use SP\Http\JsonResponse; use SP\Http\Request; -use SP\Modules\Web\Controllers\Helpers\AccountHelper; -use SP\Modules\Web\Controllers\Helpers\AccountPasswordHelper; -use SP\Modules\Web\Controllers\Helpers\AccountSearchHelper; +use SP\Modules\Web\Controllers\Helpers\Account\AccountHelper; +use SP\Modules\Web\Controllers\Helpers\Account\AccountHistoryHelper; +use SP\Modules\Web\Controllers\Helpers\Account\AccountPasswordHelper; +use SP\Modules\Web\Controllers\Helpers\Account\AccountSearchHelper; use SP\Modules\Web\Controllers\Helpers\LayoutHelper; use SP\Modules\Web\Controllers\Traits\ItemTrait; use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Mvc\Controller\CrudControllerInterface; -use SP\Repositories\PublicLink\PublicLinkRepository; use SP\Services\Account\AccountFileService; use SP\Services\Account\AccountHistoryService; use SP\Services\Account\AccountService; @@ -73,9 +73,9 @@ class AccountController extends ControllerBase implements CrudControllerInterfac public function indexAction() { try { - $AccountSearchHelper = new AccountSearchHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - $AccountSearchHelper->getSearchBox(); - $AccountSearchHelper->getAccountSearch(); + $accountSearchHelper = new AccountSearchHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $accountSearchHelper->getSearchBox(); + $accountSearchHelper->getAccountSearch(); $this->eventDispatcher->notifyEvent('show.account.search', $this); } catch (\Exception $e) { @@ -127,15 +127,9 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ->withUserGroupsById($accountDetailsResponse) ->withTagsById($accountDetailsResponse); - $AccountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - - if (!$AccountHelper->setAccount( - $accountDetailsResponse, - $this->accountService, - ActionsInterface::ACCOUNT_VIEW - )) { - return; - } + $accountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $accountHelper->setIsView(true); + $accountHelper->setViewForAccount($accountDetailsResponse, ActionsInterface::ACCOUNT_VIEW); $this->view->addTemplate('account'); $this->view->assign('title', @@ -146,12 +140,8 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ] ); - $this->view->assign('isView', true); - $this->accountService->incrementViewCounter($id); - $AccountHelper->setCommonData(); - $this->eventDispatcher->notifyEvent('show.account', $this); } catch (\Exception $e) { debugLog($e->getMessage(), true); @@ -170,8 +160,8 @@ class AccountController extends ControllerBase implements CrudControllerInterfac */ public function viewLinkAction($hash) { - $LayoutHelper = new LayoutHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - $LayoutHelper->getPublicLayout('account-link', 'account'); + $layoutHelper = new LayoutHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $layoutHelper->getPublicLayout('account-link', 'account'); try { $publicLinkService = new PublicLinkService(); @@ -259,13 +249,11 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $this->view->addTemplate('files-list', 'account'); $this->view->assign('deleteEnabled', Request::analyze('del', 0)); - $this->view->assign('files', (new AccountFileService())->getByAccountId($id)); $this->view->assign('sk', SessionUtil::getSessionKey()); $this->view->assign('fileViewRoute', Acl::getActionRoute(ActionsInterface::ACCOUNT_FILE_VIEW)); $this->view->assign('fileDownloadRoute', Acl::getActionRoute(ActionsInterface::ACCOUNT_FILE_DOWNLOAD)); $this->view->assign('fileDeleteRoute', Acl::getActionRoute(ActionsInterface::ACCOUNT_FILE_DELETE)); - $this->view->assign('fileUploadRoute', Acl::getActionRoute(ActionsInterface::ACCOUNT_FILE_UPLOAD)); if (!is_array($this->view->files) || count($this->view->files) === 0) { return; @@ -287,13 +275,8 @@ class AccountController extends ControllerBase implements CrudControllerInterfac public function createAction() { try { - $AccountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - $AccountHelper->setActionId(ActionsInterface::ACCOUNT_CREATE); - - // Obtener los datos de la cuenta antes y comprobar el acceso - if (!$AccountHelper->checkAccess()) { - return; - } + $accountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $accountHelper->setViewForBlank(ActionsInterface::ACCOUNT_CREATE); $this->view->addTemplate('account'); $this->view->assign('title', @@ -305,8 +288,6 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ); $this->view->assign('formRoute', 'account/saveCreate'); - $AccountHelper->setCommonData(); - $this->eventDispatcher->notifyEvent('show.account.create', $this); } catch (\Exception $e) { debugLog($e->getMessage(), true); @@ -331,15 +312,8 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ->withUserGroupsById($accountDetailsResponse) ->withTagsById($accountDetailsResponse); - $AccountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - - if (!$AccountHelper->setAccount( - $accountDetailsResponse, - $this->accountService, - ActionsInterface::ACCOUNT_COPY - )) { - return; - } + $accountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $accountHelper->setViewForAccount($accountDetailsResponse, ActionsInterface::ACCOUNT_COPY); $this->view->addTemplate('account'); $this->view->assign('title', @@ -351,8 +325,6 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ); $this->view->assign('formRoute', 'account/saveCopy'); - $AccountHelper->setCommonData(); - $this->eventDispatcher->notifyEvent('show.account.copy', $this); } catch (\Exception $e) { debugLog($e->getMessage(), true); @@ -377,15 +349,8 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ->withUserGroupsById($accountDetailsResponse) ->withTagsById($accountDetailsResponse); - $AccountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - - if (!$AccountHelper->setAccount( - $accountDetailsResponse, - $this->accountService, - ActionsInterface::ACCOUNT_EDIT - )) { - return; - } + $accountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $accountHelper->setViewForAccount($accountDetailsResponse, ActionsInterface::ACCOUNT_EDIT); $this->view->addTemplate('account'); $this->view->assign('title', @@ -396,11 +361,10 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ] ); $this->view->assign('formRoute', 'account/saveEdit'); + $this->view->assign(__FUNCTION__); $this->accountService->incrementViewCounter($id); - $AccountHelper->setCommonData(); - $this->eventDispatcher->notifyEvent('show.account.edit', $this); } catch (\Exception $e) { debugLog($e->getMessage(), true); @@ -424,15 +388,8 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ->withUsersById($accountDetailsResponse) ->withUserGroupsById($accountDetailsResponse); - $AccountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - - if (!$AccountHelper->setAccount( - $accountDetailsResponse, - $this->accountService, - ActionsInterface::ACCOUNT_DELETE - )) { - return; - } + $accountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $accountHelper->setViewForAccount($accountDetailsResponse, ActionsInterface::ACCOUNT_DELETE); $this->view->addTemplate('account'); $this->view->assign('title', @@ -444,8 +401,6 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ); $this->view->assign('formRoute', 'account/saveDelete'); - $AccountHelper->setCommonData(); - $this->eventDispatcher->notifyEvent('show.account.delete', $this); } catch (\Exception $e) { debugLog($e->getMessage(), true); @@ -469,15 +424,8 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ->withUsersById($accountDetailsResponse) ->withUserGroupsById($accountDetailsResponse); - $AccountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - - if (!$AccountHelper->setAccount( - $accountDetailsResponse, - $this->accountService, - ActionsInterface::ACCOUNT_EDIT_PASS - )) { - return; - } + $accountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $accountHelper->setViewForAccount($accountDetailsResponse, ActionsInterface::ACCOUNT_EDIT_PASS); $this->view->addTemplate('account-editpass'); $this->view->assign('title', @@ -489,7 +437,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ); $this->view->assign('formRoute', 'account/saveEditPass'); - $this->view->assign('accountPassDateChange', gmdate('Y-m-d', $AccountHelper->getAccountDetailsResponse()->getAccountVData()->getPassDateChange())); + $this->view->assign('accountPassDateChange', gmdate('Y-m-d', $accountDetailsResponse->getAccountVData()->getPassDateChange())); $this->eventDispatcher->notifyEvent('show.account.editpass', $this); } catch (\Exception $e) { @@ -512,15 +460,8 @@ class AccountController extends ControllerBase implements CrudControllerInterfac $accountHistoryService = new AccountHistoryService(); $accountHistoryData = $accountHistoryService->getById($id); - $AccountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - - if (!$AccountHelper->setAccountHistory( - $accountHistoryService, - $accountHistoryData, - ActionsInterface::ACCOUNT_VIEW_HISTORY) - ) { - return; - } + $accountHistoryHelper = new AccountHistoryHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $accountHistoryHelper->setView($accountHistoryData, ActionsInterface::ACCOUNT_VIEW_HISTORY); $this->view->addTemplate('account-history'); @@ -533,7 +474,6 @@ class AccountController extends ControllerBase implements CrudControllerInterfac ); $this->view->assign('formRoute', 'account/saveRestore'); - $this->view->assign('isView', true); $this->eventDispatcher->notifyEvent('show.account.history', $this); } catch (\Exception $e) { @@ -553,12 +493,9 @@ class AccountController extends ControllerBase implements CrudControllerInterfac public function requestAccessAction($id) { try { - $AccountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - $AccountHelper->setAccount( - $this->accountService->getById($id), - $this->accountService, - ActionsInterface::ACCOUNT_REQUEST - ); + $accountHelper = new AccountHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $accountHelper->setIsView(true); + $accountHelper->setViewForRequest($this->accountService->getById($id), ActionsInterface::ACCOUNT_REQUEST); $this->view->addTemplate('account-request'); $this->view->assign('formRoute', 'account/saveRequest'); diff --git a/app/modules/web/Controllers/Helpers/Account/AccountActionsDto.php b/app/modules/web/Controllers/Helpers/Account/AccountActionsDto.php new file mode 100644 index 00000000..8b58f217 --- /dev/null +++ b/app/modules/web/Controllers/Helpers/Account/AccountActionsDto.php @@ -0,0 +1,120 @@ +. + */ + +namespace SP\Modules\Web\Controllers\Helpers\Account; + +/** + * Class AccountActionsDto + * + * @package SP\Modules\Web\Controllers\Helpers\Account + */ +class AccountActionsDto +{ + /** + * @var int + */ + private $accountId; + /** + * @var int + */ + private $accountHistoryId; + /** + * @var int + */ + private $accountParentId; + /** + * @var bool + */ + private $publicLink = false; + + /** + * AccountActionsDto constructor. + * + * @param int $accountId + * @param int $accountHistoryId + * @param int $accountParentId + */ + public function __construct($accountId, $accountHistoryId = null, $accountParentId = null) + { + $this->accountId = $accountId; + $this->accountHistoryId = $accountHistoryId; + $this->accountParentId = $accountParentId; + } + + /** + * @return int + */ + public function getAccountId() + { + return $this->accountId; + } + + /** + * @return int + */ + public function getAccountHistoryId() + { + return $this->accountHistoryId; + } + + /** + * @return int + */ + public function getAccountParentId() + { + return $this->accountParentId; + } + + /** + * @return bool + */ + public function isHistory() + { + return $this->accountHistoryId !== null; + } + + /** + * @return bool + */ + public function isLinked() + { + return $this->accountParentId !== null; + } + + /** + * @return bool + */ + public function hasPublicLink() + { + return $this->publicLink; + } + + /** + * @param bool $publicLink + */ + public function setPublicLink($publicLink) + { + $this->publicLink = (bool)$publicLink; + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/Helpers/AccountActionsHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php similarity index 65% rename from app/modules/web/Controllers/Helpers/AccountActionsHelper.php rename to app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php index 145f2c3e..a08c25ff 100644 --- a/app/modules/web/Controllers/Helpers/AccountActionsHelper.php +++ b/app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php @@ -1,13 +1,37 @@ . + */ -namespace SP\Modules\Web\Controllers\Helpers; +namespace SP\Modules\Web\Controllers\Helpers\Account; +use SP\Account\AccountAcl; use SP\Account\AccountSearchItem; use SP\Core\Acl\Acl; use SP\Core\Acl\ActionsInterface; use SP\Core\UI\ThemeIconsBase; use SP\Html\DataGrid\DataGridAction; use SP\Html\DataGrid\DataGridActionType; +use SP\Modules\Web\Controllers\Helpers\HelperBase; /** * Class AccountIconsHelper @@ -20,6 +44,10 @@ class AccountActionsHelper extends HelperBase * @var ThemeIconsBase */ protected $icons; + /** + * @var string + */ + protected $sk; /** * @return DataGridAction @@ -35,13 +63,184 @@ class AccountActionsHelper extends HelperBase $action->setIcon($this->icons->getIconView()); $action->setReflectionFilter(AccountSearchItem::class, 'isShowView'); $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); - $action->addData('action-sk', $this->view->sk); + $action->addData('action-sk', $this->sk); $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); $action->addAttribute('type', 'button'); return $action; } + /** + * Set icons for view + * + * @param AccountAcl $accountAcl + * @param AccountActionsDto $accountActionsDto + * @return DataGridAction[] + */ + public function getActionsForAccount(AccountAcl $accountAcl, AccountActionsDto $accountActionsDto) + { + $actionsEnabled = []; + + $actionBack = $this->getBackAction(); + + if ($accountActionsDto->isHistory()) { + $actionBack->addData('item-id', $accountActionsDto->getAccountId()); + $actionBack->setName(__('Ver Actual')); + $actionBack->setTitle(__('Ver Actual')); + } else { + $actionBack->setData([]); + $actionBack->setClasses(['btn-back']); + } + + $actionsEnabled[] = $actionBack; + + if ($accountAcl->isShowDelete()) { + $actionsEnabled[] = $this->getDeleteAction()->addData('item-id', $accountActionsDto->getAccountId()); + } + + if ($accountActionsDto->isHistory() === false + && $accountActionsDto->isLinked() === false + && $accountAcl->isShowLink() + && $accountAcl->isShowViewPass() + ) { + $actionsEnabled[] = $accountActionsDto->hasPublicLink() ? $this->getPublicLinkRefreshAction() : $this->getPublicLinkAction(); + } + + if ($accountAcl->isShowViewPass()) { + $actionViewPass = $this->getViewPassAction(); + $actionCopy = $this->getCopyPassAction(); + + $actionViewPass->addData('parent-id', $accountActionsDto->getAccountParentId()); + $actionCopy->addData('parent-id', $accountActionsDto->getAccountParentId()); + + $actionViewPass->addData('history', (int)$accountActionsDto->isHistory()); + $actionCopy->addData('history', (int)$accountActionsDto->isHistory()); + + if ($accountActionsDto->isHistory()) { + $actionViewPass->addData('item-id', $accountActionsDto->getAccountHistoryId()); + $actionCopy->addData('item-id', $accountActionsDto->getAccountHistoryId()); + } else { + $actionViewPass->addData('item-id', $accountActionsDto->getAccountId()); + $actionCopy->addData('item-id', $accountActionsDto->getAccountId()); + } + + $actionsEnabled[] = $actionViewPass; + $actionsEnabled[] = $actionCopy; + } + + if ($accountAcl->isShowCopy()) { + $actionsEnabled[] = $this->getCopyAction()->addData('item-id', $accountActionsDto->getAccountId()); + } + + if ($accountAcl->isShowEditPass()) { + $actionsEnabled[] = $this->getEditPassAction()->addData('item-id', $accountActionsDto->getAccountId()); + } + + if ($accountAcl->isShowEdit()) { + $actionsEnabled[] = $this->getEditAction()->addData('item-id', $accountActionsDto->getAccountId()); + } + + if ($accountAcl->getAction() === ActionsInterface::ACCOUNT_VIEW + && !$accountAcl->isShowEdit() + && $this->configData->isMailRequestsEnabled() + ) { + $actionsEnabled[] = $this->getRequestAction()->addData('item-id', $accountActionsDto->getAccountId()); + } + + if ($accountAcl->isShowRestore()) { + $actionRestore = $this->getRestoreAction(); + $actionRestore->addData('item-id', $accountActionsDto->getAccountId()); + $actionRestore->addData('history-id', $accountActionsDto->getAccountHistoryId()); + + $actionsEnabled[] = $actionRestore; + } + + if ($accountAcl->isShowSave()) { + $actionsEnabled[] = $this->getSaveAction()->addAttribute('form', 'frmAccount'); + } + + return $actionsEnabled; + } + + /** + * @return DataGridAction + */ + public function getBackAction() + { + $action = new DataGridAction(); + $action->setId('btnBack'); + $action->setName(__('Atrás')); + $action->setTitle(__('Atrás')); + $action->addClass('btn-action'); + $action->setIcon($this->icons->getIconBack()); + $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); + $action->addData('action-sk', $this->sk); + $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); + $action->addAttribute('type', 'button'); + + return $action; + } + + /** + * @return DataGridAction + */ + public function getDeleteAction() + { + $action = new DataGridAction(); + $action->setId(ActionsInterface::ACCOUNT_DELETE); + $action->setType(DataGridActionType::DELETE_ITEM); + $action->setName(__('Eliminar Cuenta')); + $action->setTitle(__('Eliminar Cuenta')); + $action->addClass('btn-action'); + $action->setIcon($this->icons->getIconDelete()); + $action->setReflectionFilter(AccountSearchItem::class, 'isShowDelete'); + $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_DELETE)); + $action->addData('action-sk', $this->sk); + $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_DELETE)); + $action->addAttribute('type', 'button'); + + return $action; + } + + /** + * @return DataGridAction + */ + public function getPublicLinkRefreshAction() + { + $action = new DataGridAction(); + $action->setId(ActionsInterface::PUBLICLINK_REFRESH); + $action->setName(__('Actualizar Enlace Público')); + $action->setTitle(__('Actualizar Enlace Público')); + $action->setIcon($this->icons->getIconPublicLink()); + $action->addData('action-route', Acl::getActionRoute(ActionsInterface::PUBLICLINK_REFRESH)); + $action->addData('action-sk', $this->sk); + $action->addData('onclick', 'link/refresh'); + $action->addData('action-next', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); + $action->addAttribute('type', 'button'); + + return $action; + } + + /** + * @return DataGridAction + */ + public function getPublicLinkAction() + { + $action = new DataGridAction(); + $action->setId(ActionsInterface::PUBLICLINK_CREATE); + $action->setName(__('Crear Enlace Público')); + $action->setTitle(__('Crear Enlace Público')); + $action->addClass('btn-action'); + $action->setIcon($this->icons->getIconPublicLink()); + $action->addData('action-route', Acl::getActionRoute(ActionsInterface::PUBLICLINK_CREATE)); + $action->addData('action-sk', $this->sk); + $action->addData('onclick', 'link/save'); + $action->addData('action-next', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); + $action->addAttribute('type', 'button'); + + return $action; + } + /** * @return DataGridAction */ @@ -57,74 +256,13 @@ class AccountActionsHelper extends HelperBase $action->setReflectionFilter(AccountSearchItem::class, 'isShowViewPass'); $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW_PASS)); $action->addData('action-full', 1); - $action->addData('action-sk', $this->view->sk); + $action->addData('action-sk', $this->sk); $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW_PASS)); $action->addAttribute('type', 'button'); return $action; } - /** - * @return DataGridAction - */ - public function getEditPassAction() - { - $action = new DataGridAction(); - $action->setId(ActionsInterface::ACCOUNT_EDIT_PASS); - $action->setType(DataGridActionType::VIEW_ITEM); - $action->setName(__('Modificar Clave de Cuenta')); - $action->setTitle(__('Modificar Clave de Cuenta')); - $action->addClass('btn-action'); - $action->setIcon($this->icons->getIconEditPass()); - $action->setReflectionFilter(AccountSearchItem::class, 'isShowViewPass'); - $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_EDIT_PASS)); - $action->addData('action-sk', $this->view->sk); - $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_EDIT_PASS)); - $action->addAttribute('type', 'button'); - - return $action; - } - - /** - * @return DataGridAction - */ - public function getRestoreAction() - { - $action = new DataGridAction(); - $action->setId(ActionsInterface::ACCOUNT_EDIT_RESTORE); - $action->setType(DataGridActionType::VIEW_ITEM); - $action->setName(__('Restaurar cuenta desde este punto')); - $action->setTitle(__('Restaurar cuenta desde este punto')); - $action->addClass('btn-action'); - $action->setIcon($this->icons->getIconRestore()); - $action->addData('action-route', 'account/saveEditRestore'); - $action->addData('action-sk', $this->view->sk); - $action->addData('onclick', 'account/saveEditRestore'); - $action->addAttribute('type', 'button'); - - return $action; - } - - /** - * @return DataGridAction - */ - public function getSaveAction() - { - $action = new DataGridAction(); - $action->setId(ActionsInterface::ACCOUNT); - $action->setType(DataGridActionType::VIEW_ITEM); - $action->setName(__('Guardar')); - $action->setTitle(__('Guardar')); - $action->addClass('btn-action'); - $action->setIcon($this->icons->getIconSave()); - $action->addData('action-route', 'account/save'); - $action->addData('action-sk', $this->view->sk); - $action->addData('onclick', 'account/save'); - $action->addAttribute('type', 'submit'); - - return $action; - } - /** * @return DataGridAction */ @@ -143,73 +281,13 @@ class AccountActionsHelper extends HelperBase $action->setReflectionFilter(AccountSearchItem::class, 'isShowCopyPass'); $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_COPY_PASS)); $action->addData('action-full', 0); - $action->addData('action-sk', $this->view->sk); + $action->addData('action-sk', $this->sk); $action->addData('useclipboard', '1'); $action->addAttribute('type', 'button'); return $action; } - /** - * @return DataGridAction - */ - public function getEditAction() - { - $action = new DataGridAction(); - $action->setId(ActionsInterface::ACCOUNT_EDIT); - $action->setType(DataGridActionType::EDIT_ITEM); - $action->setName(__('Editar Cuenta')); - $action->setTitle(__('Editar Cuenta')); - $action->addClass('btn-action'); - $action->setIcon($this->icons->getIconEdit()); - $action->setReflectionFilter(AccountSearchItem::class, 'isShowEdit'); - $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_EDIT)); - $action->addData('action-sk', $this->view->sk); - $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_EDIT)); - $action->addAttribute('type', 'button'); - - return $action; - } - - /** - * @return DataGridAction - */ - public function getPublicLinkAction() - { - $action = new DataGridAction(); - $action->setId(ActionsInterface::PUBLICLINK_CREATE); - $action->setName(__('Crear Enlace Público')); - $action->setTitle(__('Crear Enlace Público')); - $action->addClass('btn-action'); - $action->setIcon($this->icons->getIconPublicLink()); - $action->addData('action-route', Acl::getActionRoute(ActionsInterface::PUBLICLINK_CREATE)); - $action->addData('action-sk', $this->view->sk); - $action->addData('onclick', 'link/save'); - $action->addData('action-next', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); - $action->addAttribute('type', 'button'); - - return $action; - } - - /** - * @return DataGridAction - */ - public function getPublicLinkRefreshAction() - { - $action = new DataGridAction(); - $action->setId(ActionsInterface::PUBLICLINK_REFRESH); - $action->setName(__('Actualizar Enlace Público')); - $action->setTitle(__('Actualizar Enlace Público')); - $action->setIcon($this->icons->getIconPublicLink()); - $action->addData('action-route', Acl::getActionRoute(ActionsInterface::PUBLICLINK_REFRESH)); - $action->addData('action-sk', $this->view->sk); - $action->addData('onclick', 'link/refresh'); - $action->addData('action-next', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); - $action->addAttribute('type', 'button'); - - return $action; - } - /** * @return DataGridAction */ @@ -224,7 +302,7 @@ class AccountActionsHelper extends HelperBase $action->setIcon($this->icons->getIconCopy()); $action->setReflectionFilter(AccountSearchItem::class, 'isShowCopy'); $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_COPY)); - $action->addData('action-sk', $this->view->sk); + $action->addData('action-sk', $this->sk); $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_COPY)); $action->addAttribute('type', 'button'); @@ -234,19 +312,40 @@ class AccountActionsHelper extends HelperBase /** * @return DataGridAction */ - public function getDeleteAction() + public function getEditPassAction() { $action = new DataGridAction(); - $action->setId(ActionsInterface::ACCOUNT_DELETE); - $action->setType(DataGridActionType::DELETE_ITEM); - $action->setName(__('Eliminar Cuenta')); - $action->setTitle(__('Eliminar Cuenta')); + $action->setId(ActionsInterface::ACCOUNT_EDIT_PASS); + $action->setType(DataGridActionType::VIEW_ITEM); + $action->setName(__('Modificar Clave de Cuenta')); + $action->setTitle(__('Modificar Clave de Cuenta')); $action->addClass('btn-action'); - $action->setIcon($this->icons->getIconDelete()); - $action->setReflectionFilter(AccountSearchItem::class, 'isShowDelete'); - $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_DELETE)); - $action->addData('action-sk', $this->view->sk); - $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_DELETE)); + $action->setIcon($this->icons->getIconEditPass()); + $action->setReflectionFilter(AccountSearchItem::class, 'isShowViewPass'); + $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_EDIT_PASS)); + $action->addData('action-sk', $this->sk); + $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_EDIT_PASS)); + $action->addAttribute('type', 'button'); + + return $action; + } + + /** + * @return DataGridAction + */ + public function getEditAction() + { + $action = new DataGridAction(); + $action->setId(ActionsInterface::ACCOUNT_EDIT); + $action->setType(DataGridActionType::EDIT_ITEM); + $action->setName(__('Editar Cuenta')); + $action->setTitle(__('Editar Cuenta')); + $action->addClass('btn-action'); + $action->setIcon($this->icons->getIconEdit()); + $action->setReflectionFilter(AccountSearchItem::class, 'isShowEdit'); + $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_EDIT)); + $action->addData('action-sk', $this->sk); + $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_EDIT)); $action->addAttribute('type', 'button'); return $action; @@ -265,7 +364,7 @@ class AccountActionsHelper extends HelperBase $action->setIcon($this->icons->getIconEmail()); $action->setReflectionFilter(AccountSearchItem::class, 'isShowRequest'); $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_REQUEST)); - $action->addData('action-sk', $this->view->sk); + $action->addData('action-sk', $this->sk); $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); $action->addAttribute('type', 'submit'); @@ -275,27 +374,49 @@ class AccountActionsHelper extends HelperBase /** * @return DataGridAction */ - public function getBackAction() + public function getRestoreAction() { $action = new DataGridAction(); - $action->setId('btnBack'); - $action->setName(__('Atrás')); - $action->setTitle(__('Atrás')); + $action->setId(ActionsInterface::ACCOUNT_EDIT_RESTORE); + $action->setType(DataGridActionType::VIEW_ITEM); + $action->setName(__('Restaurar cuenta desde este punto')); + $action->setTitle(__('Restaurar cuenta desde este punto')); $action->addClass('btn-action'); - $action->setIcon($this->icons->getIconBack()); - $action->addData('action-route', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); - $action->addData('action-sk', $this->view->sk); - $action->addData('onclick', Acl::getActionRoute(ActionsInterface::ACCOUNT_VIEW)); + $action->setIcon($this->icons->getIconRestore()); + $action->addData('action-route', 'account/saveEditRestore'); + $action->addData('action-sk', $this->sk); + $action->addData('onclick', 'account/saveEditRestore'); $action->addAttribute('type', 'button'); return $action; } + /** + * @return DataGridAction + */ + public function getSaveAction() + { + $action = new DataGridAction(); + $action->setId(ActionsInterface::ACCOUNT); + $action->setType(DataGridActionType::VIEW_ITEM); + $action->setName(__('Guardar')); + $action->setTitle(__('Guardar')); + $action->addClass('btn-action'); + $action->setIcon($this->icons->getIconSave()); + $action->addData('action-route', 'account/save'); + $action->addData('action-sk', $this->sk); + $action->addData('onclick', 'account/save'); + $action->addAttribute('type', 'submit'); + + return $action; + } + /** * Initialize class */ protected function initialize() { + $this->sk = $this->session->generateSecurityKey(); $this->icons = $this->view->getTheme()->getIcons(); } } \ No newline at end of file diff --git a/app/modules/web/Controllers/Helpers/Account/AccountHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountHelper.php new file mode 100644 index 00000000..74bb8e92 --- /dev/null +++ b/app/modules/web/Controllers/Helpers/Account/AccountHelper.php @@ -0,0 +1,337 @@ +. + */ + +namespace SP\Modules\Web\Controllers\Helpers\Account; + +use SP\Account\AccountAcl; +use SP\Core\Acl\Acl; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Acl\UnauthorizedPageException; +use SP\Core\Exceptions\SPException; +use SP\DataModel\Dto\AccountAclDto; +use SP\DataModel\Dto\AccountDetailsResponse; +use SP\Mgmt\Users\UserPass; +use SP\Modules\Web\Controllers\Helpers\HelperBase; +use SP\Modules\Web\Controllers\Traits\ItemTrait; +use SP\Mvc\View\Components\SelectItemAdapter; +use SP\Services\Account\AccountHistoryService; +use SP\Services\Account\AccountService; +use SP\Services\Category\CategoryService; +use SP\Services\Client\ClientService; +use SP\Services\PublicLink\PublicLinkService; +use SP\Services\Tag\TagService; +use SP\Services\User\UpdatedMasterPassException; +use SP\Services\User\UserService; +use SP\Services\UserGroup\UserGroupService; +use SP\Util\ErrorUtil; + +/** + * Class AccountHelper + * + * @package SP\Modules\Web\Controllers\Helpers + */ +class AccountHelper extends HelperBase +{ + use ItemTrait; + + /** + * @var Acl + */ + protected $acl; + /** + * @var AccountService + */ + protected $accountService; + /** + * @var AccountHistoryService + */ + protected $accountHistoryService; + /** + * @var PublicLinkService + */ + protected $publicLinkService; + /** + * @var string + */ + private $actionId; + /** + * @var AccountAcl + */ + private $accountAcl; + /** + * @var int con el Id de la cuenta + */ + private $accountId; + /** + * @var bool + */ + private $isView = false; + + /** + * @param Acl $acl + * @param AccountService $accountService + * @param AccountHistoryService $accountHistoryService + * @param PublicLinkService $publicLinkService + */ + public function inject(Acl $acl, + AccountService $accountService, + AccountHistoryService $accountHistoryService, + PublicLinkService $publicLinkService + ) + { + $this->acl = $acl; + $this->accountService = $accountService; + $this->accountHistoryService = $accountHistoryService; + $this->publicLinkService = $publicLinkService; + } + + /** + * Sets account's view variables + * + * @param AccountDetailsResponse $accountDetailsResponse + * @param int $actionId + * @throws SPException + * @throws UnauthorizedPageException + * @throws UpdatedMasterPassException + * @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(); + $this->checkAccess($accountDetailsResponse); + + $accountData = $accountDetailsResponse->getAccountVData(); + $selectUsers = SelectItemAdapter::factory(UserService::getItemsBasic()); + $selectUserGroups = SelectItemAdapter::factory(UserGroupService::getItemsBasic()); + $selectTags = SelectItemAdapter::factory(TagService::getItemsBasic()); + + $this->view->assign('otherUsers', $selectUsers->getItemsFromModelSelected(SelectItemAdapter::getIdFromArrayOfObjects($accountDetailsResponse->getUsers()), $accountData->getUserId())); + $this->view->assign('otherUserGroups', $selectUserGroups->getItemsFromModelSelected(SelectItemAdapter::getIdFromArrayOfObjects($accountDetailsResponse->getUserGroups()), $accountData->getUserGroupId())); + $this->view->assign('userGroups', $selectUserGroups->getItemsFromModelSelected([$accountData->getUserGroupId()])); + $this->view->assign('tags', $selectTags->getItemsFromModelSelected(SelectItemAdapter::getIdFromArrayOfObjects($accountDetailsResponse->getTags()))); + + $this->view->assign('historyData', $this->accountHistoryService->getHistoryForAccount($this->accountId)); + + $this->view->assign('isModified', strtotime($accountData->getDateEdit()) !== false); + $this->view->assign('maxFileSize', round($this->configData->getFilesAllowedSize() / 1024, 1)); + $this->view->assign('filesAllowedExts', implode(',', $this->configData->getFilesAllowedExts())); + + if ($this->configData->isPublinksEnabled() && $this->accountAcl->isShowLink()) { + $publicLinkData = $this->publicLinkService->getHashForItem($this->accountId); + + $publicLinkUrl = $publicLinkData ? PublicLinkService::getLinkForHash($publicLinkData->getHash()) : null; + $this->view->assign('publicLinkUrl', $publicLinkUrl); + $this->view->assign('publicLinkId', $publicLinkData ? $publicLinkData->getId() : 0); + $this->view->assign('publicLinkShow', true); + } else { + $this->view->assign('publicLinkShow', false); + } + + $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)); + + $this->view->assign('accountId', $accountData->getId()); + $this->view->assign('accountData', $accountData); + $this->view->assign('gotData', true); + + $this->view->assign('actions', $this->getActionsHelper()->getActionsForAccount($this->accountAcl->getStoredAcl(), new AccountActionsDto($this->accountId, null, $accountData->getParentId()))); + + $this->setViewCommon(); + } + + /** + * @throws UnauthorizedPageException + * @throws UpdatedMasterPassException + */ + public function checkActionAccess() + { + if (!$this->acl->checkUserAccess($this->actionId)) { + throw new UnauthorizedPageException(SPException::SP_INFO); + } + + if (!UserPass::checkUserUpdateMPass($this->session->getUserData()->getId())) { + throw new UpdatedMasterPassException(SPException::SP_INFO); + } + } + + /** + * Comprobar si el usuario dispone de acceso al módulo + * + * @param AccountDetailsResponse $accountDetailsResponse + * @return bool + */ + protected function checkAccess(AccountDetailsResponse $accountDetailsResponse) + { + $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()); + + if (!$this->accountAcl->getAcl($acccountAclDto)->checkAccountAccess()) { + ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_ACCOUNT_NO_PERMISSION); + + return false; + } + + return true; + } + + /** + * @return AccountActionsHelper + * @throws \SP\Core\Dic\ContainerException + */ + protected function getActionsHelper() + { + return new AccountActionsHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + } + + /** + * Sets account's view common data + */ + 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('allowPrivate', $userProfileData->isAccPrivate()); + $this->view->assign('allowPrivateGroup', $userProfileData->isAccPrivateGroup()); + $this->view->assign('mailRequestEnabled', $this->configData->isMailRequestsEnabled()); + $this->view->assign('passToImageEnabled', $this->configData->isAccountPassToImage()); + + $this->view->assign('otherAccounts', $this->accountService->getForUser($this->accountId)); + + $this->view->assign('addClientEnabled', !$this->isView && $this->acl->checkUserAccess(ActionsInterface::CLIENT)); + $this->view->assign('addClientRoute', Acl::getActionRoute(ActionsInterface::CLIENT_CREATE)); + + $this->view->assign('addCategoryEnabled', !$this->isView && $this->acl->checkUserAccess(ActionsInterface::CATEGORY)); + $this->view->assign('addCategoryRoute', Acl::getActionRoute(ActionsInterface::CATEGORY_CREATE)); + + $this->view->assign('fileUploadRoute', Acl::getActionRoute(ActionsInterface::ACCOUNT_FILE_UPLOAD)); + + $this->view->assign('disabled', $this->isView ? 'disabled' : ''); + $this->view->assign('readonly', $this->isView ? 'readonly' : ''); + + $this->view->assign('showViewCustomPass', $this->accountAcl->isShowViewPass()); + $this->view->assign('accountAcl', $this->accountAcl->getStoredAcl() ?: $this->accountAcl); + } + + /** + * Sets account's view for a blank form + * + * @param $actionId + * @return void + * @throws UnauthorizedPageException + * @throws UpdatedMasterPassException + * @throws \SP\Core\Dic\ContainerException + */ + public function setViewForBlank($actionId) + { + $this->actionId = $actionId; + $this->accountAcl = new AccountAcl($actionId); + + $this->checkActionAccess(); + + $selectUsers = SelectItemAdapter::factory(UserService::getItemsBasic()); + $selectUserGroups = SelectItemAdapter::factory(UserGroupService::getItemsBasic()); + $selectTags = SelectItemAdapter::factory(TagService::getItemsBasic()); + + $this->view->assign('accountPassDateChange', date('Y-m-d', time() + 7776000)); + $this->view->assign('otherUsers', $selectUsers->getItemsFromModel()); + $this->view->assign('otherUserGroups', $selectUserGroups->getItemsFromModel()); + $this->view->assign('userGroups', $selectUserGroups->getItemsFromModel()); + $this->view->assign('tags', $selectTags->getItemsFromModel()); + + $this->view->assign('accountId', 0); + $this->view->assign('gotData', false); + + $this->view->assign('actions', $this->getActionsHelper()->getActionsForAccount($this->accountAcl, new AccountActionsDto($this->accountId))); + + $this->setViewCommon(); + } + + /** + * Sets account's view variables + * + * @param AccountDetailsResponse $accountDetailsResponse + * @param int $actionId + * @return bool + * @throws UnauthorizedPageException + * @throws UpdatedMasterPassException + * @throws \SP\Core\Dic\ContainerException + */ + public function setViewForRequest(AccountDetailsResponse $accountDetailsResponse, $actionId) + { + $this->accountId = $accountDetailsResponse->getAccountVData()->getId(); + $this->actionId = $actionId; + $this->accountAcl = new AccountAcl($actionId); + + $this->checkActionAccess(); + + $accountData = $accountDetailsResponse->getAccountVData(); + + $this->view->assign('accountId', $accountData->getId()); + $this->view->assign('accountData', $accountDetailsResponse->getAccountVData()); + + $this->view->assign('actions', $this->getActionsHelper()->getActionsForAccount($this->accountAcl->getStoredAcl(), new AccountActionsDto($this->accountId, null, $accountData->getParentId()))); + + return true; + } + + /** + * @param bool $isView + */ + public function setIsView($isView) + { + $this->isView = (bool)$isView; + } + + /** + * Initialize class + */ + protected function initialize() + { + $this->view->assign('changesHash'); + $this->view->assign('chkUserEdit'); + $this->view->assign('chkGroupEdit'); + $this->view->assign('sk', $this->session->generateSecurityKey()); + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/Helpers/Account/AccountHistoryHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountHistoryHelper.php new file mode 100644 index 00000000..eaddd582 --- /dev/null +++ b/app/modules/web/Controllers/Helpers/Account/AccountHistoryHelper.php @@ -0,0 +1,173 @@ +. + */ + +namespace SP\Modules\Web\Controllers\Helpers\Account; + +use SP\Account\AccountAcl; +use SP\Core\Acl\Acl; +use SP\DataModel\AccountHistoryData; +use SP\DataModel\Dto\AccountAclDto; +use SP\Mgmt\Users\UserPass; +use SP\Modules\Web\Controllers\Helpers\HelperBase; +use SP\Mvc\View\Components\SelectItemAdapter; +use SP\Services\Account\AccountHistoryService; +use SP\Services\Category\CategoryService; +use SP\Services\Client\ClientService; +use SP\Util\ErrorUtil; + +/** + * Class AccountHistoryHelper + * + * @package SP\Modules\Web\Controllers\Helpers + */ +class AccountHistoryHelper extends HelperBase +{ + /** + * @var Acl + */ + protected $acl; + /** + * @var AccountHistoryService + */ + protected $accountHistoryService; + /** + * @var int + */ + protected $accountId; + /** + * @var int + */ + protected $actionId; + /** + * @var int + */ + protected $accountHistoryId; + /** + * @var AccountAcl + */ + protected $accountAcl; + + + /** + * @param Acl $acl + * @param AccountHistoryService $accountHistoryService + */ + public function inject(Acl $acl, AccountHistoryService $accountHistoryService) + { + $this->acl = $acl; + $this->accountHistoryService = $accountHistoryService; + } + + /** + * @param AccountHistoryData $accountHistoryData + * @param int $actionId + * @return bool + * @throws \SP\Core\Dic\ContainerException + */ + 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)) { + // FIXME: throw exception + return false; + } + + $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('actionId', $this->actionId); + $this->view->assign('accountId', $this->accountId); + $this->view->assign('accountHistoryId', $this->accountHistoryId); + $this->view->assign('historyData', $this->accountHistoryService->getHistoryForAccount($this->accountId)); + $this->view->assign('accountPassDate', date('Y-m-d H:i:s', $accountHistoryData->getPassDate())); + $this->view->assign('accountPassDateChange', date('Y-m-d', $accountHistoryData->getPassDateChange() ?: 0)); + $this->view->assign('categories', SelectItemAdapter::factory(CategoryService::getItemsBasic())->getItemsFromModelSelected([$accountHistoryData->getCategoryId()])); + $this->view->assign('clients', SelectItemAdapter::factory(ClientService::getItemsBasic())->getItemsFromModelSelected([$accountHistoryData->getClientId()])); + $this->view->assign('isModified', strtotime($accountHistoryData->getDateEdit()) !== false); + + $actions = new AccountActionsHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + + $this->view->assign('actions', $actions->getActionsForAccount($this->accountAcl->getStoredAcl(), new AccountActionsDto($this->accountId, $this->accountHistoryId))); + + return true; + } + + /** + * @return bool + */ + protected function checkActionAccess() + { + if (!$this->acl->checkUserAccess($this->actionId)) { + ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_PAGE_NO_PERMISSION); + + return false; + } + + if (!UserPass::checkUserUpdateMPass($this->session->getUserData()->getId())) { + ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_UPDATE_MPASS); + + return false; + } + + return true; + } + + /** + * Comprobar si el usuario dispone de acceso al módulo + * + * @param AccountHistoryData $accountHistoryData + * @return bool + */ + protected function checkAccess(AccountHistoryData $accountHistoryData) + { + $acccountAclDto = new AccountAclDto(); + $acccountAclDto->setAccountId($accountHistoryData->getAccountId()); + $acccountAclDto->setDateEdit(strtotime($accountHistoryData->getDateEdit())); + $acccountAclDto->setUserId($accountHistoryData->getUserId()); + $acccountAclDto->setUserGroupId($accountHistoryData->getUserGroupId()); + $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); + + return false; + } + + return true; + } + + /** + * Initialize class + */ + protected function initialize() + { + $this->view->assign('sk', $this->session->generateSecurityKey()); + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/Helpers/AccountPasswordHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountPasswordHelper.php similarity index 76% rename from app/modules/web/Controllers/Helpers/AccountPasswordHelper.php rename to app/modules/web/Controllers/Helpers/Account/AccountPasswordHelper.php index 3a4e9402..72385143 100644 --- a/app/modules/web/Controllers/Helpers/AccountPasswordHelper.php +++ b/app/modules/web/Controllers/Helpers/Account/AccountPasswordHelper.php @@ -1,6 +1,28 @@ . + */ -namespace SP\Modules\Web\Controllers\Helpers; +namespace SP\Modules\Web\Controllers\Helpers\Account; use SP\Core\Acl\Acl; use SP\Core\Acl\ActionsInterface; @@ -9,6 +31,8 @@ use SP\Core\Crypt\Session as CryptSession; use SP\Core\SessionUtil; use SP\DataModel\AccountPassData; use SP\Mgmt\Users\UserPass; +use SP\Modules\Web\Controllers\Helpers\HelperBase; +use SP\Modules\Web\Controllers\Helpers\HelperException; use SP\Util\ImageUtil; /** diff --git a/app/modules/web/Controllers/Helpers/AccountSearchHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php similarity index 97% rename from app/modules/web/Controllers/Helpers/AccountSearchHelper.php rename to app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php index 108239fe..20b57a89 100644 --- a/app/modules/web/Controllers/Helpers/AccountSearchHelper.php +++ b/app/modules/web/Controllers/Helpers/Account/AccountSearchHelper.php @@ -2,9 +2,9 @@ /** * sysPass * - * @author nuxsmin - * @link http://syspass.org - * @copyright 2012-2017, Rubén Domínguez nuxsmin@$syspass.org + * @author nuxsmin + * @link http://syspass.org + * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -22,7 +22,7 @@ * along with sysPass. If not, see . */ -namespace SP\Modules\Web\Controllers\Helpers; +namespace SP\Modules\Web\Controllers\Helpers\Account; use SP\Account\AccountSearchFilter; use SP\Account\AccountSearchItem; @@ -36,6 +36,8 @@ use SP\Html\DataGrid\DataGridHeaderSort; use SP\Html\DataGrid\DataGridPager; use SP\Html\DataGrid\DataGridSort; use SP\Http\Request; +use SP\Modules\Web\Controllers\Helpers\Account\AccountActionsHelper; +use SP\Modules\Web\Controllers\Helpers\HelperBase; use SP\Mvc\View\Components\SelectItemAdapter; use SP\Repositories\Category\CategoryRepository; use SP\Repositories\Client\ClientRepository; diff --git a/app/modules/web/Controllers/Helpers/AccountHelper.php b/app/modules/web/Controllers/Helpers/AccountHelper.php deleted file mode 100644 index 4ffb6f71..00000000 --- a/app/modules/web/Controllers/Helpers/AccountHelper.php +++ /dev/null @@ -1,505 +0,0 @@ -. - */ - -namespace SP\Modules\Web\Controllers\Helpers; - -use SP\Account\AccountAcl; -use SP\Core\Acl\Acl; -use SP\Core\Acl\ActionsInterface; -use SP\Core\SessionUtil; -use SP\DataModel\AccountHistoryData; -use SP\DataModel\Dto\AccountAclDto; -use SP\DataModel\Dto\AccountDetailsResponse; -use SP\Html\DataGrid\DataGridAction; -use SP\Mgmt\Users\UserPass; -use SP\Modules\Web\Controllers\Traits\ItemTrait; -use SP\Mvc\View\Components\SelectItemAdapter; -use SP\Services\Account\AccountHistoryService; -use SP\Services\Account\AccountService; -use SP\Services\Category\CategoryService; -use SP\Services\Client\ClientService; -use SP\Services\PublicLink\PublicLinkService; -use SP\Services\Tag\TagService; -use SP\Services\User\UserService; -use SP\Services\UserGroup\UserGroupService; -use SP\Util\ErrorUtil; -use SP\Util\Json; - -/** - * Class AccountHelper - * - * @package SP\Modules\Web\Controllers\Helpers - */ -class AccountHelper extends HelperBase -{ - use ItemTrait; - - /** - * @var Acl - */ - protected $acl; - /** - * @var AccountService - */ - protected $accountService; - /** - * @var AccountHistoryService - */ - protected $accountHistoryService; - /** - * @var string - */ - private $actionId; - /** - * @var AccountAcl - */ - private $accountAcl; - /** - * @var int con el Id de la cuenta - */ - private $accountId; - /** - * @var int el Id de la cuenta en el histórico - */ - private $accountHistoryId; - /** - * @var AccountDetailsResponse - */ - private $accountDetailsResponse; - /** - * @var bool - */ - private $isHistory; - - /** - * @param Acl $acl - */ - public function inject(Acl $acl) - { - $this->acl = $acl; - } - - /** - * Establecer las variables que contienen la información de la cuenta en una fecha concreta. - * - * @param AccountHistoryService $accountHistoryService - * @param AccountHistoryData $accountHistoryData - * @param int $actionId - * @return bool - * @throws \SP\Core\Dic\ContainerException - */ - public function setAccountHistory(AccountHistoryService $accountHistoryService, AccountHistoryData $accountHistoryData, $actionId) - { - - $this->actionId = $actionId; - $this->isHistory = true; - $this->accountHistoryId = $accountHistoryData->getId(); - $this->accountId = $accountHistoryData->getAccountId(); - $this->accountHistoryService = $accountHistoryService; - - if (!$this->checkAccessHistory($accountHistoryData)) { - return false; - } - - $this->view->assign('accountData', $accountHistoryData); - $this->view->assign('accountAcl', $this->accountAcl); - $this->view->assign('actionId', $this->actionId); - $this->view->assign('accountId', $this->accountId); - $this->view->assign('accountHistoryId', $this->accountHistoryId); - $this->view->assign('historyData', $this->accountHistoryService->getHistoryForAccount($this->accountId)); - $this->view->assign('accountIsHistory', true); - $this->view->assign('accountPassDate', date('Y-m-d H:i:s', $accountHistoryData->getPassDate())); - $this->view->assign('accountPassDateChange', date('Y-m-d', $accountHistoryData->getPassDateChange() ?: 0)); - $this->view->assign('categories', (new SelectItemAdapter(CategoryService::getItemsBasic()))->getItemsFromModelSelected([$accountHistoryData->getCategoryId()])); - $this->view->assign('clients', (new SelectItemAdapter(ClientService::getItemsBasic()))->getItemsFromModelSelected([$accountHistoryData->getClientId()])); - $this->view->assign('isModified', strtotime($accountHistoryData->getDateEdit()) !== false); - $this->view->assign('actions', $this->getActions($accountHistoryData->getParentId())); - - return true; - } - - /** - * Comprobar si el usuario dispone de acceso al módulo - * - * @param AccountHistoryData $accountHistoryData - * @return bool - * @throws \SP\Core\Dic\ContainerException - */ - public function checkAccessHistory(AccountHistoryData $accountHistoryData) - { - $this->view->assign('showLogo', false); - - if (!$this->acl->checkUserAccess($this->actionId)) { - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_PAGE_NO_PERMISSION); - - return false; - } - - if (!UserPass::checkUserUpdateMPass($this->session->getUserData()->getId())) { - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_UPDATE_MPASS); - - return false; - } - - if ($this->accountId > 0) { - $acccountAclDto = new AccountAclDto(); - $acccountAclDto->setAccountId($accountHistoryData->getAccountId()); - $acccountAclDto->setDateEdit(strtotime($accountHistoryData->getDateEdit())); - $acccountAclDto->setUserId($accountHistoryData->getUserId()); - $acccountAclDto->setUserGroupId($accountHistoryData->getUserGroupId()); - $acccountAclDto->setUsersId($this->accountHistoryService->getUsersByAccountId($this->accountId)); - $acccountAclDto->setUserGroupsId($this->accountHistoryService->getUserGroupsByAccountId($this->accountId)); - - $this->accountAcl = (new AccountAcl($this->actionId, true))->getAcl($acccountAclDto); - - if (!$this->accountAcl->checkAccountAccess()) { - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_ACCOUNT_NO_PERMISSION); - - return false; - } - } - - return true; - } - - /** - * Set icons for view - * - * @param int $parentId - * @return DataGridAction[] - * @throws \SP\Core\Dic\ContainerException - */ - protected function getActions($parentId = 0) - { - $actionsEnabled = []; - - $actions = new AccountActionsHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - - $actionBack = $actions->getBackAction(); - - if ($this->isHistory) { - $actionBack->addData('item-id', $this->accountId); - $actionBack->setName(__('Ver Actual')); - $actionBack->setTitle(__('Ver Actual')); - } else { - $actionBack->setData([]); - $actionBack->setClasses(['btn-back']); - } - - $actionsEnabled[] = $actionBack; - - if ($this->accountAcl->isShowDelete()) { - $actionsEnabled[] = $actions->getDeleteAction()->addData('item-id', $this->accountId); - } - - if ($this->isHistory === false - && $parentId === 0 - && $this->accountAcl->isShowLink() - && $this->accountAcl->isShowViewPass() - ) { - if (null === $this->view->publicLinkUrl) { - $actionsEnabled[] = $actions->getPublicLinkAction(); - } else { - $actionsEnabled[] = $actions->getPublicLinkRefreshAction(); - } - } - - if ($this->accountAcl->isShowViewPass()) { - $actionViewPass = $actions->getViewPassAction(); - $actionCopy = $actions->getCopyPassAction(); - - $actionViewPass->addData('parent-id', $parentId); - $actionCopy->addData('parent-id', $parentId); - - $actionViewPass->addData('history', (int)$this->isHistory); - $actionCopy->addData('history', (int)$this->isHistory); - - if ($this->isHistory) { - $actionViewPass->addData('item-id', $this->accountHistoryId); - $actionCopy->addData('item-id', $this->accountHistoryId); - } else { - $actionViewPass->addData('item-id', $this->accountId); - $actionCopy->addData('item-id', $this->accountId); - } - - $actionsEnabled[] = $actionViewPass; - $actionsEnabled[] = $actionCopy; - } - - if ($this->accountAcl->isShowCopy()) { - $actionsEnabled[] = $actions->getCopyAction()->addData('item-id', $this->accountId); - } - - if ($this->accountAcl->isShowEditPass()) { - $actionsEnabled[] = $actions->getEditPassAction()->addData('item-id', $this->accountId); - } - - if ($this->accountAcl->isShowEdit()) { - $actionsEnabled[] = $actions->getEditAction()->addData('item-id', $this->accountId); - } - - if ($this->actionId === ActionsInterface::ACCOUNT_VIEW - && !$this->accountAcl->isShowEdit() - && $this->configData->isMailRequestsEnabled() - ) { - $actionsEnabled[] = $actions->getRequestAction()->addData('item-id', $this->accountId); - } - - if ($this->accountAcl->isShowRestore()) { - $actionRestore = $actions->getRestoreAction(); - $actionRestore->addData('item-id', $this->accountId); - $actionRestore->addData('history-id', $this->accountHistoryId); - - $actionsEnabled[] = $actionRestore; - } - - if ($this->accountAcl->isShowSave()) { - $actionsEnabled[] = $actions->getSaveAction()->addAttribute('form', 'frmAccount'); - } - - return $actionsEnabled; - } - - /** - * @return AccountAcl - */ - public function getAccountAcl() - { - return $this->accountAcl; - } - - /** - * @return int - */ - public function getAccountId() - { - return $this->accountId; - } - - /** - * Establecer variables comunes del formulario para todos los interfaces - * - * @throws \SP\Core\Exceptions\SPException - * @throws \SP\Core\Dic\ContainerException - */ - public function setCommonData() - { - $userProfileData = $this->session->getUserProfile(); - - if ($this->isGotData()) { - $accountData = $this->accountDetailsResponse->getAccountVData(); - - $this->view->assign('accountIsHistory', $this->isHistory); - $this->view->assign('accountOtherUsers', $this->accountDetailsResponse->getUsers()); - $this->view->assign('accountOtherGroups', $this->accountDetailsResponse->getUserGroups()); - $this->view->assign('accountTags', $this->accountDetailsResponse->getTags()); - $this->view->assign('accountTagsJson', Json::getJson(array_keys($this->accountDetailsResponse->getTags()))); - - $accountHistoryService = new AccountHistoryService(); - $this->view->assign('historyData', $accountHistoryService->getHistoryForAccount($this->accountId)); - - $this->view->assign('isModified', strtotime($accountData->getDateEdit()) !== false); - $this->view->assign('maxFileSize', round($this->configData->getFilesAllowedSize() / 1024, 1)); - $this->view->assign('filesAllowedExts', implode(',', $this->configData->getFilesAllowedExts())); - - if ($this->configData->isPublinksEnabled() && $this->accountAcl->isShowLink()) { - $publicLinkService = new PublicLinkService(); - $publicLinkData = $publicLinkService->getHashForItem($this->accountId); - - $publicLinkUrl = $publicLinkData ? PublicLinkService::getLinkForHash($publicLinkData->getHash()) : null; - $this->view->assign('publicLinkUrl', $publicLinkUrl); - $this->view->assign('publicLinkId', $publicLinkData ? $publicLinkData->getId() : 0); - $this->view->assign('publicLinkShow', true); - } else { - $this->view->assign('publicLinkShow', false); - } - - $this->view->assign('accountPassDate', date('Y-m-d H:i:s', $accountData->getPassDate())); - $this->view->assign('accountPassDateChange', date('Y-m-d', $accountData->getPassDateChange() ?: 0)); - } else { - $this->view->assign('accountPassDateChange', date('Y-m-d', time() + 7776000)); - } - - $this->view->assign('customFields', $this->getCustomFieldsForItem(ActionsInterface::ACCOUNT, $this->accountId)); - $this->view->assign('categories', (new SelectItemAdapter(CategoryService::getItemsBasic()))->getItemsFromModel()); - $this->view->assign('clients', (new SelectItemAdapter(ClientService::getItemsBasic()))->getItemsFromModel()); - - $userItemAdapter = new SelectItemAdapter(UserService::getItemsBasic()); - - $this->view->assign('otherUsers', $userItemAdapter->getItemsFromModel()); - $this->view->assign('otherUsersJson', $userItemAdapter->getJsonItemsFromModel()); - - $userGroupItemAdapter = new SelectItemAdapter(UserGroupService::getItemsBasic()); - - $this->view->assign('otherGroups', $userGroupItemAdapter->getItemsFromModel()); - $this->view->assign('otherGroupsJson', $userGroupItemAdapter->getJsonItemsFromModel()); - - $tagItemAdapter = new SelectItemAdapter(TagService::getItemsBasic()); - - $this->view->assign('tagsJson', $tagItemAdapter->getJsonItemsFromModel()); - $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()); - - $this->view->assign('otherAccounts', $this->accountService->getForUser($this->accountId)); - $this->view->assign('linkedAccounts', $this->accountService->getLinked($this->accountId)); - - $this->view->assign('addClientEnabled', !$this->view->isView && $this->acl->checkUserAccess(ActionsInterface::CLIENT)); - $this->view->assign('addClientRoute', Acl::getActionRoute(ActionsInterface::CLIENT_CREATE)); - - $this->view->assign('addCategoryEnabled', !$this->view->isView && $this->acl->checkUserAccess(ActionsInterface::CATEGORY)); - $this->view->assign('addCategoryRoute', Acl::getActionRoute(ActionsInterface::CATEGORY_CREATE)); - - $this->view->assign('disabled', $this->view->isView ? 'disabled' : ''); - $this->view->assign('readonly', $this->view->isView ? 'readonly' : ''); - - $this->view->assign('showViewCustomPass', $this->accountAcl->isShowViewPass()); - $this->view->assign('accountAcl', $this->accountAcl); - - $this->view->assign('actions', $this->getActions($this->isGotData() ? $this->accountDetailsResponse->getAccountVData()->getParentId() : 0)); - } - - /** - * @return boolean - */ - private function isGotData() - { - return $this->accountDetailsResponse !== null; - } - - /** - * @param string $actionId - */ - public function setActionId($actionId) - { - $this->actionId = $actionId; - } - - /** - * @return AccountDetailsResponse - */ - public function getAccountDetailsResponse() - { - return $this->accountDetailsResponse; - } - - /** - * Establecer las variables que contienen la información de la cuenta. - * - * @param AccountDetailsResponse $accountDetailsResponse - * @param AccountService $accountService - * @param int $actionId - * @return bool - * @throws \SP\Core\Dic\ContainerException - */ - public function setAccount(AccountDetailsResponse $accountDetailsResponse, AccountService $accountService, $actionId) - { - $this->accountDetailsResponse = $accountDetailsResponse; - $this->accountService = $accountService; - - $this->accountId = $accountDetailsResponse->getAccountVData()->getId(); - $this->actionId = $actionId; - $this->isHistory = false; - - if (!$this->checkAccess($accountDetailsResponse)) { - return false; - } - - $this->view->assign('actionId', $actionId); - $this->view->assign('accountId', $this->accountId); - $this->view->assign('accountData', $accountDetailsResponse->getAccountVData()); - $this->view->assign('gotData', $this->isGotData()); - - return true; - } - - /** - * Comprobar si el usuario dispone de acceso al módulo - * - * @param AccountDetailsResponse $accountDetailsResponse - * @return bool - * @throws \SP\Core\Dic\ContainerException - */ - public function checkAccess(AccountDetailsResponse $accountDetailsResponse = null) - { - $this->view->assign('showLogo', false); - - if (!$this->acl->checkUserAccess($this->actionId)) { - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_PAGE_NO_PERMISSION); - - return false; - } - - if (!UserPass::checkUserUpdateMPass($this->session->getUserData()->getId())) { - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_UPDATE_MPASS); - - return false; - } - - if ($this->accountId > 0 && $accountDetailsResponse !== null) { - $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()); - - $this->accountAcl = (new AccountAcl($this->actionId, $this->isHistory))->getAcl($acccountAclDto); - - if (!$this->accountAcl->checkAccountAccess()) { - ErrorUtil::showErrorInView($this->view, ErrorUtil::ERR_ACCOUNT_NO_PERMISSION); - - return false; - } - } - - return true; - } - - /** - * @return int - */ - public function getAccountHistoryId() - { - return $this->accountHistoryId; - } - - /** - * Initialize - * - * @throws \Psr\Container\ContainerExceptionInterface - */ - protected function initialize() - { - $this->view->assign('changesHash'); - $this->view->assign('chkUserEdit'); - $this->view->assign('chkGroupEdit'); - $this->view->assign('isView', false); - $this->view->assign('sk', SessionUtil::getSessionKey(true)); - } -} \ No newline at end of file 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 f5285ebc..0c57fbd3 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 @@ -24,18 +24,17 @@
- @@ -44,20 +43,21 @@ - - - - diff --git a/app/modules/web/themes/material-blue/views/account/account-request.inc b/app/modules/web/themes/material-blue/views/account/account-request.inc index 6b7b1ee7..28627372 100644 --- a/app/modules/web/themes/material-blue/views/account/account-request.inc +++ b/app/modules/web/themes/material-blue/views/account/account-request.inc @@ -1,4 +1,9 @@ - +
@@ -16,7 +21,7 @@ + value="getName(); ?>" readonly>
@@ -28,7 +33,7 @@ + value="getClientName(); ?>" readonly> 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 98bf2155..bbe26aca 100644 --- a/app/modules/web/themes/material-blue/views/account/account.inc +++ b/app/modules/web/themes/material-blue/views/account/account.inc @@ -6,12 +6,7 @@
- - - - - +
- + @@ -170,15 +165,22 @@ - - name; ?> + + isSelected()): ?> + getName(); ?> + - + - 0): ?> + 0): ?> - 0): ?> + 0): ?> diff --git a/lib/SP/Account/AccountUtil.php b/lib/SP/Account/AccountUtil.php index b3707934..e5971e49 100644 --- a/lib/SP/Account/AccountUtil.php +++ b/lib/SP/Account/AccountUtil.php @@ -32,7 +32,7 @@ use SP\Core\Exceptions\SPException; use SP\Core\Session\Session; use SP\Core\SessionFactory; use SP\DataModel\ItemSearchData; -use SP\Mvc\Model\QueryFilter; +use SP\Mvc\Model\QueryCondition; use SP\Storage\DbWrapper; use SP\Storage\QueryData; @@ -245,11 +245,11 @@ class AccountUtil * * @param Session $session * @param bool $useGlobalSearch - * @return QueryFilter + * @return QueryCondition */ public static function getAccountFilterUser(Session $session, $useGlobalSearch = false) { - $queryFilter = new QueryFilter(); + $queryFilter = new QueryCondition(); $configData = $session->getConfig(); $userData = $session->getUserData(); @@ -287,13 +287,14 @@ class AccountUtil /** * Devuelve el filtro para la consulta SQL de cuentas que un usuario puede acceder * - * @param QueryData $Data - * @param Session $session - * @param bool $useGlobalSearch - * @return array + * @param Session $session + * @param bool $useGlobalSearch + * @return QueryCondition */ - public static function getAccountHistoryFilterUser(QueryData $Data, Session $session, $useGlobalSearch = false) + public static function getAccountHistoryFilterUser(Session $session, $useGlobalSearch = false) { + $queryFilter = new QueryCondition(); + $configData = $session->getConfig(); $userData = $session->getUserData(); @@ -302,39 +303,29 @@ class AccountUtil && !($useGlobalSearch && $session->getUserProfile()->isAccGlobalSearch() && $configData->isGlobalSearch()) ) { // Filtro usuario y grupo - $filterUser[] = 'AH.userId = ?'; - $Data->addParam($userData->getId()); + $filter = + /** @lang SQL */ + '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 = ?)'; - $filterUser[] = 'AH.userGroupId = ?'; - $Data->addParam($userData->getUserGroupId()); - - // Filtro de cuenta en usuarios y grupos secundarios - $filterUser[] = /** @lang SQL */ - 'AH.accountId IN (SELECT accountId FROM AccountToUser WHERE accountId = AH.accountId AND userId = ? UNION ALL SELECT accountId FROM AccountToUserGroup WHERE accountId = account_id AND AH.accountId = ?)'; - $Data->addParam($userData->getId()); - $Data->addParam($userData->getUserGroupId()); - - // Filtro de grupo principal de cuenta en grupos que incluyen al usuario - $filterUser[] = /** @lang SQL */ - 'AH.userGroupId IN (SELECT userGroupId FROM UserToUserGroup WHERE userGroupId = AH.userGroupId AND userId = ?)'; - $Data->addParam($userData->getId()); + $params = [$userData->getId(), $userData->getUserGroupId(), $userData->getId(), $userData->getUserGroupId(), $userData->getId()]; if ($configData->isAccountFullGroupAccess()) { // Filtro de grupos secundarios en grupos que incluyen al usuario - $filterUser[] = /** @lang SQL */ - 'AH.accountId = (SELECT accountId FROM AccountToUserGroup aug INNER JOIN UserToUserGroup uug ON uug.userGroupId = aug.userGroupId WHERE aug.accountId = AH.accountId AND uug.userId = ? LIMIT 1)'; - $Data->addParam($userData->getId()); + $filter .= /** @lang SQL */ + PHP_EOL . 'OR AH.accountId = (SELECT accountId FROM AccountToUserGroup aug INNER JOIN UserToUserGroup uug ON uug.userGroupId = aug.userGroupId WHERE aug.accountId = AH.accountId AND uug.userId = ? LIMIT 1)'; + $params[] = $userData->getId(); } - $queryWhere[] = '(' . implode(' OR ', $filterUser) . ')'; + $queryFilter->addFilter($filter, $params); } - $queryWhere[] = '(AH.isPrivate = 0 OR (AH.isPrivate = 1 AND AH.userId = ?))'; - $Data->addParam($userData->getId()); - $queryWhere[] = '(AH.isPrivateGroup = 0 OR (AH.isPrivateGroup = 1 AND AH.userGroupId = ?))'; - $Data->addParam($userData->getUserGroupId()); + $queryFilter->addFilter(/** @lang SQL */ + '(AH.isPrivate = 0 OR (AH.isPrivate = 1 AND AH.userId = ?)) AND (AH.isPrivateGroup = 0 OR (AH.isPrivateGroup = 1 AND AH.userGroupId = ?))', [$userData->getId(), $userData->getUserGroupId()]); - return $queryWhere; + return $queryFilter; } /** diff --git a/lib/SP/Config/Config.php b/lib/SP/Config/Config.php index 18b860b8..10013c69 100644 --- a/lib/SP/Config/Config.php +++ b/lib/SP/Config/Config.php @@ -27,7 +27,6 @@ namespace SP\Config; use ReflectionObject; use SP\Core\Exceptions\ConfigException; use SP\Core\Session\Session; -use SP\Core\SessionFactory; use SP\Core\Traits\InjectableTrait; use SP\Storage\XmlFileStorageInterface; @@ -62,6 +61,7 @@ class Config * * @param XmlFileStorageInterface $fileStorage * @throws \SP\Core\Exceptions\ConfigException + * @throws \SP\Core\Dic\ContainerException */ public function __construct(XmlFileStorageInterface $fileStorage) { @@ -114,7 +114,7 @@ class Config /** * Obtener la configuración o devolver una nueva * - * @return ConfigData + * @return void * @deprecated */ public static function getConfig() @@ -129,15 +129,11 @@ class Config */ public function loadConfig($reload = false) { - if ($reload === false && self::$configLoaded) { - return $this->configData; - } - - $ConfigData = $this->session->getConfig(); + $configData = $this->session->getConfig(); if ($reload === true - || !is_object($ConfigData) - || time() >= ($this->session->getConfigTime() + $ConfigData->getSessionTimeout() / 2) + || null === $configData + || time() >= ($this->session->getConfigTime() + $configData->getSessionTimeout() / 2) ) { $this->saveConfigInSession(); } diff --git a/lib/SP/Controller/ControllerBase.php b/lib/SP/Controller/ControllerBase.php index aab9de48..f1421ce0 100644 --- a/lib/SP/Controller/ControllerBase.php +++ b/lib/SP/Controller/ControllerBase.php @@ -101,6 +101,7 @@ abstract class ControllerBase * Constructor * * @param $actionName + * @throws \SP\Core\Dic\ContainerException */ public function __construct($actionName) { diff --git a/lib/SP/Core/Acl/UnauthorizedPageException.php b/lib/SP/Core/Acl/UnauthorizedPageException.php new file mode 100644 index 00000000..70182d15 --- /dev/null +++ b/lib/SP/Core/Acl/UnauthorizedPageException.php @@ -0,0 +1,48 @@ +. + */ + +namespace SP\Core\Acl; + +use SP\Core\Exceptions\SPException; + +/** + * Class UnauthorizedPageException + * + * @package SP\Core\Acl + */ +class UnauthorizedPageException extends SPException +{ + /** + * SPException constructor. + * + * @param string $type + * @param int $code + * @param \Exception|null $previous + */ + public function __construct($type, $code = 0, \Exception $previous = null) + { + parent::__construct($type, __u('No tiene permisos para acceder a esta página'), __u('Consulte con el administrador'), $code, $previous); + } + +} \ No newline at end of file diff --git a/lib/SP/Core/Session/Session.php b/lib/SP/Core/Session/Session.php index 232bc564..88ea295e 100644 --- a/lib/SP/Core/Session/Session.php +++ b/lib/SP/Core/Session/Session.php @@ -54,7 +54,7 @@ class Session * @param mixed $default * @return mixed */ - protected function getSessionKey($key, $default = '') + protected function getSessionKey($key, $default = null) { if (isset($_SESSION[$key])) { return is_numeric($default) ? (int)$_SESSION[$key] : $_SESSION[$key]; @@ -78,20 +78,13 @@ class Session * * @param string $key El nombre de la variable * @param mixed $value El valor de la variable + * @return mixed */ protected function setSessionKey($key, $value) { $_SESSION[$key] = $value; - } - /** - * Devolver la configuración - * - * @return ConfigData - */ - public function getConfig() - { - return $this->getSessionKey('config'); + return $value; } /** @@ -256,4 +249,39 @@ class Session { $this->setSessionKey('tempmasterpass', $password); } + + /** + * @return mixed + */ + public function getSecurityKey() + { + return $this->getSessionKey('sk'); + } + + /** + * @return string + */ + public function generateSecurityKey() + { + return $this->setSecurityKey(sha1(time() . $this->getConfig()->getPasswordSalt())); + } + + /** + * @param $sk + * @return mixed + */ + public function setSecurityKey($sk) + { + return $this->setSessionKey('sk', $sk); + } + + /** + * Devolver la configuración + * + * @return ConfigData + */ + public function getConfig() + { + return $this->getSessionKey('config'); + } } \ No newline at end of file diff --git a/lib/SP/DataModel/Dto/AccountDetailsResponse.php b/lib/SP/DataModel/Dto/AccountDetailsResponse.php index a20b53f7..74b2f7ad 100644 --- a/lib/SP/DataModel/Dto/AccountDetailsResponse.php +++ b/lib/SP/DataModel/Dto/AccountDetailsResponse.php @@ -44,15 +44,15 @@ class AccountDetailsResponse /** * @var array Los Ids de los usuarios secundarios de la cuenta. */ - private $users; + private $users = []; /** * @var array Los Ids de los grupos secundarios de la cuenta. */ - private $userGroups; + private $userGroups = []; /** * @var array */ - private $tags; + private $tags = []; /** * AccountDetailsResponse constructor. diff --git a/lib/SP/Forms/AccountForm.php b/lib/SP/Forms/AccountForm.php index ec00cdb4..062cf300 100644 --- a/lib/SP/Forms/AccountForm.php +++ b/lib/SP/Forms/AccountForm.php @@ -87,16 +87,17 @@ class AccountForm extends FormBase implements FormInterface $this->accountRequest->url = Request::analyze('url'); $this->accountRequest->notes = Request::analyze('notes'); $this->accountRequest->userEditId = SessionFactory::getUserData()->getId(); - $this->accountRequest->otherUserEdit = Request::analyze('userEditEnabled', 0, false, 1); - $this->accountRequest->otherUserGroupEdit = Request::analyze('groupEditEnabled', 0, false, 1); + $this->accountRequest->otherUserEdit = Request::analyze('otherUserEditEnabled', 0, false, 1); + $this->accountRequest->otherUserGroupEdit = Request::analyze('otherUserGroupEditEnabled', 0, false, 1); $this->accountRequest->pass = Request::analyzeEncrypted('pass'); $this->accountRequest->isPrivate = Request::analyze('privateEnabled', 0, false, 1); $this->accountRequest->isPrivateGroup = Request::analyze('privateGroupEnabled', 0, false, 1); $this->accountRequest->passDateChange = Request::analyze('passworddatechange_unix', 0); $this->accountRequest->parentId = Request::analyze('parentAccountId', 0); + $this->accountRequest->userGroupId = Request::analyze('mainUserGroupId', 0); // Arrays - $accountOtherGroups = Request::analyze('otherGroups', 0); + $accountOtherGroups = Request::analyze('otherUserGroups', 0); $accountOtherUsers = Request::analyze('otherUsers', 0); $accountTags = Request::analyze('tags', 0); @@ -111,15 +112,6 @@ class AccountForm extends FormBase implements FormInterface if (is_array($accountTags)) { $this->accountRequest->tags = $accountTags; } - - $accountMainGroupId = Request::analyze('mainGroupId', 0); - - // Cambiar el grupo principal si el usuario es Admin - if ($accountMainGroupId !== 0 - && (SessionFactory::getUserData()->isIsAdminApp() || SessionFactory::getUserData()->isIsAdminAcc()) - ) { - $this->accountRequest->userGroupId = $accountMainGroupId; - } } /** diff --git a/lib/SP/Mvc/Model/QueryAssignment.php b/lib/SP/Mvc/Model/QueryAssignment.php new file mode 100644 index 00000000..91ca44ed --- /dev/null +++ b/lib/SP/Mvc/Model/QueryAssignment.php @@ -0,0 +1,97 @@ +. + */ + +namespace SP\Mvc\Model; + +/** + * Class QueryAssignment + * + * @package SP\Mvc\Model + */ +class QueryAssignment +{ + /** + * @var array + */ + protected $fields = []; + /** + * @var array + */ + protected $values = []; + + /** + * @param $field + * @param $value + * @return QueryAssignment + */ + public function addField($field, $value) + { + if (strpos($field, '=') === false) { + $this->fields[] = $field . ' = ?'; + $this->values[] = $value; + } + + return $this; + } + + /** + * @param array $fields + * @param array $values + * @return QueryAssignment + */ + public function setFields(array $fields, array $values) + { + $this->fields = array_map(function ($value) { + return strpos($value, '=') === false ? $value . ' = ?' : $value; + }, $fields); + + $this->values = array_merge($this->values, $values); + + return $this; + } + + /** + * @return string|null + */ + public function getAssignments() + { + return $this->hasFields() ? implode(',', $this->fields) : null; + } + + /** + * @return bool + */ + public function hasFields() + { + return count($this->fields) > 0; + } + + /** + * @return array + */ + public function getValues() + { + return $this->values; + } +} \ No newline at end of file diff --git a/lib/SP/Mvc/Model/QueryFilter.php b/lib/SP/Mvc/Model/QueryCondition.php similarity index 86% rename from lib/SP/Mvc/Model/QueryFilter.php rename to lib/SP/Mvc/Model/QueryCondition.php index 1f9254d3..bc213358 100644 --- a/lib/SP/Mvc/Model/QueryFilter.php +++ b/lib/SP/Mvc/Model/QueryCondition.php @@ -25,14 +25,14 @@ namespace SP\Mvc\Model; /** - * Class QueryFilter + * Class QueryCondition * * @package SP\Mvc\Model */ -class QueryFilter +class QueryCondition { - const FILTER_AND = ' AND '; - const FILTER_OR = ' OR '; + const CONDITION_AND = ' AND '; + const CONDITION_OR = ' OR '; /** * @var array @@ -46,7 +46,7 @@ class QueryFilter /** * @param $query * @param $params - * @return QueryFilter + * @return QueryCondition */ public function addFilter($query, array $params) { @@ -60,9 +60,9 @@ class QueryFilter * @param string $type * @return string|null */ - public function getFilters($type = self::FILTER_AND) + public function getFilters($type = self::CONDITION_AND) { - if ($type !== self::FILTER_AND && $type !== self::FILTER_OR) { + if ($type !== self::CONDITION_AND && $type !== self::CONDITION_OR) { throw new \RuntimeException(__u('Tipo de filtro inválido')); } diff --git a/lib/SP/Mvc/View/Components/SelectItem.php b/lib/SP/Mvc/View/Components/SelectItem.php index 1042edbc..96109523 100644 --- a/lib/SP/Mvc/View/Components/SelectItem.php +++ b/lib/SP/Mvc/View/Components/SelectItem.php @@ -47,6 +47,10 @@ class SelectItem * @var bool */ protected $selected = false; + /** + * @var bool + */ + protected $skip = false; /** * SelectItem constructor. @@ -102,4 +106,20 @@ class SelectItem { return null !== $this->item && isset($this->item->{$property}) ? $this->item->{$property} : null; } + + /** + * @return bool + */ + public function isSkip() + { + return $this->skip; + } + + /** + * @param bool $skip + */ + public function setSkip($skip) + { + $this->skip = (bool)$skip; + } } \ No newline at end of file diff --git a/lib/SP/Mvc/View/Components/SelectItemAdapter.php b/lib/SP/Mvc/View/Components/SelectItemAdapter.php index ad660a42..14c07811 100644 --- a/lib/SP/Mvc/View/Components/SelectItemAdapter.php +++ b/lib/SP/Mvc/View/Components/SelectItemAdapter.php @@ -50,6 +50,34 @@ class SelectItemAdapter implements ItemAdapterInterface $this->items = $items; } + /** + * @param array $items + * @return static + */ + public static function factory(array $items) + { + return new static($items); + } + + /** + * Returns an array of ids from the given array of objects + * + * @param array $items + * @return array + */ + public static function getIdFromArrayOfObjects(array $items) + { + $ids = []; + + foreach ($items as $item) { + if (is_object($item) && null !== $item->id) { + $ids[] = $item->id; + } + } + + return $ids; + } + /** * Returns a JSON like collection of items for a select component * @@ -71,22 +99,6 @@ class SelectItemAdapter implements ItemAdapterInterface return Json::getJson($out); } - /** - * Returns a collection of items for a select component - * - * @return array - */ - public function getItemsFromArray() - { - $out = []; - - foreach ($this->items as $key => $value) { - $out[] = new SelectItem($key, $value); - } - - return $out; - } - /** * Returns a collection of items for a select component * @@ -108,14 +120,19 @@ class SelectItemAdapter implements ItemAdapterInterface * Returns a collection of items for a select component and set selected ones from an array * * @param array $selected + * @param null $skip * @return SelectItem[] */ - public function getItemsFromModelSelected(array $selected) + public function getItemsFromModelSelected(array $selected, $skip = null) { $items = $this->getItemsFromModel(); foreach ($items as $item) { - if ($selected !== null && in_array($item->getId(), $selected, false)) { + if ($skip !== null && $item->getId() === $skip) { + $item->setSkip(true); + } + + if (in_array($item->getId(), $selected, false)) { $item->setSelected(true); } } @@ -161,4 +178,20 @@ class SelectItemAdapter implements ItemAdapterInterface return $items; } + + /** + * Returns a collection of items for a select component + * + * @return array + */ + public function getItemsFromArray() + { + $out = []; + + foreach ($this->items as $key => $value) { + $out[] = new SelectItem($key, $value); + } + + return $out; + } } \ No newline at end of file diff --git a/lib/SP/Repositories/Account/AccountRepository.php b/lib/SP/Repositories/Account/AccountRepository.php index cec0656d..03aecb3c 100644 --- a/lib/SP/Repositories/Account/AccountRepository.php +++ b/lib/SP/Repositories/Account/AccountRepository.php @@ -36,7 +36,8 @@ use SP\DataModel\AccountVData; use SP\DataModel\Dto\AccountSearchResponse; use SP\DataModel\ItemData; use SP\DataModel\ItemSearchData; -use SP\Mvc\Model\QueryFilter; +use SP\Mvc\Model\QueryAssignment; +use SP\Mvc\Model\QueryCondition; use SP\Repositories\Repository; use SP\Repositories\RepositoryItemInterface; use SP\Repositories\RepositoryItemTrait; @@ -73,25 +74,22 @@ class AccountRepository extends Repository implements RepositoryItemInterface } /** - * @param $id - * @return AccountPassData + * @param QueryCondition $queryCondition + * @return ItemData */ - public function getPasswordHistoryForId($id) + public function getPasswordHistoryForId(QueryCondition $queryCondition) { - $Data = new QueryData(); - $Data->setMapClassName(AccountPassData::class); - $Data->setLimit(1); + $query = /** @lang SQL */ + 'SELECT AH.id, AH.name, AH.login, AH.pass, AH.key, AH.parentId + FROM AccountHistory AH + WHERE ' . $queryCondition->getFilters(); - $Data->setSelect('AH.id, AH.name, AH.login, AH.pass, AH.key, AH.parentId'); - $Data->setFrom('AccountHistory AH'); + $queryData = new QueryData(); + $queryData->setMapClassName(AccountPassData::class); + $queryData->setQuery($query); + $queryData->setParams($queryCondition->getParams()); - $queryWhere = AccountUtil::getAccountHistoryFilterUser($Data, $this->session); - $queryWhere[] = 'AH.id = ?'; - $Data->addParam($id); - - $Data->setWhere($queryWhere); - - return DbWrapper::getResults($Data, $this->db); + return DbWrapper::getResults($queryData, $this->db); } /** @@ -127,48 +125,50 @@ class AccountRepository extends Repository implements RepositoryItemInterface { $query = /** @lang SQL */ 'INSERT INTO Account SET - clientId = :clientId, - categoryId = :categoryId, - name = :name, - login = :login, - url = :url, - pass = :pass, - `key` = :key, - notes = :notes, + clientId = ?, + categoryId = ?, + name = ?, + login = ?, + url = ?, + pass = ?, + `key` = ?, + notes = ?, dateAdd = NOW(), - userId = :userId, - userGroupId = :userGroupId, - userEditId = :userEditId, - otherUserEdit = :otherUserEdit, - otherUserGroupEdit = :otherGroupEdit, - isPrivate = :isPrivate, - isPrivateGroup = :isPrivateGroup, + userId = ?, + userGroupId = ?, + userEditId = ?, + otherUserEdit = ?, + otherUserGroupEdit = ?, + isPrivate = ?, + isPrivateGroup = ?, passDate = UNIX_TIMESTAMP(), - passDateChange = :passDateChange, - parentId = :parentId'; + passDateChange = ?, + parentId = ?'; - $Data = new QueryData(); - $Data->setQuery($query); - $Data->addParam($itemData->clientId, 'clientId'); - $Data->addParam($itemData->categoryId, 'aategoryId'); - $Data->addParam($itemData->name, 'name'); - $Data->addParam($itemData->login, 'login'); - $Data->addParam($itemData->url, 'url'); - $Data->addParam($itemData->pass, 'pass'); - $Data->addParam($itemData->key, 'key'); - $Data->addParam($itemData->notes, 'notes'); - $Data->addParam($itemData->userId, 'userId'); - $Data->addParam($itemData->userGroupId ?: $this->session->getUserData()->getUserGroupId(), 'userGroupId'); - $Data->addParam($itemData->userId, 'userEditId'); - $Data->addParam($itemData->otherUserEdit, 'otherUserEdit'); - $Data->addParam($itemData->otherUserGroupEdit, 'otherGroupEdit'); - $Data->addParam($itemData->isPrivate, 'isPrivate'); - $Data->addParam($itemData->isPrivateGroup, 'isPrivateGroup'); - $Data->addParam($itemData->passDateChange, 'passDateChange'); - $Data->addParam($itemData->parentId, 'parentId'); - $Data->setOnErrorMessage(__u('Error al crear la cuenta')); + $queryData = new QueryData(); + $queryData->setQuery($query); + $queryData->setParams([ + $itemData->clientId, + $itemData->categoryId, + $itemData->name, + $itemData->login, + $itemData->url, + $itemData->pass, + $itemData->key, + $itemData->notes, + $itemData->userId, + $itemData->userGroupId, + $itemData->userId, + $itemData->otherUserEdit, + $itemData->otherUserGroupEdit, + $itemData->isPrivate, + $itemData->isPrivateGroup, + $itemData->passDateChange, + $itemData->parentId + ]); + $queryData->setOnErrorMessage(__u('Error al crear la cuenta')); - DbWrapper::getQuery($Data, $this->db); + DbWrapper::getQuery($queryData, $this->db); return $this->db->getLastId(); } @@ -280,56 +280,56 @@ class AccountRepository extends Repository implements RepositoryItemInterface */ public function update($itemData) { - $Data = new QueryData(); + $queryAssignment = new QueryAssignment(); - $fields = [ - 'clientId = :clientId', - 'categoryId = :categoryId', - 'name = :name', - 'login = :login', - 'url = :url', - 'notes = :notes', - 'userEditId = :userEditId', + $queryAssignment->setFields([ + 'clientId', + 'categoryId', + 'name', + 'login', + 'url', + 'notes', + 'userEditId', 'dateEdit = NOW()', - 'passDateChange = :passDateChange', - 'isPrivate = :isPrivate', - 'isPrivateGroup = :isPrivateGroup', - 'parentId = :parentId' - ]; + 'passDateChange', + 'isPrivate', + 'isPrivateGroup', + 'parentId' + ], [ + $itemData->clientId, + $itemData->categoryId, + $itemData->name, + $itemData->login, + $itemData->url, + $itemData->notes, + $itemData->userEditId, + $itemData->passDateChange, + $itemData->isPrivate, + $itemData->isPrivateGroup, + $itemData->parentId + ]); + + + $queryData = new QueryData(); if ($itemData->changeUserGroup) { - $fields[] = 'userGroupId = :userGroupId'; - - $Data->addParam($itemData->userGroupId, 'userGroupId'); + $queryAssignment->addField('userGroupId', $itemData->userGroupId); } if ($itemData->changePermissions) { - $fields[] = 'otherUserEdit = :otherUserEdit'; - $fields[] = 'otherUserGroupEdit = :otherUserGroupEdit'; - - $Data->addParam($itemData->otherUserEdit, 'otherUserEdit'); - $Data->addParam($itemData->otherUserGroupEdit, 'otherUserGroupEdit'); + $queryAssignment->addField('otherUserEdit', $itemData->otherUserEdit); + $queryAssignment->addField('otherUserGroupEdit', $itemData->otherUserGroupEdit); } $query = /** @lang SQL */ - 'UPDATE Account SET ' . implode(',', $fields) . ' WHERE id = :accountId'; + 'UPDATE Account SET ' . $queryAssignment->getAssignments() . ' WHERE id = ?'; - $Data->setQuery($query); - $Data->addParam($itemData->clientId, 'clientId'); - $Data->addParam($itemData->categoryId, 'categoryId'); - $Data->addParam($itemData->name, 'name'); - $Data->addParam($itemData->login, 'login'); - $Data->addParam($itemData->url, 'url'); - $Data->addParam($itemData->notes, 'notes'); - $Data->addParam($itemData->userEditId, 'userEditId'); - $Data->addParam($itemData->passDateChange, 'passDateChange'); - $Data->addParam($itemData->isPrivate, 'isPrivate'); - $Data->addParam($itemData->isPrivateGroup, 'isPrivateGroup'); - $Data->addParam($itemData->parentId, 'parentId'); - $Data->addParam($itemData->id, 'id'); - $Data->setOnErrorMessage(__u('Error al modificar la cuenta')); + $queryData->setQuery($query); + $queryData->setParams($queryAssignment->getValues()); + $queryData->addParam($itemData->id); + $queryData->setOnErrorMessage(__u('Error al modificar la cuenta')); - return DbWrapper::getQuery($Data, $this->db); + return DbWrapper::getQuery($queryData, $this->db); } /** @@ -529,8 +529,8 @@ class AccountRepository extends Repository implements RepositoryItemInterface $queryJoin = []; $queryLimit = ''; - $queryFilterCommon = new QueryFilter(); - $queryFilterSelect = new QueryFilter(); + $queryFilterCommon = new QueryCondition(); + $queryFilterSelect = new QueryCondition(); $searchText = $accountSearchFilter->getTxtSearch(); @@ -568,7 +568,7 @@ class AccountRepository extends Repository implements RepositoryItemInterface $where = []; if ($queryFilterCommon->hasFilters()) { - $where[] = $queryFilterCommon->getFilters(QueryFilter::FILTER_OR); + $where[] = $queryFilterCommon->getFilters(QueryCondition::CONDITION_OR); } if ($queryFilterSelect->hasFilters()) { @@ -610,10 +610,10 @@ class AccountRepository extends Repository implements RepositoryItemInterface } /** - * @param QueryFilter $queryFilter + * @param QueryCondition $queryFilter * @return array */ - public function getForUser(QueryFilter $queryFilter) + public function getForUser(QueryCondition $queryFilter) { $query = /** @lang SQL */ 'SELECT A.id, A.name, C.name AS clientName @@ -631,10 +631,10 @@ class AccountRepository extends Repository implements RepositoryItemInterface /** - * @param QueryFilter $queryFilter + * @param QueryCondition $queryFilter * @return array */ - public function getLinked(QueryFilter $queryFilter) + public function getLinked(QueryCondition $queryFilter) { $query = /** @lang SQL */ 'SELECT A.id, A.name, C.name AS clientName diff --git a/lib/SP/Repositories/Account/AccountToTagRepository.php b/lib/SP/Repositories/Account/AccountToTagRepository.php index 3fcee602..61ee4e7c 100644 --- a/lib/SP/Repositories/Account/AccountToTagRepository.php +++ b/lib/SP/Repositories/Account/AccountToTagRepository.php @@ -72,7 +72,7 @@ class AccountToTagRepository extends Repository public function add(AccountRequest $accountRequest) { $query = /** @lang SQL */ - 'INSERT INTO AccountToTag (accountId, tagId) VALUES ' . $this->getParamsFromArray($accountRequest->tags); + 'INSERT INTO AccountToTag (accountId, tagId) VALUES ' . $this->getParamsFromArray($accountRequest->tags, '(?,?)'); $Data = new QueryData(); $Data->setQuery($query); @@ -89,18 +89,18 @@ class AccountToTagRepository extends Repository /** * Eliminar las etiquetas de una cuenta * - * @param int $accountId + * @param int $id * @return bool * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException */ - public function delete($accountId) + public function deleteByAccountId($id) { $Data = new QueryData(); $query = /** @lang SQL */ 'DELETE FROM AccountToTag WHERE accountId = ?'; - $Data->addParam($accountId); + $Data->addParam($id); $Data->setQuery($query); $Data->setOnErrorMessage(__u('Error al eliminar las etiquetas de la cuenta')); @@ -115,7 +115,7 @@ class AccountToTagRepository extends Repository */ public function update(AccountRequest $accountRequest) { - $this->delete($accountRequest->id); + $this->deleteByAccountId($accountRequest->id); $this->add($accountRequest); } diff --git a/lib/SP/Repositories/Account/AccountToUserRepository.php b/lib/SP/Repositories/Account/AccountToUserRepository.php index 1c340f89..00d71bdf 100644 --- a/lib/SP/Repositories/Account/AccountToUserRepository.php +++ b/lib/SP/Repositories/Account/AccountToUserRepository.php @@ -49,7 +49,7 @@ class AccountToUserRepository extends Repository */ public function update(AccountRequest $accountRequest) { - $this->delete($accountRequest->id); + $this->deleteByAccountId($accountRequest->id); $this->add($accountRequest); return false; @@ -58,19 +58,19 @@ class AccountToUserRepository extends Repository /** * Eliminar la asociación de grupos con cuentas. * - * @param int $accountId con el Id de la cuenta + * @param int $id con el Id de la cuenta * @return bool * @throws \SP\Core\Exceptions\QueryException * @throws \SP\Core\Exceptions\ConstraintException */ - public function delete($accountId) + public function deleteByAccountId($id) { $Data = new QueryData(); $query = /** @lang SQL */ 'DELETE FROM AccountToUser WHERE accountId = ?'; - $Data->addParam($accountId); + $Data->addParam($id); $Data->setQuery($query); $Data->setOnErrorMessage(__u('Error al eliminar usuarios asociados a la cuenta')); @@ -89,7 +89,7 @@ class AccountToUserRepository extends Repository public function add(AccountRequest $accountRequest) { $query = /** @lang SQL */ - 'INSERT INTO AccountToUser (accountId, userId) VALUES ' . $this->getParamsFromArray($accountRequest->users); + 'INSERT INTO AccountToUser (accountId, userId) VALUES ' . $this->getParamsFromArray($accountRequest->users, '(?,?)'); $Data = new QueryData(); $Data->setQuery($query); diff --git a/lib/SP/Repositories/Client/ClientRepository.php b/lib/SP/Repositories/Client/ClientRepository.php index a3921a78..768ca076 100644 --- a/lib/SP/Repositories/Client/ClientRepository.php +++ b/lib/SP/Repositories/Client/ClientRepository.php @@ -29,7 +29,7 @@ use SP\Core\Exceptions\SPException; use SP\DataModel\ClientData; use SP\DataModel\ItemData; use SP\DataModel\ItemSearchData; -use SP\Mvc\Model\QueryFilter; +use SP\Mvc\Model\QueryCondition; use SP\Repositories\Repository; use SP\Repositories\RepositoryItemInterface; use SP\Repositories\RepositoryItemTrait; @@ -300,10 +300,10 @@ class ClientRepository extends Repository implements RepositoryItemInterface /** * Devolver los clientes visibles por el usuario * - * @param QueryFilter $queryFilter + * @param QueryCondition $queryFilter * @return array */ - public function getAllForFilter(QueryFilter $queryFilter) + public function getAllForFilter(QueryCondition $queryFilter) { $query = /** @lang SQL */ 'SELECT C.id, C.name diff --git a/lib/SP/Services/Account/AccountService.php b/lib/SP/Services/Account/AccountService.php index 01352195..bea2c3c2 100644 --- a/lib/SP/Services/Account/AccountService.php +++ b/lib/SP/Services/Account/AccountService.php @@ -192,17 +192,17 @@ class AccountService implements AccountServiceInterface public function create(AccountRequest $accountRequest) { $accountRequest->changePermissions = (new AccountAcl(ActionsInterface::ACCOUNT_EDIT))->isShowPermission(); + $accountRequest->userGroupId ?: $this->session->getUserData()->getUserGroupId(); $pass = $this->getPasswordEncrypted($accountRequest->pass); $accountRequest->pass = $pass['pass']; $accountRequest->key = $pass['key']; + $accountRequest->id = $this->accountRepository->create($accountRequest); - $id = $this->accountRepository->create($accountRequest); + $this->addItems($accountRequest); - $this->addItems($accountRequest, $id); - - return $id; + return $accountRequest->id; } /** @@ -236,9 +236,8 @@ class AccountService implements AccountServiceInterface * Adds external items to the account * * @param AccountRequest $accountRequest - * @param int $accountId */ - protected function addItems(AccountRequest $accountRequest, $accountId) + protected function addItems(AccountRequest $accountRequest) { try { if ($accountRequest->changePermissions) { @@ -270,6 +269,10 @@ class AccountService implements AccountServiceInterface { $accountRequest->changePermissions = (new AccountAcl(ActionsInterface::ACCOUNT_EDIT))->isShowPermission(); + // Cambiar el grupo principal si el usuario es Admin + $accountRequest->changeUserGroup = ($accountRequest->userGroupId !== 0 + && ($this->session->getUserData()->getIsAdminApp() || $this->session->getUserData()->getIsAdminAcc())); + $this->addHistory($accountRequest->id); $this->accountRepository->update($accountRequest); @@ -304,12 +307,26 @@ class AccountService implements AccountServiceInterface protected function updateItems(AccountRequest $accountRequest) { try { + if ($accountRequest->changePermissions) { - $this->accountToUserGroupRepository->update($accountRequest); - $this->accountToUserRepository->update($accountRequest); + if (!empty($accountRequest->userGroups)) { + $this->accountToUserGroupRepository->update($accountRequest); + } else { + $this->accountToUserGroupRepository->deleteByAccountId($accountRequest->id); + } + + if (!empty($accountRequest->users)) { + $this->accountToUserRepository->update($accountRequest); + } else { + $this->accountToUserRepository->deleteByAccountId($accountRequest->id); + } } - $this->accountToTagRepository->update($accountRequest); + if (!empty($accountRequest->tags)) { + $this->accountToTagRepository->update($accountRequest); + } else { + $this->accountToTagRepository->deleteByAccountId($accountRequest->id); + } } catch (SPException $e) { Log::writeNewLog(__FUNCTION__, $e->getMessage(), Log::ERROR); } @@ -411,11 +428,14 @@ class AccountService implements AccountServiceInterface /** * @param $id - * @return \SP\DataModel\AccountPassData + * @return \SP\DataModel\ItemData */ public function getPasswordHistoryForId($id) { - return $this->accountRepository->getPasswordHistoryForId($id); + $queryFilter = AccountUtil::getAccountHistoryFilterUser($this->session) + ->addFilter('AH.id = ?', [$id]); + + return $this->accountRepository->getPasswordHistoryForId($queryFilter); } /** diff --git a/lib/SP/Core/Exceptions/AuthException.php b/lib/SP/Services/Auth/AuthException.php similarity index 84% rename from lib/SP/Core/Exceptions/AuthException.php rename to lib/SP/Services/Auth/AuthException.php index 264cce05..92b2a788 100644 --- a/lib/SP/Core/Exceptions/AuthException.php +++ b/lib/SP/Services/Auth/AuthException.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link http://syspass.org - * @copyright 2012-2017, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -22,13 +22,14 @@ * along with sysPass. If not, see . */ -namespace SP\Core\Exceptions; +namespace SP\Services\Auth; +use SP\Core\Exceptions\SPException; /** * Class AuthException * - * @package SP\Core\Exceptions + * @package SP\Services\Auth */ class AuthException extends SPException { diff --git a/lib/SP/Services/Auth/LoginService.php b/lib/SP/Services/Auth/LoginService.php index f667667b..e4422569 100644 --- a/lib/SP/Services/Auth/LoginService.php +++ b/lib/SP/Services/Auth/LoginService.php @@ -37,7 +37,7 @@ use SP\Providers\Auth\Ldap\LdapAuthData; use SP\Bootstrap; use SP\Config\Config; use SP\Core\Events\EventDispatcher; -use SP\Core\Exceptions\AuthException; +use SP\Services\Auth\AuthException; use SP\Core\Exceptions\SPException; use SP\Core\Language; use SP\Core\Messages\LogMessage; @@ -130,6 +130,7 @@ class LoginService * @param Session $session * @param Theme $theme * @param EventDispatcher $eventDispatcher + * @throws \SP\Core\Dic\ContainerException */ public function __construct(Config $config, Session $session, Theme $theme, EventDispatcher $eventDispatcher) { @@ -218,7 +219,7 @@ class LoginService /** * Comprobar los intentos de login * - * @throws \SP\Core\Exceptions\AuthException + * @throws \SP\Services\Auth\AuthException */ private function checkTracking() { @@ -249,7 +250,7 @@ class LoginService /** * Añadir un seguimiento * - * @throws \SP\Core\Exceptions\AuthException + * @throws \SP\Services\Auth\AuthException */ private function addTracking() { @@ -269,7 +270,7 @@ class LoginService * * @throws \SP\Core\Exceptions\SPException * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException - * @throws \SP\Core\Exceptions\AuthException + * @throws \SP\Services\Auth\AuthException */ protected function checkUser() { diff --git a/lib/SP/Services/User/UpdatedMasterPassException.php b/lib/SP/Services/User/UpdatedMasterPassException.php new file mode 100644 index 00000000..036efd0f --- /dev/null +++ b/lib/SP/Services/User/UpdatedMasterPassException.php @@ -0,0 +1,48 @@ +. + */ + +namespace SP\Services\User; + +use SP\Core\Exceptions\SPException; + +/** + * Class UpdatedMasterPassException + * + * @package SP\Services\User + */ +class UpdatedMasterPassException extends SPException +{ + /** + * SPException constructor. + * + * @param string $type + * @param int $code + * @param \Exception $previous + */ + public function __construct($type, $code = 0, \Exception $previous = null) + { + parent::__construct($type, __u('Clave maestra actualizada'), __u('Reinicie la sesión para cambiarla'), $code, $previous); + } + +} \ No newline at end of file diff --git a/lib/SP/Services/User/UserPassService.php b/lib/SP/Services/User/UserPassService.php index f320f313..fea296ca 100644 --- a/lib/SP/Services/User/UserPassService.php +++ b/lib/SP/Services/User/UserPassService.php @@ -74,6 +74,8 @@ class UserPassService /** * UserPassService constructor. + * + * @throws \SP\Core\Dic\ContainerException */ public function __construct() { diff --git a/lib/SP/Services/User/UserService.php b/lib/SP/Services/User/UserService.php index 3bba345e..3b061ecf 100644 --- a/lib/SP/Services/User/UserService.php +++ b/lib/SP/Services/User/UserService.php @@ -51,6 +51,8 @@ class UserService /** * UserService constructor. + * + * @throws \SP\Core\Dic\ContainerException */ public function __construct() { diff --git a/public/js/app-actions.js b/public/js/app-actions.js index a6e6c9ef..8c423182 100644 --- a/public/js/app-actions.js +++ b/public/js/app-actions.js @@ -930,11 +930,11 @@ sysPass.Actions = function (Common) { viewPass: function ($obj) { log.info("account:showpass"); - var parentId = $obj.data("parent-id"); - var id = parentId === 0 ? $obj.data("item-id") : parentId; - var history = $obj.data("history") || 0; + const parentId = $obj.data("parent-id") || 0; + const id = parentId === 0 ? $obj.data("item-id") : parentId; + const history = $obj.data("history") || 0; - var opts = Common.appRequests().getRequestOpts(); + const opts = Common.appRequests().getRequestOpts(); opts.url = ajaxUrl.entrypoint; opts.method = "get"; opts.data = { @@ -1115,7 +1115,7 @@ sysPass.Actions = function (Common) { save: function ($obj) { log.info("account:save"); - var opts = Common.appRequests().getRequestOpts(); + const opts = Common.appRequests().getRequestOpts(); opts.url = ajaxUrl.account.save + "?r=" + $obj.data("action-route") + "/" + $obj.data("item-id"); opts.data = $obj.serialize(); diff --git a/public/js/app-actions.min.js b/public/js/app-actions.min.js index f440f1d2..df739cb3 100644 --- a/public/js/app-actions.min.js +++ b/public/js/app-actions.min.js @@ -13,8 +13,8 @@ var b=c.appRequests().getRequestOpts();b.url=f.main.install;b.data=a.serialize() a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(c.config().LANG[62]);if(0";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(b){b=c.appRequests().getRequestOpts();b.url=f.account.save;b.data={r:"account/saveDelete/"+a.data("item-id"),sk:c.sk.get()};c.appRequests().getActionCall(b,function(a){c.msg.out(a);p.search()})}}})},viewPass:function(a){e.info("account:showpass");var b=a.data("parent-id"),b=0===b? -a.data("item-id"):b,d=a.data("history")||0,g=c.appRequests().getRequestOpts();g.url=f.entrypoint;g.method="get";g.data={r:a.data("action-route")+"/"+b+"/"+d,sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(g,function(a){0!==a.status?c.msg.out(a):(a=$(a.data.html),n(a),h=setTimeout(function(){$.magnificPopup.close()},3E4),a.on("mouseleave",function(){clearTimeout(h);h=setTimeout(function(){$.magnificPopup.close()},3E4)}).on("mouseenter",function(){0!==h&&clearTimeout(h)}))})},copyPass:function(a){e.info("account:copypass"); +c.config().LANG[3]+"

";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(b){b=c.appRequests().getRequestOpts();b.url=f.account.save;b.data={r:"account/saveDelete/"+a.data("item-id"),sk:c.sk.get()};c.appRequests().getActionCall(b,function(a){c.msg.out(a);p.search()})}}})},viewPass:function(a){e.info("account:showpass");var b=a.data("parent-id")||0,b=0=== +b?a.data("item-id"):b,d=a.data("history")||0,g=c.appRequests().getRequestOpts();g.url=f.entrypoint;g.method="get";g.data={r:a.data("action-route")+"/"+b+"/"+d,sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(g,function(a){0!==a.status?c.msg.out(a):(a=$(a.data.html),n(a),h=setTimeout(function(){$.magnificPopup.close()},3E4),a.on("mouseleave",function(){clearTimeout(h);h=setTimeout(function(){$.magnificPopup.close()},3E4)}).on("mouseenter",function(){0!==h&&clearTimeout(h)}))})},copyPass:function(a){e.info("account:copypass"); var b=a.data("parent-id"),b=0===b?a.data("item-id"):b,d=c.appRequests().getRequestOpts();d.url=f.entrypoint;d.method="get";d.async=!1;d.data={r:a.data("action-route")+"/"+b+"/"+a.data("history"),sk:c.sk.get(),isAjax:1};return c.appRequests().getActionCall(d)},copy:function(a){e.info("account:copy");m(c.appRequests().getRouteForQuery(a.data("action-route"),a.data("item-id")),"account")},saveFavorite:function(a,b){e.info("account:saveFavorite");var d="on"===a.data("status"),g={r:(d?a.data("action-id-off"): a.data("action-id-on"))+"/"+a.data("item-id"),sk:c.sk.get(),isAjax:1},q=c.appRequests().getRequestOpts();q.url=f.account.saveFavorite;q.data=g;c.appRequests().getActionCall(q,function(g){c.msg.out(g);0===g.status&&(a.data("status",d?"off":"on"),"function"===typeof b&&b())})},request:function(a){e.info("account:request");var b=c.appRequests().getRequestOpts();b.url=f.account.request;b.data=a.serialize();c.appRequests().getActionCall(b,function(a){c.msg.out(a)})},menu:function(a){a.hide();a.parent().children(".actions-optional").show(250)}, sort:function(a){e.info("account:sort");var c=$("#frmSearch");c.find('input[name="skey"]').val(a.data("key"));c.find('input[name="sorder"]').val(a.data("dir"));c.find('input[name="start"]').val(a.data("start"));p.search()},editPass:function(a){e.info("account:editpass");var b=a.data("parent-id"),b=void 0===b?a.data("item-id"):b;m(c.appRequests().getRouteForQuery(a.data("action-route"),b),"account")},saveEditRestore:function(a){e.info("account:restore");var b=c.appRequests().getRequestOpts();b.url= diff --git a/public/js/app-main.js b/public/js/app-main.js index b822ce3c..97ffac95 100644 --- a/public/js/app-main.js +++ b/public/js/app-main.js @@ -24,8 +24,526 @@ sysPass.Main = function () { "use strict"; + /** + * Comprobar si hay actualizaciones de plugins + */ + const checkPluginUpdates = function () { + log.info("checkPluginUpdates"); + + for (const plugin in appPlugins) { + if (typeof appPlugins[plugin].checkVersion === "function") { + appPlugins[plugin].checkVersion().then(function (json) { + if (json.status === 0 && json.data.plugin !== undefined) { + msg.info(String.format(config.LANG[67], json.data.plugin, json.data.remoteVersion)); + } + }); + } + } + }; + + /** + * Inicializar los plugins + */ + const initPlugins = function () { + log.info("initPlugins"); + + for (let i = 0; i < config.PLUGINS.length; i++) { + const plugin = config.PLUGINS[i]; + + if (typeof sysPass.Plugin[plugin] === "function") { + appPlugins[plugin] = sysPass.Plugin[plugin](oProtected); + } + } + + Object.freeze(appPlugins); + }; + + /** + * @author http://stackoverflow.com/users/24950/robert-k + * @link http://stackoverflow.com/questions/5796718/html-entity-decode + */ + const decodeEntities = (function () { + // this prevents any overhead from creating the object each time + const element = document.createElement("div"); + + function decodeHTMLEntities(str) { + if (str && typeof str === "string") { + // strip script/html tags + str = str.replace(/]*>([\S\s]*?)<\/script>/gmi, ""); + str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, ""); + element.innerHTML = str; + str = element.textContent; + element.textContent = ""; + } + + return str; + } + + return decodeHTMLEntities; + })(); + + /** + * Redimensionar una imagen al viewport + * + * @param $obj + */ + const resizeImage = function ($obj) { + log.info("resizeImage"); + + const viewport = { + width: $(window).width() * 0.90, + height: $(window).height() * 0.90 + }; + const image = { + width: $obj.width(), + height: $obj.height() + }; + const dimension = { + calc: 0, + main: 0, + secondary: 0, + factor: 0.90, + rel: image.width / image.height + }; + + /** + * Ajustar la relación de aspecto de la imagen. + * + * Se tiene en cuenta la dimensión máxima en el eje opuesto. + * + * @param dimension + * @returns {*} + */ + const adjustRel = function (dimension) { + if (dimension.main > dimension.secondary) { + dimension.calc = dimension.main / dimension.rel; + } else if (dimension.main < dimension.secondary) { + dimension.calc = dimension.main * dimension.rel; + } + + if (dimension.calc > dimension.secondary) { + dimension.main *= dimension.factor; + + adjustRel(dimension); + } + + return dimension; + }; + + /** + * Redimensionar en relación a la anchura + */ + const resizeWidth = function () { + dimension.main = viewport.width; + dimension.secondary = viewport.height; + + const adjust = adjustRel(dimension); + + $obj.css({ + "width": adjust.main, + "height": adjust.calc + }); + + image.width = adjust.main; + image.height = adjust.calc; + }; + + /** + * Redimensionar en relación a la altura + */ + const resizeHeight = function () { + dimension.main = viewport.height; + dimension.secondary = viewport.width; + + const adjust = adjustRel(dimension); + + $obj.css({ + "width": adjust.calc, + "height": adjust.main + }); + + image.width = adjust.calc; + image.height = adjust.main; + }; + + if (image.width > viewport.width) { + resizeWidth(); + } else if (image.height > viewport.height) { + log.info("height"); + resizeHeight(); + } + + return image; + }; + + /** + * Evaluar una acción javascript y ejecutar la función + * + * @param evalFn + * @param $obj + */ + const evalAction = function (evalFn, $obj) { + log.info("Eval: " + evalFn); + + if (typeof evalFn === "function") { + evalFn($obj); + } else { + throw Error("Function not found: " + evalFn); + } + }; + + /** + * Delegar los eventos 'blur' y 'keypress' para que los campos de claves + * sean encriptados antes de ser enviados por el formulario + */ + const bindPassEncrypt = function () { + log.info("bindPassEncrypt"); + + $("body").on("blur", ":input[type=password]", function (e) { + const $this = $(this); + + if ($this.hasClass("passwordfield__no-pki")) { + return; + } + + encryptFormValue($this); + }).on("keypress", ":input[type=password]", function (e) { + if (e.keyCode === 13) { + e.preventDefault(); + + const $this = $(this); + encryptFormValue($this); + + $this.closest("form").submit(); + } + }); + }; + + /** + * Inicializar portapapeles + */ + const initializeClipboard = function () { + log.info("initializeClipboard"); + + if (!clipboard.isSupported()) { + log.warn(config.LANG[65]); + return; + } + + $("body").on("click", ".clip-pass-button", function () { + const json = appActions.account.copyPass($(this)).done(function (json) { + if (json.status !== 0) { + msg.out(json); + + return false; + } + + sk.set(json.csrf); + }); + + if (json !== false) { + clipboard.copy(json.responseJSON.data.accpass).then( + function () { + msg.ok(config.LANG[45]); + }, + function (err) { + msg.error(config.LANG[46]); + } + ); + } + }).on("click", ".dialog-clip-button", function () { + const $target = $(this.dataset.clipboardTarget); + + clipboard.copy($target.text()).then( + function () { + $(".dialog-text").removeClass("dialog-clip-copy"); + $target.addClass("dialog-clip-copy"); + }, + function (err) { + msg.error(config.LANG[46]); + } + ); + }).on("click", ".clip-pass-icon", function () { + const $target = $(this.dataset.clipboardTarget); + + clipboard.copy(decodeEntities($target.val())).then( + function () { + msg.ok(config.LANG[45]); + }, + function (err) { + msg.error(config.LANG[46]); + } + ); + }); + }; + + /** + * Encriptar el valor de un campo del formulario + * + * @param $input El id del campo + */ + const encryptFormValue = function ($input) { + log.info("encryptFormValue"); + + const curValue = $input.val(); + + if (curValue !== "" && parseInt($input.attr("data-length")) !== curValue.length) { + const passEncrypted = config.CRYPT.encrypt(curValue); + + $input.val(passEncrypted); + $input.attr("data-length", passEncrypted.length); + } + }; + + // Funciones para analizar al fortaleza de una clave + const outputResult = function (level, $target) { + log.info("outputResult"); + + const $passLevel = $(".passLevel-" + $target.attr("id")); + const score = level.score; + + $passLevel.show(); + $passLevel.removeClass("weak good strong strongest"); + + if (passwordData.passLength === 0) { + $passLevel.attr("title", "").empty(); + } else if (passwordData.passLength < passwordData.minPasswordLength) { + $passLevel.attr("title", config.LANG[11]).addClass("weak"); + } else if (score === 0) { + $passLevel.attr("title", config.LANG[9] + " - " + level.feedback.warning).addClass("weak"); + } else if (score === 1 || score === 2) { + $passLevel.attr("title", config.LANG[8] + " - " + level.feedback.warning).addClass("good"); + } else if (score === 3) { + $passLevel.attr("title", config.LANG[7]).addClass("strong"); + } else if (score === 4) { + $passLevel.attr("title", config.LANG[10]).addClass("strongest"); + } + }; + + // From http://net.tutsplus.com/tutorials/javascript-ajax/build-a-simple-password-strength-checker/ + const checkPassLevel = function ($target) { + log.info("checkPassLevel"); + + passwordData.passLength = $target.val().length; + + outputResult(zxcvbn($target.val()), $target); + }; + + // Función para habilitar la subida de archivos en una zona o formulario + const fileUpload = function ($obj) { + + // Inicializar el formulario de archivos en modo compatibilidad + const initForm = function (display) { + const $form = $("#fileUploadForm"); + + if (display === false) { + $form.hide(); + } + + const $input = $form.find("input[type='file']"); + + $input.on("change", function () { + if (typeof options.beforeSendAction === "function") { + options.beforeSendAction(); + } + + handleFiles(this.files); + }); + + return $input; + }; + + const requestData = { + actionId: $obj.data("action-id"), + itemId: $obj.data("item-id"), + sk: sk.get() + }; + + const options = { + requestDoneAction: "", + setRequestData: function (data) { + $.extend(requestData, data); + }, + getRequestData: function () { + return requestData; + }, + beforeSendAction: "", + url: "" + }; + + // Subir un archivo + const sendFile = function (file) { + if (options.url === undefined || options.url === "") { + return false; + } + + // Objeto FormData para crear datos de un formulario + const fd = new FormData(); + fd.append("inFile", file); + fd.append("isAjax", 1); + + requestData.sk = sk.get(); + + Object.keys(requestData).forEach(function (key) { + fd.append(key, requestData[key]); + }); + + const opts = appRequests.getRequestOpts(); + opts.url = options.url; + opts.processData = false; + opts.contentType = false; + opts.data = fd; + + appRequests.getActionCall(opts, function (json) { + const status = json.status; + const description = json.description; + + if (status === 0) { + if (typeof options.requestDoneAction === "function") { + options.requestDoneAction(); + } + + msg.ok(description); + } else if (status === 10) { + appActions.main.logout(); + } else { + msg.error(description); + } + }); + + }; + + const checkFileSize = function (size) { + return (size / 1000 > config.MAX_FILE_SIZE); + }; + + const checkFileExtension = function (name) { + const file_exts_ok = $obj.data("files-ext").toLowerCase().split(","); + + for (let i = 0; i <= file_exts_ok.length; i++) { + if (name.indexOf(file_exts_ok[i]) !== -1) { + return true; + } + } + + return false; + }; + + // Comprobar los archivos y subirlos + const handleFiles = function (filesArray) { + if (filesArray.length > 5) { + msg.error(config.LANG[17] + " (Max: 5)"); + return; + } + + for (let i = 0; i < filesArray.length; i++) { + const file = filesArray[i]; + if (checkFileSize(file.size)) { + msg.error(config.LANG[18] + "
" + file.name + " (Max: " + config.MAX_FILE_SIZE + ")"); + } else if (!checkFileExtension(file.name)) { + msg.error(config.LANG[19] + "
" + file.name); + } else { + sendFile(filesArray[i]); + } + } + }; + + // Inicializar la zona de subida de archivos Drag&Drop + const init = function () { + log.info("fileUpload:init"); + + const fallback = initForm(false); + + $obj.on("dragover dragenter", function (e) { + log.info("fileUpload:drag"); + + e.stopPropagation(); + e.preventDefault(); + }); + + $obj.on("drop", function (e) { + log.info("fileUpload:drop"); + + e.stopPropagation(); + e.preventDefault(); + + if (typeof options.beforeSendAction === "function") { + options.beforeSendAction(); + } + + handleFiles(e.originalEvent.dataTransfer.files); + }); + + $obj.on("click", function () { + fallback.click(); + }); + }; + + + if (window.File && window.FileList && window.FileReader) { + init(); + } else { + initForm(true); + } + + return options; + }; + const redirect = function (url) { + window.location.replace(url); + }; + + // Función para comprobar si se ha salido de la sesión + const checkLogout = function () { + log.info("checkLogout"); + + if (parseInt(getUrlVars("r")) === "login/logout") { + msg.sticky(config.LANG[61], function () { + redirect("index.php?r=login"); + }); + + return true; + } + + return false; + }; + + // Función para retornar el scroll a la posición inicial + const scrollUp = function () { + $("html, body").animate({scrollTop: 0}, "slow"); + }; + + // Función para establecer la altura del contenedor ajax + const setContentSize = function () { + const $container = $("#container"); + + if ($container.hasClass("content-no-auto-resize")) { + return; + } + + //console.info($("#content").height()); + + // Calculate total height for full body resize + $container.css("height", $("#content").height() + 200); + }; + + // Objeto para leer/escribir el token de seguridad + const sk = { + get: function () { + log.info("sk:get"); + return $("#container").attr("data-sk"); + }, + set: function (sk) { + log.info("sk:set"); + log.debug(sk); + + $("#container").attr("data-sk", sk); + + state.sk = sk; + } + }; + // Configuración de atributos generales - var config = { + const config = { APP_ROOT: "", // Base para llamadas AJAX LANG: [], // Array de lenguaje PK: "", // Clave pública @@ -42,7 +560,7 @@ sysPass.Main = function () { }; // Atributos del generador de claves - var passwordData = { + const passwordData = { passLength: 0, minPasswordLength: 8, complexity: { @@ -54,31 +572,35 @@ sysPass.Main = function () { } }; + const state = { + sk: "" + }; + Object.seal(passwordData); // Objeto con las funciones propias del tema visual - var appTheme = {}; + let appTheme = {}; // Objeto con los triggers de la aplicación - var appTriggers = {}; + let appTriggers = {}; // Objeto con las acciones de la aplicación - var appActions = {}; + let appActions = {}; // Objeto con las funciones para peticiones de la aplicación - var appRequests = {}; + let appRequests = {}; // Objeto con los plugins habilitados - var appPlugins = {}; + const appPlugins = {}; // Objeto con las propiedades públicas - var oPublic = {}; + let oPublic = {}; // Objeto con las propiedades protegidas - var oProtected = {}; + let oProtected = {}; // Logging - var log = { + const log = { log: function (msg) { if (config.DEBUG === true) { console.log(msg); @@ -126,10 +648,10 @@ sysPass.Main = function () { /** * Retrollamadas de los elementos */ - var setupCallbacks = function () { + const setupCallbacks = function () { log.info("setupCallbacks"); - var page = $("#container").data("page"); + const page = $("#container").data("page"); if (page !== "" && typeof appTriggers.views[page] === "function") { appTriggers.views[page](); @@ -147,7 +669,7 @@ sysPass.Main = function () { }; // Mostrar mensaje de aviso - var msg = { + const msg = { ok: function (msg) { toastr.success(msg); }, @@ -161,7 +683,7 @@ sysPass.Main = function () { toastr.info(msg); }, sticky: function (msg, callback) { - var opts = {timeOut: 0}; + const opts = {timeOut: 0}; if (typeof callback === "function") { opts.onHidden = callback; @@ -171,8 +693,8 @@ sysPass.Main = function () { }, out: function (data) { if (typeof data === "object") { - var status = data.status; - var description = data.description; + const status = data.status; + let description = data.description; if (data.messages !== undefined && data.messages.length > 0) { description = description + "
" + data.messages.join("
"); @@ -221,17 +743,62 @@ sysPass.Main = function () { if (!String.format) { String.format = function (format) { - var args = Array.prototype.slice.call(arguments, 1); + const args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] !== "undefined" ? args[number] : match; }); }; } + /** + * Obtener las variables de entorno de sysPass + */ + const getEnvironment = function () { + log.info("getEnvironment"); + + const path = window.location.pathname.split("/"); + const rootPath = function () { + let fullPath = ""; + + for (let i = 1; i <= path.length - 2; i++) { + fullPath += "/" + path[i]; + } + + return fullPath; + }; + + config.APP_ROOT = window.location.protocol + "//" + window.location.host + rootPath(); + + const opts = appRequests.getRequestOpts(); + opts.url = "/index.php?r=bootstrap/getEnvironment"; + opts.method = "get"; + // opts.async = false; + opts.useLoading = false; + opts.data = {isAjax: 1}; + + return appRequests.getActionCall(opts, function (json) { + // config.APP_ROOT = json.app_root; + config.LANG = json.lang; + config.PK = json.pk; + config.CHECK_UPDATES = json.check_updates; + config.CRYPT.setPublicKey(json.pk); + config.TIMEZONE = json.timezone; + config.LOCALE = json.locale; + config.DEBUG = json.debug; + config.MAX_FILE_SIZE = parseInt(json.max_file_size); + config.COOKIES_ENABLED = json.cookies_enabled; + config.PLUGINS = json.plugins; + config.LOGGEDIN = json.loggedin; + config.AUTHBASIC_AUTOLOGIN = json.authbasic_autologin; + + Object.freeze(config); + }); + }; + /** * Inicialización */ - var init = function () { + const init = function () { log.info("init"); // Objeto con métodos y propiedades públicas @@ -328,94 +895,12 @@ sysPass.Main = function () { return oPublic; }; - /** - * Obtener las variables de entorno de sysPass - */ - var getEnvironment = function () { - log.info("getEnvironment"); - - var path = window.location.pathname.split("/"); - var rootPath = function () { - var fullPath = ""; - - for (var i = 1; i <= path.length - 2; i++) { - fullPath += "/" + path[i]; - } - - return fullPath; - }; - - config.APP_ROOT = window.location.protocol + "//" + window.location.host + rootPath(); - - var opts = appRequests.getRequestOpts(); - opts.url = "/index.php?r=bootstrap/getEnvironment"; - opts.method = "get"; - // opts.async = false; - opts.useLoading = false; - opts.data = {isAjax: 1}; - - return appRequests.getActionCall(opts, function (json) { - // config.APP_ROOT = json.app_root; - config.LANG = json.lang; - config.PK = json.pk; - config.CHECK_UPDATES = json.check_updates; - config.CRYPT.setPublicKey(json.pk); - config.TIMEZONE = json.timezone; - config.LOCALE = json.locale; - config.DEBUG = json.debug; - config.MAX_FILE_SIZE = parseInt(json.max_file_size); - config.COOKIES_ENABLED = json.cookies_enabled; - config.PLUGINS = json.plugins; - config.LOGGEDIN = json.loggedin; - config.AUTHBASIC_AUTOLOGIN = json.authbasic_autologin; - - Object.freeze(config); - }); - }; - - // Objeto para leer/escribir el token de seguridad - var sk = { - current: "", - get: function () { - log.info("sk:get"); - return $("#container").attr("data-sk"); - }, - set: function (sk) { - log.info("sk:set"); - $("#container").attr("data-sk", sk); - - sk.current = sk; - } - }; - - // Función para establecer la altura del contenedor ajax - var setContentSize = function () { - var $container = $("#container"); - - if ($container.hasClass("content-no-auto-resize")) { - return; - } - - //console.info($("#content").height()); - - // Calculate total height for full body resize - var totalHeight = $("#content").height() + 200; - //var totalWidth = $("#wrap").width(); - - $container.css("height", totalHeight); - }; - - // Función para retornar el scroll a la posición inicial - var scrollUp = function () { - $("html, body").animate({scrollTop: 0}, "slow"); - }; - // Función para obtener las variables de la URL y parsearlas a un array. - var getUrlVars = function (param) { - var vars = [], hash; - var hashes = window.location.href.slice(window.location.href.indexOf("?") + 1).split("&"); - for (var i = 0; i < hashes.length; i++) { + const getUrlVars = function (param) { + let vars = [], hash; + const hashes = window.location.href.slice(window.location.href.indexOf("?") + 1).split("&"); + for (let i = 0; i < hashes.length; i++) { hash = hashes[i].split("="); vars.push(hash[0]); vars[hash[0]] = hash[1]; @@ -424,495 +909,12 @@ sysPass.Main = function () { return param !== undefined && vars[param] !== undefined ? vars[param] : vars; }; - // Función para comprobar si se ha salido de la sesión - var checkLogout = function () { - log.info("checkLogout"); - - if (parseInt(getUrlVars("r")) === "login/logout") { - msg.sticky(config.LANG[61], function () { - redirect("index.php?r=login"); - }); - - return true; - } - - return false; - }; - - var redirect = function (url) { - window.location.replace(url); - }; - - // Función para habilitar la subida de archivos en una zona o formulario - var fileUpload = function ($obj) { - var requestData = { - actionId: $obj.data("action-id"), - itemId: $obj.data("item-id"), - sk: sk.get() - }; - - var options = { - requestDoneAction: "", - setRequestData: function (data) { - $.extend(requestData, data); - }, - getRequestData: function () { - return requestData; - }, - beforeSendAction: "", - url: "" - }; - - // Subir un archivo - var sendFile = function (file) { - if (options.url === undefined || options.url === "") { - return false; - } - - // Objeto FormData para crear datos de un formulario - var fd = new FormData(); - fd.append("inFile", file); - fd.append("isAjax", 1); - - requestData.sk = sk.get(); - - Object.keys(requestData).forEach(function (key) { - fd.append(key, requestData[key]); - }); - - var opts = appRequests.getRequestOpts(); - opts.url = options.url; - opts.processData = false; - opts.contentType = false; - opts.data = fd; - - appRequests.getActionCall(opts, function (json) { - var status = json.status; - var description = json.description; - - if (status === 0) { - if (typeof options.requestDoneAction === "function") { - options.requestDoneAction(); - } - - msg.ok(description); - } else if (status === 10) { - appActions.main.logout(); - } else { - msg.error(description); - } - }); - - }; - - var checkFileSize = function (size) { - return (size / 1000 > config.MAX_FILE_SIZE); - }; - - var checkFileExtension = function (name) { - var file_exts_ok = $obj.data("files-ext").toLowerCase().split(","); - - for (var i = 0; i <= file_exts_ok.length; i++) { - if (name.indexOf(file_exts_ok[i]) !== -1) { - return true; - } - } - - return false; - }; - - // Comprobar los archivos y subirlos - var handleFiles = function (filesArray) { - if (filesArray.length > 5) { - msg.error(config.LANG[17] + " (Max: 5)"); - return; - } - - for (var i = 0; i < filesArray.length; i++) { - var file = filesArray[i]; - if (checkFileSize(file.size)) { - msg.error(config.LANG[18] + "
" + file.name + " (Max: " + config.MAX_FILE_SIZE + ")"); - } else if (!checkFileExtension(file.name)) { - msg.error(config.LANG[19] + "
" + file.name); - } else { - sendFile(filesArray[i]); - } - } - }; - - // Inicializar la zona de subida de archivos Drag&Drop - var init = function () { - log.info("fileUpload:init"); - - var fallback = initForm(false); - - $obj.on("dragover dragenter", function (e) { - log.info("fileUpload:drag"); - - e.stopPropagation(); - e.preventDefault(); - }); - - $obj.on("drop", function (e) { - log.info("fileUpload:drop"); - - e.stopPropagation(); - e.preventDefault(); - - if (typeof options.beforeSendAction === "function") { - options.beforeSendAction(); - } - - handleFiles(e.originalEvent.dataTransfer.files); - }); - - $obj.on("click", function () { - fallback.click(); - }); - }; - - // Inicializar el formulario de archivos en modo compatibilidad - var initForm = function (display) { - var $form = $("#fileUploadForm"); - - if (display === false) { - $form.hide(); - } - - var $input = $form.find("input[type='file']"); - - $input.on("change", function () { - if (typeof options.beforeSendAction === "function") { - options.beforeSendAction(); - } - - handleFiles(this.files); - }); - - return $input; - }; - - - if (window.File && window.FileList && window.FileReader) { - init(); - } else { - initForm(true); - } - - return options; - }; - // Función para obtener el tiempo actual en milisegundos - var getTime = function () { - var t = new Date(); + const getTime = function () { + const t = new Date(); return t.getTime(); }; - // Funciones para analizar al fortaleza de una clave - // From http://net.tutsplus.com/tutorials/javascript-ajax/build-a-simple-password-strength-checker/ - var checkPassLevel = function ($target) { - log.info("checkPassLevel"); - - passwordData.passLength = $target.val().length; - - outputResult(zxcvbn($target.val()), $target); - }; - - var outputResult = function (level, $target) { - log.info("outputResult"); - - var $passLevel = $(".passLevel-" + $target.attr("id")); - var score = level.score; - - $passLevel.show(); - $passLevel.removeClass("weak good strong strongest"); - - if (passwordData.passLength === 0) { - $passLevel.attr("title", "").empty(); - } else if (passwordData.passLength < passwordData.minPasswordLength) { - $passLevel.attr("title", config.LANG[11]).addClass("weak"); - } else if (score === 0) { - $passLevel.attr("title", config.LANG[9] + " - " + level.feedback.warning).addClass("weak"); - } else if (score === 1 || score === 2) { - $passLevel.attr("title", config.LANG[8] + " - " + level.feedback.warning).addClass("good"); - } else if (score === 3) { - $passLevel.attr("title", config.LANG[7]).addClass("strong"); - } else if (score === 4) { - $passLevel.attr("title", config.LANG[10]).addClass("strongest"); - } - }; - - /** - * Encriptar el valor de un campo del formulario - * - * @param $input El id del campo - */ - var encryptFormValue = function ($input) { - log.info("encryptFormValue"); - - var curValue = $input.val(); - - if (curValue !== "" && parseInt($input.attr("data-length")) !== curValue.length) { - var passEncrypted = config.CRYPT.encrypt(curValue); - - $input.val(passEncrypted); - $input.attr("data-length", passEncrypted.length); - } - }; - - /** - * Inicializar portapapeles - */ - var initializeClipboard = function () { - log.info("initializeClipboard"); - - if (!clipboard.isSupported()) { - log.warn(config.LANG[65]); - return; - } - - $("body").on("click", ".clip-pass-button", function () { - var json = appActions.account.copyPass($(this)).done(function (json) { - if (json.status !== 0) { - msg.out(json); - - return false; - } - - sk.set(json.csrf); - }); - - if (json !== false) { - clipboard.copy(json.responseJSON.data.accpass).then( - function () { - msg.ok(config.LANG[45]); - }, - function (err) { - msg.error(config.LANG[46]); - } - ); - } - }).on("click", ".dialog-clip-button", function () { - var $target = $(this.dataset.clipboardTarget); - - clipboard.copy($target.text()).then( - function () { - $(".dialog-text").removeClass("dialog-clip-copy"); - $target.addClass("dialog-clip-copy"); - }, - function (err) { - msg.error(config.LANG[46]); - } - ); - }).on("click", ".clip-pass-icon", function () { - var $target = $(this.dataset.clipboardTarget); - - clipboard.copy(decodeEntities($target.val())).then( - function () { - msg.ok(config.LANG[45]); - }, - function (err) { - msg.error(config.LANG[46]); - } - ); - }); - }; - - /** - * Delegar los eventos 'blur' y 'keypress' para que los campos de claves - * sean encriptados antes de ser enviados por el formulario - */ - var bindPassEncrypt = function () { - log.info("bindPassEncrypt"); - - $("body").on("blur", ":input[type=password]", function (e) { - var $this = $(this); - - if ($this.hasClass("passwordfield__no-pki")) { - return; - } - - encryptFormValue($this); - }).on("keypress", ":input[type=password]", function (e) { - if (e.keyCode === 13) { - e.preventDefault(); - - var $this = $(this); - encryptFormValue($this); - - var $form = $this.closest("form"); - $form.submit(); - } - }); - }; - - /** - * Evaluar una acción javascript y ejecutar la función - * - * @param evalFn - * @param $obj - */ - var evalAction = function (evalFn, $obj) { - log.info("Eval: " + evalFn); - - if (typeof evalFn === "function") { - evalFn($obj); - } else { - throw Error("Function not found: " + evalFn); - } - }; - - /** - * Redimensionar una imagen al viewport - * - * @param $obj - */ - var resizeImage = function ($obj) { - log.info("resizeImage"); - - var viewport = { - width: $(window).width() * 0.90, - height: $(window).height() * 0.90 - }; - var image = { - width: $obj.width(), - height: $obj.height() - }; - var dimension = { - calc: 0, - main: 0, - secondary: 0, - factor: 0.90, - rel: image.width / image.height - }; - - /** - * Ajustar la relación de aspecto de la imagen. - * - * Se tiene en cuenta la dimensión máxima en el eje opuesto. - * - * @param dimension - * @returns {*} - */ - var adjustRel = function (dimension) { - if (dimension.main > dimension.secondary) { - dimension.calc = dimension.main / dimension.rel; - } else if (dimension.main < dimension.secondary) { - dimension.calc = dimension.main * dimension.rel; - } - - if (dimension.calc > dimension.secondary) { - dimension.main *= dimension.factor; - - adjustRel(dimension); - } - - return dimension; - }; - - /** - * Redimensionar en relación a la anchura - */ - var resizeWidth = function () { - dimension.main = viewport.width; - dimension.secondary = viewport.height; - - var adjust = adjustRel(dimension); - - $obj.css({ - "width": adjust.main, - "height": adjust.calc - }); - - image.width = adjust.main; - image.height = adjust.calc; - }; - - /** - * Redimensionar en relación a la altura - */ - var resizeHeight = function () { - dimension.main = viewport.height; - dimension.secondary = viewport.width; - - var adjust = adjustRel(dimension); - - $obj.css({ - "width": adjust.calc, - "height": adjust.main - }); - - image.width = adjust.calc; - image.height = adjust.main; - }; - - if (image.width > viewport.width) { - resizeWidth(); - } else if (image.height > viewport.height) { - log.info("height"); - resizeHeight(); - } - - return image; - }; - - /** - * @author http://stackoverflow.com/users/24950/robert-k - * @link http://stackoverflow.com/questions/5796718/html-entity-decode - */ - var decodeEntities = (function () { - // this prevents any overhead from creating the object each time - var element = document.createElement("div"); - - function decodeHTMLEntities(str) { - if (str && typeof str === "string") { - // strip script/html tags - str = str.replace(/]*>([\S\s]*?)<\/script>/gmi, ""); - str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, ""); - element.innerHTML = str; - str = element.textContent; - element.textContent = ""; - } - - return str; - } - - return decodeHTMLEntities; - })(); - - /** - * Inicializar los plugins - */ - var initPlugins = function () { - log.info("initPlugins"); - - for (var i = 0; i < config.PLUGINS.length; i++) { - var plugin = config.PLUGINS[i]; - - if (typeof sysPass.Plugin[plugin] === "function") { - appPlugins[plugin] = sysPass.Plugin[plugin](oProtected); - } - } - - Object.freeze(appPlugins); - }; - - /** - * Comprobar si hay actualizaciones de plugins - */ - var checkPluginUpdates = function () { - log.info("checkPluginUpdates"); - - for (var plugin in appPlugins) { - if (typeof appPlugins[plugin].checkVersion === "function") { - appPlugins[plugin].checkVersion().then(function (json) { - if (json.status === 0 && json.data.plugin !== undefined) { - msg.info(String.format(config.LANG[67], json.data.plugin, json.data.remoteVersion)); - } - }); - } - } - }; return init(); }; \ No newline at end of file diff --git a/public/js/app-main.min.js b/public/js/app-main.min.js index a6f1cd54..5ba76f92 100644 --- a/public/js/app-main.min.js +++ b/public/js/app-main.min.js @@ -1,25 +1,25 @@ -var $jscomp={scope:{}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(b,h,e){if(e.get||e.set)throw new TypeError("ES3 does not support getters and setters.");b!=Array.prototype&&b!=Object.prototype&&(b[h]=e.value)};$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_"; -$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(b){return $jscomp.SYMBOL_PREFIX+(b||"")+$jscomp.symbolCounter_++}; -$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var b=$jscomp.global.Symbol.iterator;b||(b=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[b]&&$jscomp.defineProperty(Array.prototype,b,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(b){var h=0;return $jscomp.iteratorPrototype(function(){return h"+a.messages.join("
")); -switch(b){case 0:f.ok(d);break;case 1:f.error(d);break;case 2:f.warn(d);break;case 10:l.main.logout();break;case 100:f.ok(d);f.sticky(d);break;case 101:f.error(d);f.sticky(d);break;case 102:f.warn(d);f.sticky(d);break;default:f.error(d)}}},html:{error:function(a){return'

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

"}}};Object.freeze(f);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 y=function(){g.info("getEnvironment");var a=window.location.pathname.split("/");b.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 c=m.getRequestOpts();c.url="/index.php?r=bootstrap/getEnvironment";c.method="get";c.useLoading=!1;c.data={isAjax:1};return m.getActionCall(c,function(a){b.LANG=a.lang;b.PK=a.pk;b.CHECK_UPDATES=a.check_updates;b.CRYPT.setPublicKey(a.pk);b.TIMEZONE=a.timezone; -b.LOCALE=a.locale;b.DEBUG=a.debug;b.MAX_FILE_SIZE=parseInt(a.max_file_size);b.COOKIES_ENABLED=a.cookies_enabled;b.PLUGINS=a.plugins;b.LOGGEDIN=a.loggedin;b.AUTHBASIC_AUTOLOGIN=a.authbasic_autologin;Object.freeze(b)})},r={current:"",get:function(){g.info("sk:get");return $("#container").attr("data-sk")},set:function(a){g.info("sk:set");$("#container").attr("data-sk",a);a.current=a}},z=function(){var a=$("#container");if(!a.hasClass("content-no-auto-resize")){var b=$("#content").height()+200;a.css("height", -b)}},A=function(){$("html, body").animate({scrollTop:0},"slow")},B=function(a){for(var b=[],d,f=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),g=0;gb.MAX_FILE_SIZE)f.error(b.LANG[18]+"
"+t.name+" (Max: "+b.MAX_FILE_SIZE+")");else{var g;a:{g=t.name;for(var h=a.data("files-ext").toLowerCase().split(","),e=0;e<=h.length;e++)if(-1!==g.indexOf(h[e])){g=!0;break a}g=!1}g?k(c[d]):f.error(b.LANG[19]+"
"+t.name)}}},e=function(a){var b= -$("#fileUploadForm");!1===a&&b.hide();a=b.find("input[type='file']");a.on("change",function(){"function"===typeof d.beforeSendAction&&d.beforeSendAction();h(this.files)});return a};window.File&&window.FileList&&window.FileReader?function(){g.info("fileUpload:init");var b=e(!1);a.on("dragover dragenter",function(a){g.info("fileUpload:drag");a.stopPropagation();a.preventDefault()});a.on("drop",function(a){g.info("fileUpload:drop");a.stopPropagation();a.preventDefault();"function"===typeof d.beforeSendAction&& -d.beforeSendAction();h(a.originalEvent.dataTransfer.files)});a.on("click",function(){b.click()})}():e(!0);return d},E=function(a){g.info("checkPassLevel");h.passLength=a.val().length;w(zxcvbn(a.val()),a)},w=function(a,c){g.info("outputResult");var d=$(".passLevel-"+c.attr("id")),e=a.score;d.show();d.removeClass("weak good strong strongest");0===h.passLength?d.attr("title","").empty():h.passLengtha.secondary?a.calc=a.main/a.rel:a.maina.secondary&&(a.main*=a.factor,h(a));return a},k=function(){f.main=b;f.secondary=d;var c=h(f);a.css({width:c.main,height:c.calc});e.width=c.main;e.height= -c.calc},l=function(){f.main=d;f.secondary=b;var c=h(f);a.css({width:c.calc,height:c.main});e.width=c.calc;e.height=c.main};e.width>b?k():e.height>d&&(g.info("height"),l());return e},F=function(){var a=document.createElement("div");return function(b){b&&"string"===typeof b&&(b=b.replace(/]*>([\S\s]*?)<\/script>/gmi,""),b=b.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi,""),a.innerHTML=b,b=a.textContent,a.textContent="");return b}}(),K=function(){g.info("checkPluginUpdates");for(var a in p)"function"=== -typeof p[a].checkVersion&&p[a].checkVersion().then(function(a){0===a.status&&void 0!==a.data.plugin&&f.info(String.format(b.LANG[67],a.data.plugin,a.data.remoteVersion))})};return function(){g.info("init");q={actions:function(){return l},triggers:function(){return k},theme:function(){return e},sk:r,msg:f,log:g,passwordData:h,outputResult:w,checkPassLevel:E,encryptFormValue:v,fileUpload:D,redirect:u,scrollUp:A,setContentSize:z};n=$.extend({log:g,config:function(){return b},appTheme:function(){return e}, -appActions:function(){return l},appTriggers:function(){return k},appRequests:function(){return m},appPlugins:function(){return p},evalAction:I,resizeImage:J},q);Object.freeze(q);Object.freeze(n);k=sysPass.Triggers(n);l=sysPass.Actions(n);m=sysPass.Requests(n);"function"===typeof sysPass.Theme&&(e=sysPass.Theme(n));y().then(function(){if(!C()&&(""!==b.PK&&H(),!0===b.CHECK_UPDATES&&l.main.getUpdates(),!1===b.COOKIES_ENABLED&&f.sticky(b.LANG[64]),G(),x(),0]*>([\S\s]*?)<\/script>/gmi,""),g=g.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi,""),a.innerHTML=g,g=a.textContent, +a.textContent="");return g}}(),l=function(a){f.info("resizeImage");var g=.9*$(window).width(),d=.9*$(window).height(),b={width:a.width(),height:a.height()},c={calc:0,main:0,secondary:0,factor:.9,rel:b.width/b.height},e=function(a){a.main>a.secondary?a.calc=a.main/a.rel:a.maina.secondary&&(a.main*=a.factor,e(a));return a},D=function(){c.main=g;c.secondary=d;var h=e(c);a.css({width:h.main,height:h.calc});b.width=h.main;b.height=h.calc},E=function(){c.main= +d;c.secondary=g;var h=e(c);a.css({width:h.calc,height:h.main});b.width=h.calc;b.height=h.main};b.width>g?D():b.height>d&&(f.info("height"),E());return b},m=function(a,b){f.info("Eval: "+a);if("function"===typeof a)a(b);else throw Error("Function not found: "+a);},n=function(){f.info("bindPassEncrypt");$("body").on("blur",":input[type=password]",function(a){a=$(this);a.hasClass("passwordfield__no-pki")||z(a)}).on("keypress",":input[type=password]",function(a){13===a.keyCode&&(a.preventDefault(),a= +$(this),z(a),a.closest("form").submit())})},w=function(){f.info("initializeClipboard");if(clipboard.isSupported())$("body").on("click",".clip-pass-button",function(){var a=p.account.copyPass($(this)).done(function(a){if(0!==a.status)return e.out(a),!1;x.set(a.csrf)});!1!==a&&clipboard.copy(a.responseJSON.data.accpass).then(function(){e.ok(c.LANG[45])},function(a){e.error(c.LANG[46])})}).on("click",".dialog-clip-button",function(){var a=$(this.dataset.clipboardTarget);clipboard.copy(a.text()).then(function(){$(".dialog-text").removeClass("dialog-clip-copy"); +a.addClass("dialog-clip-copy")},function(a){e.error(c.LANG[46])})}).on("click",".clip-pass-icon",function(){var a=$(this.dataset.clipboardTarget);clipboard.copy(k(a.val())).then(function(){e.ok(c.LANG[45])},function(a){e.error(c.LANG[46])})});else f.warn(c.LANG[65])},z=function(a){f.info("encryptFormValue");var b=a.val();""!==b&&parseInt(a.attr("data-length"))!==b.length&&(b=c.CRYPT.encrypt(b),a.val(b),a.attr("data-length",b.length))},C=function(a,b){f.info("outputResult");var d=$(".passLevel-"+b.attr("id")), +g=a.score;d.show();d.removeClass("weak good strong strongest");0===u.passLength?d.attr("title","").empty():u.passLengthc.MAX_FILE_SIZE)e.error(c.LANG[18]+ +"
"+g.name+" (Max: "+c.MAX_FILE_SIZE+")");else{var h;a:{h=g.name;for(var f=a.data("files-ext").toLowerCase().split(","),k=0;k<=f.length;k++)if(-1!==h.indexOf(f[k])){h=!0;break a}h=!1}h?l(b[d]):e.error(c.LANG[19]+"
"+g.name)}}};window.File&&window.FileList&&window.FileReader?function(){f.info("fileUpload:init");var d=b(!1);a.on("dragover dragenter",function(a){f.info("fileUpload:drag");a.stopPropagation();a.preventDefault()});a.on("drop",function(a){f.info("fileUpload:drop");a.stopPropagation(); +a.preventDefault();"function"===typeof h.beforeSendAction&&h.beforeSendAction();k(a.originalEvent.dataTransfer.files)});a.on("click",function(){d.click()})}():b(!0);return h},A=function(a){window.location.replace(a)},I=function(){f.info("checkLogout");return"login/logout"===parseInt(H("r"))?(e.sticky(c.LANG[61],function(){A("index.php?r=login")}),!0):!1},J=function(){$("html, body").animate({scrollTop:0},"slow")},K=function(){var a=$("#container");a.hasClass("content-no-auto-resize")||a.css("height", +$("#content").height()+200)},x={get:function(){f.info("sk:get");return $("#container").attr("data-sk")},set:function(a){f.info("sk:set");f.debug(a);$("#container").attr("data-sk",a)}},c={APP_ROOT:"",LANG:[],PK:"",MAX_FILE_SIZE:1024,CRYPT:new JSEncrypt,CHECK_UPDATES:!1,TIMEZONE:"",LOCALE:"",DEBUG:"",COOKIES_ENABLED:!1,PLUGINS:[],LOGGEDIN:!1,AUTHBASIC_AUTOLOGIN:!1},u={passLength:0,minPasswordLength:8,complexity:{chars:!0,numbers:!0,symbols:!0,uppercase:!0,numlength:12}};Object.seal(u);var B={},q={}, +p={},v={},t={},y={},r={},f={log:function(a){!0===c.DEBUG&&console.log(a)},info:function(a){!0===c.DEBUG&&console.info(a)},error:function(a){console.error(a)},warn:function(a){console.warn(a)},debug:function(a){!0===c.DEBUG&&console.debug(a)}};Object.freeze(f);toastr.options={closeButton:!0,debug:!1,newestOnTop:!1,progressBar:!1,positionClass:"toast-top-center",preventDuplicates:!1,onclick:null,showDuration:"300",hideDuration:"1000",timeOut:"5000",extendedTimeOut:"1000",showEasing:"swing",hideEasing:"linear", +showMethod:"fadeIn",hideMethod:"fadeOut"};var L=function(){f.info("setupCallbacks");var a=$("#container").data("page");if(""!==a&&"function"===typeof q.views[a])q.views[a]();0<$("footer").length&&q.views.footer();$("#btnBack").click(function(){A("index.php")});q.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:p.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;Object.freeze(c)})},H=function(a){for(var b=[],c,e=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),f=0;f 0 && _history[_history.length - 1].hash === hash) { return _history; @@ -102,7 +102,7 @@ sysPass.Requests = function (Common) { * * @returns {requestOpts} */ - var getRequestOpts = function () { + const getRequestOpts = function () { return Object.create(requestOpts); }; @@ -112,7 +112,7 @@ sysPass.Requests = function (Common) { * @param url * @returns {*} */ - var getUrl = function (url) { + const getUrl = function (url) { return (url.indexOf("http") === -1 && url.indexOf("https") === -1) ? Common.config().APP_ROOT + url : url; }; @@ -123,7 +123,7 @@ sysPass.Requests = function (Common) { * @param callbackOk * @param callbackError */ - var getActionCall = function (opts, callbackOk, callbackError) { + const getActionCall = function (opts, callbackOk, callbackError) { log.info("getActionCall"); return $.ajax({ @@ -156,7 +156,7 @@ sysPass.Requests = function (Common) { }, error: function (jqXHR, textStatus, errorThrown) { if (typeof callbackError !== "function") { - var txt = Common.config().LANG[1] + "

" + errorThrown + textStatus + "

"; + const txt = Common.config().LANG[1] + "

" + errorThrown + textStatus + "

"; log.error(txt); @@ -189,15 +189,15 @@ sysPass.Requests = function (Common) { * @param callbackProgress * @param callbackEnd */ - var getActionEvent = function (opts, callbackProgress, callbackEnd) { - var url = getUrl(opts.url); + const getActionEvent = function (opts, callbackProgress, callbackEnd) { + let url = getUrl(opts.url); url += "?" + $.param(opts.data); - var source = new EventSource(url); + const source = new EventSource(url); //a message is received source.addEventListener("message", function (e) { - var result = JSON.parse(e.data); + const result = JSON.parse(e.data); log.debug(result); @@ -230,7 +230,7 @@ sysPass.Requests = function (Common) { * @param query * @returns {{r: string}} */ - var getRouteForQuery = function (route, query) { + const getRouteForQuery = function (route, query) { if (typeof query === "object") { return {r: route + "/" + query.join("/")}; } diff --git a/public/js/app-triggers.js b/public/js/app-triggers.js index bcadc0ed..3e5ffaee 100644 --- a/public/js/app-triggers.js +++ b/public/js/app-triggers.js @@ -24,23 +24,23 @@ sysPass.Triggers = function (Common) { "use strict"; - var log = Common.log; + const log = Common.log; // Detectar los campos select y añadir funciones - var selectDetect = function ($container) { - var options = { + const selectDetect = function ($container) { + const options = { valueField: "id", labelField: "name", searchField: ["name"] }; $container.find(".select-box").each(function (e) { - var $this = $(this); + const $this = $(this); options.plugins = $this.hasClass("select-box-deselect") ? {"clear_selection": {title: Common.config().LANG[51]}} : {}; if ($this.data("onchange")) { - var onchange = $this.data("onchange").split("/"); + const onchange = $this.data("onchange").split("/"); options.onChange = function (value) { if (value > 0) { @@ -78,13 +78,13 @@ sysPass.Triggers = function (Common) { * Ejecutar acción para botones * @param $obj */ - var handleActionButton = function ($obj) { + const handleActionButton = function ($obj) { log.info("handleActionButton: " + $obj.attr("id")); - var onclick = $obj.data("onclick").split("/"); - var actions; + const onclick = $obj.data("onclick").split("/"); + let actions; - var plugin = $obj.data("plugin"); + const plugin = $obj.data("plugin"); if (plugin !== undefined && Common.appPlugins()[plugin] !== undefined) { actions = Common.appPlugins()[plugin]; @@ -104,19 +104,19 @@ sysPass.Triggers = function (Common) { * * @param $obj */ - var handleFormAction = function ($obj) { + const handleFormAction = function ($obj) { log.info("formAction"); - var lastHash = $obj.attr("data-hash"); - var currentHash = SparkMD5.hash($obj.serialize(), false); + const lastHash = $obj.attr("data-hash"); + const currentHash = SparkMD5.hash($obj.serialize(), false); if (lastHash === currentHash) { Common.msg.ok(Common.config().LANG[55]); return false; } - var plugin = $obj.data("plugin"); - var actions; + const plugin = $obj.data("plugin"); + let actions; if (plugin !== undefined && Common.appPlugins()[plugin] !== undefined) { actions = Common.appPlugins()[plugin]; @@ -124,7 +124,7 @@ sysPass.Triggers = function (Common) { actions = Common.appActions(); } - var onsubmit = $obj.data("onsubmit").split("/"); + const onsubmit = $obj.data("onsubmit").split("/"); $obj.find("input[name='sk']").val(Common.sk.get()); @@ -135,18 +135,18 @@ sysPass.Triggers = function (Common) { } }; - var bodyHooks = function () { + const bodyHooks = function () { log.info("bodyHooks"); $("body").on("click", "button.btn-action[data-onclick][type='button'],li.btn-action[data-onclick],span.btn-action[data-onclick],i.btn-action[data-onclick],.btn-action-pager[data-onclick]", function () { handleActionButton($(this)); }).on("click", ".btn-back", function () { - var appRequests = Common.appRequests(); + const appRequests = Common.appRequests(); if (appRequests.history.length() > 0) { log.info("back"); - var lastHistory = appRequests.history.del(); + const lastHistory = appRequests.history.del(); appRequests.getActionCall(lastHistory, lastHistory.callback); } @@ -155,8 +155,8 @@ sysPass.Triggers = function (Common) { handleFormAction($(this)); }).on("click", ".btn-help", function () { - var $this = $(this); - var helpText = $("#" + $this.data("help")).html(); + const $this = $(this); + const helpText = $("#" + $this.data("help")).html(); mdlDialog().show({ title: Common.config().LANG[54], @@ -170,7 +170,7 @@ sysPass.Triggers = function (Common) { log.info("reset"); - var $this = $(this); + const $this = $(this); $this.find("input:text, input:password, input:file, textarea").val("").parent("div").removeClass("is-dirty"); $this.find("input:radio, input:checkbox").prop("checked", false).prop("selected", false); @@ -189,7 +189,7 @@ sysPass.Triggers = function (Common) { /** * Triggers que se ejecutan en determinadas vistas */ - var views = { + const views = { main: function () { log.info("views:main"); @@ -198,7 +198,7 @@ sysPass.Triggers = function (Common) { } $(".btn-menu").click(function () { - var $this = $(this); + const $this = $(this); if ($this.attr("data-history-reset") === "1") { Common.appRequests().history.reset(); @@ -224,7 +224,7 @@ sysPass.Triggers = function (Common) { search: function () { log.info("views:search"); - var $frmSearch = $("#frmSearch"); + const $frmSearch = $("#frmSearch"); if ($frmSearch.length === 0) { return; @@ -253,7 +253,7 @@ sysPass.Triggers = function (Common) { $frmSearch.find("input:text:visible:first").focus(); $("#globalSearch").click(function () { - var val = $(this).prop("checked") == true ? 1 : 0; + const val = $(this).prop("checked") == true ? 1 : 0; $frmSearch.find("input[name='gsearch']").val(val); $frmSearch.submit(); @@ -267,7 +267,7 @@ sysPass.Triggers = function (Common) { login: function () { log.info("views:login"); - var $frmLogin = $("#frmLogin"); + const $frmLogin = $("#frmLogin"); if (Common.config().AUTHBASIC_AUTOLOGIN && $frmLogin.find("input[name='loggedOut']").val() === "0") { log.info("views:login:autologin"); @@ -280,7 +280,7 @@ sysPass.Triggers = function (Common) { passreset: function () { log.info("views:passreset"); - var $form = $("#frmPassReset"); + const $form = $("#frmPassReset"); Common.appTheme().passwordDetect($form); }, @@ -293,6 +293,12 @@ sysPass.Triggers = function (Common) { selectDetect($container); + const $sk = $container.find(":input [name='sk']"); + + if ($sk.length > 0) { + Common.sk.set($sk.val()); + } + // $container.find(".help-box").dialog({ // autoOpen: false, // title: Common.config().LANG[54], @@ -305,11 +311,11 @@ sysPass.Triggers = function (Common) { Common.appTriggers().updateFormHash($container); }, - datatabs: function (active) { + datatabs: function () { log.info("views:datatabs"); $(".datagrid-action-search>form").each(function () { - var $this = $(this); + const $this = $(this); $this.find("button.btn-clear").on("click", function (e) { e.preventDefault(); @@ -321,10 +327,10 @@ sysPass.Triggers = function (Common) { config: function () { log.info("views:config"); - var $dropFiles = $("#drop-import-files"); + const $dropFiles = $("#drop-import-files"); if ($dropFiles.length > 0) { - var upload = Common.fileUpload($dropFiles); + const upload = Common.fileUpload($dropFiles); upload.url = Common.appActions().ajaxUrl.config.import; upload.beforeSendAction = function () { @@ -342,16 +348,16 @@ sysPass.Triggers = function (Common) { account: function () { log.info("views:account"); - var $listFiles = $("#list-account-files"); + const $listFiles = $("#list-account-files"); if ($listFiles.length > 0) { Common.appActions().account.listFiles($listFiles); } - var $dropFiles = $("#drop-account-files"); + const $dropFiles = $("#drop-account-files"); if ($dropFiles.length > 0) { - var upload = Common.fileUpload($dropFiles); + const upload = Common.fileUpload($dropFiles); upload.url = Common.appActions().ajaxUrl.file; upload.requestDoneAction = function () { @@ -359,12 +365,12 @@ sysPass.Triggers = function (Common) { }; } - var $extraInfo = $(".show-extra-info"); + const $extraInfo = $(".show-extra-info"); if ($extraInfo.length > 0) { $extraInfo.on("click", function () { - var $this = $(this); - var $target = $($this.data("target")); + const $this = $(this); + const $target = $($this.data("target")); if ($target.is(":hidden")) { $target.slideDown("slow"); @@ -376,12 +382,12 @@ sysPass.Triggers = function (Common) { }); } - var $selParentAccount = $("#selParentAccount"); + const $selParentAccount = $("#selParentAccount"); if ($selParentAccount.length > 0) { $selParentAccount.on("change", function () { - var $this = $(this); - var $pass = $("#accountpass,#accountpassR"); + const $this = $(this); + const $pass = $("#accountpass,#accountpassR"); if ($this[0].value > 0) { $pass.each(function () { @@ -398,11 +404,70 @@ sysPass.Triggers = function (Common) { Common.appActions().items.get($selParentAccount); } + + const $selTags = $("#selTags"); + + if ($selTags.length > 0) { + $selTags.selectize({ + persist: false, + maxItems: null, + valueField: "id", + labelField: "name", + searchField: ["name"], + plugins: ["remove_button"] + }); + } + + const $otherUsers = $('#otherUsers'); + + if ($otherUsers.length > 0) { + $otherUsers.selectize({ + persist: false, + valueField: 'id', + labelField: 'name', + searchField: ['name'], + plugins: ['remove_button'], + onInitialize: function () { + const userId = $otherUsers.data('userId'); + + if (userId > 0) { + this.removeOption(userId); + } + } + }); + } + + const $otherUserGroups = $('#otherUserGroups'); + + if ($otherUserGroups.length > 0) { + $otherUserGroups.selectize({ + persist: false, + valueField: 'id', + labelField: 'name', + searchField: ['name'], + plugins: ['remove_button'], + onInitialize: function () { + const userGroupId = $otherUserGroups.data('userGroupId'); + + if (userGroupId > 0) { + this.removeOption(userGroupId); + } + } + }); + } + + const $accesses = $("#data-accesses"); + + if ($accesses.length > 0 && $accesses[0].childNodes.length === 1) { + $accesses.parent(".data").hide(); + } + + $('input:text:visible:first').focus(); }, install: function () { log.info("views:install"); - var $form = $("#frmInstall"); + const $form = $("#frmInstall"); Common.appTheme().passwordDetect($form); selectDetect($form); @@ -413,7 +478,7 @@ sysPass.Triggers = function (Common) { * Actualizar el token de seguridad en los atributos de los botones y formularios * */ - var updateSk = function () { + const updateSk = function () { $("#content").find("[data-sk]").each(function () { log.info("updateSk"); @@ -424,10 +489,10 @@ sysPass.Triggers = function (Common) { /** * Actualizar el hash de los formularios de acción */ - var updateFormHash = function ($container) { + const updateFormHash = function ($container) { log.info("updateFormHash"); - var $form; + let $form; if ($container !== undefined) { $form = $container.find(".form-action[data-hash]"); @@ -437,7 +502,7 @@ sysPass.Triggers = function (Common) { if ($form.length > 0) { $form.each(function () { - var $this = $(this); + const $this = $(this); $this.attr("data-hash", SparkMD5.hash($this.serialize(), false)); }); diff --git a/public/js/app-triggers.min.js b/public/js/app-triggers.min.js index c6ee792c..874b0772 100644 --- a/public/js/app-triggers.min.js +++ b/public/js/app-triggers.min.js @@ -1,15 +1,17 @@ var $jscomp={scope:{},findInternal:function(b,d,f){b instanceof String&&(b=String(b));for(var a=b.length,c=0;cform").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(){d.info("views:config");var a=$("#drop-import-files");if(0. + */ + +sysPass.Util = function (Common) { + "use strict"; + +}; \ No newline at end of file diff --git a/public/js/app.js b/public/js/app.js index 4f1c015c..59455307 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -24,13 +24,15 @@ // // From http://www.kenneth-truyers.net/2013/04/27/javascript-namespaces-and-modules/ // -var sysPass = sysPass || {}; +const sysPass = {}; // create a general purpose namespace method // this will allow us to create namespace a bit easier sysPass.createNS = function (namespace) { - var nsparts = namespace.split("."); - var parent = sysPass; + "use strict"; + + let nsparts = namespace.split("."); + let parent = sysPass; // we want to be able to include or exclude the root namespace // So we strip it if it's in the namespace @@ -40,8 +42,8 @@ sysPass.createNS = function (namespace) { // loop through the parts and create // a nested namespace if necessary - for (var i = 0; i < nsparts.length; i++) { - var partname = nsparts[i]; + for (let i = 0; i < nsparts.length; i++) { + const partname = nsparts[i]; // check if the current parent already has // the namespace declared, if not create it if (typeof parent[partname] === "undefined") { @@ -62,9 +64,10 @@ sysPass.createNS("Actions"); sysPass.createNS("Requests"); sysPass.createNS("Theme"); sysPass.createNS("Plugin"); +sysPass.createNS("Util"); // Objeto con las funciones públicas de sysPass -var sysPassApp = {}; +let sysPassApp = {}; $(document).on("DOMContentLoaded", function (e) { "use strict"; diff --git a/public/js/app.min.js b/public/js/app.min.js index 9f22bd72..0a7fb951 100644 --- a/public/js/app.min.js +++ b/public/js/app.min.js @@ -1 +1 @@ -var sysPass=sysPass||{};sysPass.createNS=function(a){a=a.split(".");var b=sysPass;"sysPass"===a[0]&&(a=a.slice(1));for(var c=0;c
@@ -260,40 +262,23 @@ - - isShowFiles()): ?> - includeTemplate('files'); ?> - + isShowFiles()) { + include $this->includeTemplate('files'); + } - 0): ?> - includeTemplate('linkedAccounts'); ?> - + // Linked accounts box + if ($gotData && count($linkedAccounts) > 0) { + include $this->includeTemplate('linkedAccounts'); + } - - isShowDetails()): ?> - includeTemplate('details'); ?> - + // Details box + if ($gotData && $accountAcl->isShowDetails()) { + include $this->includeTemplate('details'); + } - includeTemplate('actions'); ?> - - + // Actions box + include $this->includeTemplate('actions'); + ?> + \ No newline at end of file diff --git a/app/modules/web/themes/material-blue/views/account/details.inc b/app/modules/web/themes/material-blue/views/account/details.inc index c6a2524f..b6868ca1 100644 --- a/app/modules/web/themes/material-blue/views/account/details.inc +++ b/app/modules/web/themes/material-blue/views/account/details.inc @@ -57,7 +57,7 @@ getUserGroupName(); ?>
@@ -66,9 +66,10 @@ id !== $accountData->getUserId()) { - $users[] = $otherUser->name; + /** @var \SP\Mvc\View\Components\SelectItem[] $otherUsers */ + foreach ($otherUsers as $otherUser) { + if (!$otherUser->isSkip() && $otherUser->isSelected()) { + $users[] = $otherUser->getName(); } } @@ -78,25 +79,24 @@
id !== $accountData->getUserGroupId()) { - $groups[] = $otherGroup->name; + /** @var \SP\Mvc\View\Components\SelectItem[] $otherUserGroups */ + foreach ($otherUserGroups as $otherUserGroup) { + if (!$otherUserGroup->isSkip() && $otherUserGroup->isSelected()) { + $userGroups[] = $otherUserGroup->getName(); } } - $groupsEdit = $accountData->getOtherUserGroupEdit() ? '(+)' : ''; - - echo $groupsEdit . ' ' . implode(' | ', $groups); + $userGroupsEdit = $accountData->getOtherUserGroupEdit() ? '(+)' : ''; + echo $userGroupsEdit . ' ' . implode(' | ', $userGroups); ?>