diff --git a/app/modules/web/Controllers/User/CreateController.php b/app/modules/web/Controllers/User/CreateController.php new file mode 100644 index 00000000..0c0187db --- /dev/null +++ b/app/modules/web/Controllers/User/CreateController.php @@ -0,0 +1,72 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + + +use Exception; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Events\Event; +use SP\Http\JsonResponse; +use SP\Modules\Web\Controllers\Traits\JsonTrait; + +/** + * Class CreateController + */ +final class CreateController extends UserViewBase +{ + use JsonTrait; + + /** + * @return bool + * @throws \JsonException + */ + public function createAction(): bool + { + try { + if (!$this->acl->checkUserAccess(ActionsInterface::USER_CREATE)) { + return $this->returnJsonResponse( + JsonResponse::JSON_ERROR, + __u('You don\'t have permission to do this operation') + ); + } + + $this->view->assign('header', __('New User')); + $this->view->assign('isView', false); + $this->view->assign('route', 'user/saveCreate'); + + $this->setViewData(); + + $this->eventDispatcher->notifyEvent('show.user.create', new Event($this)); + + return $this->returnJsonResponseData(['html' => $this->render()]); + } catch (Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', new Event($e)); + + return $this->returnJsonResponseException($e); + } + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/User/DeleteController.php b/app/modules/web/Controllers/User/DeleteController.php new file mode 100644 index 00000000..f9201782 --- /dev/null +++ b/app/modules/web/Controllers/User/DeleteController.php @@ -0,0 +1,103 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + + +use Exception; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Events\Event; +use SP\Core\Events\EventMessage; +use SP\Http\JsonResponse; +use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Mvc\Controller\ItemTrait; + +/** + * Class DeleteController + */ +final class DeleteController extends UserSaveBase +{ + use JsonTrait, ItemTrait; + + /** + * Delete action + * + * @param int|null $id + * + * @return bool + * @throws \JsonException + */ + public function deleteAction(?int $id = null): bool + { + try { + if (!$this->acl->checkUserAccess(ActionsInterface::USER_DELETE)) { + return $this->returnJsonResponse( + JsonResponse::JSON_ERROR, + __u('You don\'t have permission to do this operation') + ); + } + + if ($id === null) { + $this->userService->deleteByIdBatch($this->getItemsIdFromRequest($this->request)); + + $this->eventDispatcher->notifyEvent( + 'delete.user.selection', + new Event( + $this, + EventMessage::factory() + ->addDescription(__u('Users deleted')) + ->setExtra('userId', $this->getItemsIdFromRequest($this->request)) + ) + ); + + $this->deleteCustomFieldsForItem(ActionsInterface::USER, $id, $this->customFieldService); + + return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Users deleted')); + } + + $this->userService->delete($id); + + $this->deleteCustomFieldsForItem(ActionsInterface::USER, $id, $this->customFieldService); + + $this->eventDispatcher->notifyEvent( + 'delete.user', + new Event( + $this, + EventMessage::factory() + ->addDescription(__u('User deleted')) + ->addDetail(__u('User'), $id) + ->addExtra('userId', $id) + ) + ); + + return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('User deleted')); + } catch (Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', new Event($e)); + + return $this->returnJsonResponseException($e); + } + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/User/EditController.php b/app/modules/web/Controllers/User/EditController.php new file mode 100644 index 00000000..3955c54b --- /dev/null +++ b/app/modules/web/Controllers/User/EditController.php @@ -0,0 +1,76 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + + +use Exception; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Events\Event; +use SP\Http\JsonResponse; +use SP\Modules\Web\Controllers\Traits\JsonTrait; + +/** + * Class EditController + */ +final class EditController extends UserViewBase +{ + use JsonTrait; + + /** + * Edit action + * + * @param int $id + * + * @return bool + * @throws \JsonException + */ + public function editAction(int $id): bool + { + try { + if (!$this->acl->checkUserAccess(ActionsInterface::USER_EDIT)) { + return $this->returnJsonResponse( + JsonResponse::JSON_ERROR, + __u('You don\'t have permission to do this operation') + ); + } + + $this->view->assign('header', __('Edit User')); + $this->view->assign('isView', false); + $this->view->assign('route', 'user/saveEdit/'.$id); + + $this->setViewData($id); + + $this->eventDispatcher->notifyEvent('show.user.edit', new Event($this)); + + return $this->returnJsonResponseData(['html' => $this->render()]); + } catch (Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', new Event($e)); + + return $this->returnJsonResponseException($e); + } + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/User/EditPassController.php b/app/modules/web/Controllers/User/EditPassController.php new file mode 100644 index 00000000..c58e26b9 --- /dev/null +++ b/app/modules/web/Controllers/User/EditPassController.php @@ -0,0 +1,84 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + + +use Exception; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Events\Event; +use SP\DataModel\UserData; +use SP\Http\JsonResponse; +use SP\Modules\Web\Controllers\Traits\JsonTrait; + +/** + * Class EditPassController + */ +final class EditPassController extends UserViewBase +{ + use JsonTrait; + + /** + * Edit user's pass action + * + * @param int $id + * + * @return bool + * @throws \JsonException + */ + public function editPassAction(int $id): bool + { + try { + // Comprobar si el usuario a modificar es distinto al de la sesión + if (!$this->acl->checkUserAccess(ActionsInterface::USER_EDIT_PASS, $id)) { + return $this->returnJsonResponse( + JsonResponse::JSON_ERROR, + __u('You don\'t have permission to do this operation') + ); + } + + $this->view->addTemplate('user_pass', 'itemshow'); + + $this->view->assign('header', __('Password Change')); + $this->view->assign('isView', false); + $this->view->assign('route', 'user/saveEditPass/'.$id); + + $user = $id + ? $this->userService->getById($id) + : new UserData(); + + $this->view->assign('user', $user); + + $this->eventDispatcher->notifyEvent('show.user.editPass', new Event($this)); + + return $this->returnJsonResponseData(['html' => $this->render()]); + } catch (Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', new Event($e)); + + return $this->returnJsonResponseException($e); + } + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/User/SaveCreateController.php b/app/modules/web/Controllers/User/SaveCreateController.php new file mode 100644 index 00000000..3853cd19 --- /dev/null +++ b/app/modules/web/Controllers/User/SaveCreateController.php @@ -0,0 +1,89 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + + +use Exception; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Events\Event; +use SP\Core\Events\EventMessage; +use SP\Core\Exceptions\ValidationException; +use SP\Http\JsonResponse; +use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Mvc\Controller\ItemTrait; + +/** + * Class SaveCreateController + */ +final class SaveCreateController extends UserSaveBase +{ + use JsonTrait, ItemTrait; + + /** + * @return bool + * @throws \JsonException + */ + public function saveCreateAction() + { + try { + if (!$this->acl->checkUserAccess(ActionsInterface::USER_CREATE)) { + return $this->returnJsonResponse( + JsonResponse::JSON_ERROR, + __u('You don\'t have permission to do this operation') + ); + } + + $this->form->validateFor(ActionsInterface::USER_CREATE); + + $itemData = $this->form->getItemData(); + + $id = $this->userService->create($itemData); + + $this->eventDispatcher->notifyEvent( + 'create.user', + new Event( + $this, + EventMessage::factory() + ->addDescription(__u('User added')) + ->addDetail(__u('User'), $itemData->getName()) + ) + ); + + $this->addCustomFieldsForItem(ActionsInterface::USER, $id, $this->request, $this->customFieldService); + + $this->checkChangeUserPass($id, $itemData); + + return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('User added')); + } catch (ValidationException $e) { + return $this->returnJsonResponseException($e); + } catch (Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', new Event($e)); + + return $this->returnJsonResponseException($e); + } + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/User/SaveEditController.php b/app/modules/web/Controllers/User/SaveEditController.php new file mode 100644 index 00000000..bd4ca347 --- /dev/null +++ b/app/modules/web/Controllers/User/SaveEditController.php @@ -0,0 +1,94 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + + +use Exception; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Events\Event; +use SP\Core\Events\EventMessage; +use SP\Core\Exceptions\ValidationException; +use SP\Http\JsonResponse; +use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Mvc\Controller\ItemTrait; + +/** + * Class SaveEditController + */ +final class SaveEditController extends UserSaveBase +{ + use JsonTrait, ItemTrait; + + /** + * Saves edit action + * + * @param int $id + * + * @return bool + * @throws \JsonException + */ + public function saveEditAction(int $id): bool + { + try { + if (!$this->acl->checkUserAccess(ActionsInterface::USER_EDIT)) { + return $this->returnJsonResponse( + JsonResponse::JSON_ERROR, + __u('You don\'t have permission to do this operation') + ); + } + + $this->form->validateFor(ActionsInterface::USER_EDIT, $id); + + $itemData = $this->form->getItemData(); + + $this->userService->update($itemData); + + $this->eventDispatcher->notifyEvent( + 'edit.user', + new Event( + $this, + EventMessage::factory() + ->addDescription(__u('User updated')) + ->addDetail(__u('User'), $itemData->getName()) + ->addExtra('userId', $id) + ) + ); + + $this->updateCustomFieldsForItem(ActionsInterface::USER, $id, $this->request, $this->customFieldService); + + $this->checkChangeUserPass($id, $itemData); + + return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('User updated')); + } catch (ValidationException $e) { + return $this->returnJsonResponseException($e); + } catch (Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', new Event($e)); + + return $this->returnJsonResponseException($e); + } + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/User/SaveEditPassController.php b/app/modules/web/Controllers/User/SaveEditPassController.php new file mode 100644 index 00000000..d9f215b9 --- /dev/null +++ b/app/modules/web/Controllers/User/SaveEditPassController.php @@ -0,0 +1,89 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + + +use Exception; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Events\Event; +use SP\Core\Events\EventMessage; +use SP\Core\Exceptions\ValidationException; +use SP\Http\JsonResponse; +use SP\Modules\Web\Controllers\Traits\JsonTrait; + +/** + * Class SaveEditPassController + */ +final class SaveEditPassController extends UserSaveBase +{ + use JsonTrait; + + /** + * Saves edit action + * + * @param int $id + * + * @return bool + * @throws \JsonException + */ + public function saveEditPassAction(int $id): bool + { + try { + if (!$this->acl->checkUserAccess(ActionsInterface::USER_EDIT_PASS, $id)) { + return $this->returnJsonResponse( + JsonResponse::JSON_ERROR, + __u('You don\'t have permission to do this operation') + ); + } + + $this->form->validateFor(ActionsInterface::USER_EDIT_PASS, $id); + + $itemData = $this->form->getItemData(); + + $this->userService->updatePass($id, $itemData->getPass()); + + $this->eventDispatcher->notifyEvent( + 'edit.user.pass', + new Event( + $this, + EventMessage::factory() + ->addDescription(__u('Password updated')) + ->addDetail(__u('User'), $id) + ) + ); + + return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Password updated')); + } catch (ValidationException $e) { + return $this->returnJsonResponseException($e); + } catch (Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', new Event($e)); + + return $this->returnJsonResponseException($e); + } + } + +} \ No newline at end of file diff --git a/app/modules/web/Controllers/User/SearchController.php b/app/modules/web/Controllers/User/SearchController.php new file mode 100644 index 00000000..ecefd2c9 --- /dev/null +++ b/app/modules/web/Controllers/User/SearchController.php @@ -0,0 +1,106 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + + +use SP\Core\Acl\ActionsInterface; +use SP\Core\Application; +use SP\Domain\User\UserServiceInterface; +use SP\Html\DataGrid\DataGridInterface; +use SP\Http\JsonResponse; +use SP\Modules\Web\Controllers\ControllerBase; +use SP\Modules\Web\Controllers\Helpers\Grid\UserGrid; +use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Mvc\Controller\ItemTrait; +use SP\Mvc\Controller\WebControllerHelper; + +/** + * Class SearchController + */ +final class SearchController extends ControllerBase +{ + use JsonTrait, ItemTrait; + + private UserServiceInterface $userService; + private UserGrid $userGrid; + + public function __construct( + Application $application, + WebControllerHelper $webControllerHelper, + UserServiceInterface $userService, + UserGrid $userGrid + ) { + parent::__construct($application, $webControllerHelper); + + $this->checkLoggedIn(); + + $this->userService = $userService; + $this->userGrid = $userGrid; + } + + /** + * Search action + * + * @return bool + * @throws \JsonException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function searchAction(): bool + { + if (!$this->acl->checkUserAccess(ActionsInterface::USER_SEARCH)) { + return $this->returnJsonResponse( + JsonResponse::JSON_ERROR, + __u('You don\'t have permission to do this operation') + ); + } + + $this->view->addTemplate('datagrid-table', 'grid'); + $this->view->assign('index', $this->request->analyzeInt('activetab', 0)); + $this->view->assign('data', $this->getSearchGrid()); + + return $this->returnJsonResponseData(['html' => $this->render()]); + } + + /** + * getSearchGrid + * + * @return \SP\Html\DataGrid\DataGridInterface + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + protected function getSearchGrid(): DataGridInterface + { + $itemSearchData = $this->getSearchData( + $this->configData->getAccountCount(), + $this->request + ); + + return $this->userGrid->updatePager( + $this->userGrid->getGrid($this->userService->search($itemSearchData)), + $itemSearchData + ); + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/User/UserSaveBase.php b/app/modules/web/Controllers/User/UserSaveBase.php new file mode 100644 index 00000000..f5d7e090 --- /dev/null +++ b/app/modules/web/Controllers/User/UserSaveBase.php @@ -0,0 +1,91 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + + +use SP\Core\Application; +use SP\DataModel\UserData; +use SP\Domain\CustomField\CustomFieldServiceInterface; +use SP\Domain\Notification\MailServiceInterface; +use SP\Domain\User\Services\UserPassRecoverService; +use SP\Domain\User\UserPassRecoverServiceInterface; +use SP\Domain\User\UserServiceInterface; +use SP\Modules\Web\Controllers\ControllerBase; +use SP\Modules\Web\Forms\UserForm; +use SP\Mvc\Controller\WebControllerHelper; + +/** + * Class UserSaveBase + */ +abstract class UserSaveBase extends ControllerBase +{ + protected UserServiceInterface $userService; + protected CustomFieldServiceInterface $customFieldService; + protected UserForm $form; + private MailServiceInterface $mailService; + private UserPassRecoverServiceInterface $userPassRecoverService; + + public function __construct( + Application $application, + WebControllerHelper $webControllerHelper, + UserServiceInterface $userService, + CustomFieldServiceInterface $customFieldService, + MailServiceInterface $mailService, + UserPassRecoverServiceInterface $userPassRecoverService + ) { + parent::__construct($application, $webControllerHelper); + + $this->checkLoggedIn(); + + $this->userService = $userService; + $this->customFieldService = $customFieldService; + $this->mailService = $mailService; + $this->userPassRecoverService = $userPassRecoverService; + $this->form = new UserForm($application, $this->request); + } + + /** + * @param int $userId + * @param UserData $userData + * + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + * @throws \PHPMailer\PHPMailer\Exception + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Domain\Common\Services\ServiceException + */ + final protected function checkChangeUserPass(int $userId, UserData $userData): void + { + if ($userData->isChangePass()) { + $hash = $this->userPassRecoverService->requestForUserId($userId); + + $this->mailService->send( + __('Password Change'), + $userData->getEmail(), + UserPassRecoverService::getMailMessage($hash) + ); + } + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/User/UserViewBase.php b/app/modules/web/Controllers/User/UserViewBase.php new file mode 100644 index 00000000..cf082c97 --- /dev/null +++ b/app/modules/web/Controllers/User/UserViewBase.php @@ -0,0 +1,149 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + + +use SP\Core\Acl\Acl; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Application; +use SP\DataModel\UserData; +use SP\Domain\CustomField\CustomFieldServiceInterface; +use SP\Domain\User\UserGroupServiceInterface; +use SP\Domain\User\UserProfileServiceInterface; +use SP\Domain\User\UserServiceInterface; +use SP\Modules\Web\Controllers\ControllerBase; +use SP\Mvc\Controller\ItemTrait; +use SP\Mvc\Controller\WebControllerHelper; +use SP\Mvc\View\Components\SelectItemAdapter; + +/** + * Class UserViewBase + */ +abstract class UserViewBase extends ControllerBase +{ + use ItemTrait; + + protected UserServiceInterface $userService; + private UserGroupServiceInterface $userGroupService; + private UserProfileServiceInterface $userProfileService; + private CustomFieldServiceInterface $customFieldService; + + public function __construct( + Application $application, + WebControllerHelper $webControllerHelper, + UserServiceInterface $userService, + UserGroupServiceInterface $userGroupService, + UserProfileServiceInterface $userProfileService, + CustomFieldServiceInterface $customFieldService + ) { + parent::__construct($application, $webControllerHelper); + + $this->checkLoggedIn(); + + $this->userService = $userService; + $this->userGroupService = $userGroupService; + $this->userProfileService = $userProfileService; + $this->customFieldService = $customFieldService; + } + + /** + * Sets view data for displaying user's data + * + * @param int|null $userId + * + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\SPException + * @throws \SP\Domain\Common\Services\ServiceException + */ + protected function setViewData(?int $userId = null): void + { + $this->view->addTemplate('user', 'itemshow'); + + $user = $userId + ? $this->userService->getById($userId) + : new UserData(); + + $this->view->assign('user', $user); + $this->view->assign( + 'groups', + SelectItemAdapter::factory($this->userGroupService->getAllBasic())->getItemsFromModel() + ); + $this->view->assign( + 'profiles', + SelectItemAdapter::factory($this->userProfileService->getAllBasic())->getItemsFromModel() + ); + $this->view->assign('isUseSSO', $this->configData->isAuthBasicAutoLoginEnabled()); + $this->view->assign( + 'mailEnabled', + $this->configData->isMailEnabled() + ); + $this->view->assign( + 'nextAction', + Acl::getActionRoute(ActionsInterface::ACCESS_MANAGE) + ); + + if ($this->view->isView === true + || ($this->configData->isDemoEnabled() + && $user->getLogin() === 'demo') + ) { + $this->view->assign('disabled', 'disabled'); + $this->view->assign('readonly', 'readonly'); + + $this->view->assign( + 'usage', + array_map( + static function ($value) { + switch ($value->ref) { + case 'Account': + $value->icon = 'description'; + break; + case 'UserGroup': + $value->icon = 'group'; + break; + case 'PublicLink': + $value->icon = 'link'; + break; + default: + $value->icon = 'info_outline'; + } + + return $value; + }, + $this->userService->getUsageForUser($userId) + ) + ); + } else { + $this->view->assign('disabled', false); + $this->view->assign('readonly', false); + } + + $this->view->assign('showViewCustomPass', $this->acl->checkUserAccess(ActionsInterface::CUSTOMFIELD_VIEW_PASS)); + $this->view->assign( + 'customFields', + $this->getCustomFieldsForItem(ActionsInterface::USER, $userId, $this->customFieldService) + ); + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/User/ViewController.php b/app/modules/web/Controllers/User/ViewController.php new file mode 100644 index 00000000..36e22b1a --- /dev/null +++ b/app/modules/web/Controllers/User/ViewController.php @@ -0,0 +1,76 @@ +. + */ + +namespace SP\Modules\Web\Controllers\User; + +use Exception; +use SP\Core\Acl\ActionsInterface; +use SP\Core\Events\Event; +use SP\Http\JsonResponse; +use SP\Modules\Web\Controllers\Traits\JsonTrait; + +/** + * Class ViewController + * + * @package SP\Modules\Web\Controllers + */ +final class ViewController extends UserViewBase +{ + use JsonTrait; + + /** + * View action + * + * @param int $id + * + * @return bool + * @throws \JsonException + */ + public function viewAction(int $id): bool + { + try { + if (!$this->acl->checkUserAccess(ActionsInterface::USER_VIEW)) { + return $this->returnJsonResponse( + JsonResponse::JSON_ERROR, + __u('You don\'t have permission to do this operation') + ); + } + + $this->view->assign('header', __('View User')); + $this->view->assign('isView', true); + + $this->setViewData($id); + + $this->eventDispatcher->notifyEvent('show.user', new Event($this)); + + return $this->returnJsonResponseData(['html' => $this->render()]); + } catch (Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', new Event($e)); + + return $this->returnJsonResponseException($e); + } + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/UserController.php b/app/modules/web/Controllers/UserController.php deleted file mode 100644 index 31d0984d..00000000 --- a/app/modules/web/Controllers/UserController.php +++ /dev/null @@ -1,679 +0,0 @@ -. - */ - -namespace SP\Modules\Web\Controllers; - -use DI\DependencyException; -use DI\NotFoundException; -use Exception; -use Psr\Container\ContainerExceptionInterface; -use SP\Core\Acl\Acl; -use SP\Core\Acl\ActionsInterface; -use SP\Core\Events\Event; -use SP\Core\Events\EventMessage; -use SP\Core\Exceptions\ConstraintException; -use SP\Core\Exceptions\QueryException; -use SP\Core\Exceptions\SessionTimeout; -use SP\Core\Exceptions\SPException; -use SP\Core\Exceptions\ValidationException; -use SP\DataModel\UserData; -use SP\Domain\Auth\Services\AuthException; -use SP\Domain\Notification\Services\MailService; -use SP\Domain\User\Services\UserGroupService; -use SP\Domain\User\Services\UserPassRecoverService; -use SP\Domain\User\Services\UserProfileService; -use SP\Domain\User\Services\UserService; -use SP\Html\DataGrid\DataGridInterface; -use SP\Http\JsonResponse; -use SP\Modules\Web\Controllers\Helpers\Grid\UserGrid; -use SP\Modules\Web\Controllers\Traits\JsonTrait; -use SP\Modules\Web\Forms\UserForm; -use SP\Mvc\Controller\CrudControllerInterface; -use SP\Mvc\Controller\ItemTrait; -use SP\Mvc\View\Components\SelectItemAdapter; - -/** - * Class UserController - * - * @package SP\Modules\Web\Controllers - */ -final class UserController extends ControllerBase implements CrudControllerInterface -{ - use JsonTrait; - use ItemTrait; - - protected ?UserService $userService = null; - - /** - * Search action - * - * @return bool - * @throws \DI\DependencyException - * @throws \DI\NotFoundException - * @throws \JsonException - * @throws \SP\Core\Exceptions\ConstraintException - * @throws \SP\Core\Exceptions\QueryException - */ - public function searchAction(): bool - { - if (!$this->acl->checkUserAccess(ActionsInterface::USER_SEARCH)) { - return $this->returnJsonResponse( - JsonResponse::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->view->addTemplate('datagrid-table', 'grid'); - $this->view->assign( - 'index', - $this->request->analyzeInt('activetab', 0) - ); - $this->view->assign('data', $this->getSearchGrid()); - - return $this->returnJsonResponseData(['html' => $this->render()]); - } - - /** - * getSearchGrid - * - * @throws DependencyException - * @throws NotFoundException - * @throws ConstraintException - * @throws QueryException - */ - protected function getSearchGrid(): DataGridInterface - { - $itemSearchData = $this->getSearchData( - $this->configData->getAccountCount(), - $this->request - ); - - $userGrid = $this->dic->get(UserGrid::class); - - return $userGrid->updatePager( - $userGrid->getGrid($this->userService->search($itemSearchData)), - $itemSearchData - ); - } - - /** - * @return bool - * @throws \DI\DependencyException - * @throws \DI\NotFoundException - * @throws \JsonException - */ - public function createAction(): bool - { - try { - if (!$this->acl->checkUserAccess(ActionsInterface::USER_CREATE)) { - return $this->returnJsonResponse( - JsonResponse::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->view->assign('header', __('New User')); - $this->view->assign('isView', false); - $this->view->assign('route', 'user/saveCreate'); - - $this->setViewData(); - - $this->eventDispatcher->notifyEvent( - 'show.user.create', - new Event($this) - ); - - return $this->returnJsonResponseData(['html' => $this->render()]); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notifyEvent( - 'exception', - new Event($e) - ); - - return $this->returnJsonResponseException($e); - } - } - - /** - * Sets view data for displaying user's data - * - * @param int|null $userId - * - * @throws SPException - * @throws ContainerExceptionInterface - */ - protected function setViewData(?int $userId = null): void - { - $this->view->addTemplate('user', 'itemshow'); - - $user = $userId - ? $this->userService->getById($userId) - : new UserData(); - - $this->view->assign('user', $user); - $this->view->assign( - 'groups', - SelectItemAdapter::factory(UserGroupService::getItemsBasic()) - ->getItemsFromModel() - ); - $this->view->assign( - 'profiles', - SelectItemAdapter::factory(UserProfileService::getItemsBasic()) - ->getItemsFromModel() - ); - $this->view->assign( - 'isUseSSO', - $this->configData->isAuthBasicAutoLoginEnabled() - ); - $this->view->assign( - 'mailEnabled', - $this->configData->isMailEnabled() - ); - $this->view->assign( - 'nextAction', - Acl::getActionRoute(ActionsInterface::ACCESS_MANAGE) - ); - - if ($this->view->isView === true - || ($this->configData->isDemoEnabled() - && $user->getLogin() === 'demo') - ) { - $this->view->assign('disabled', 'disabled'); - $this->view->assign('readonly', 'readonly'); - - $this->view->assign( - 'usage', - array_map( - static function ($value) { - switch ($value->ref) { - case 'Account': - $value->icon = 'description'; - break; - case 'UserGroup': - $value->icon = 'group'; - break; - case 'PublicLink': - $value->icon = 'link'; - break; - default: - $value->icon = 'info_outline'; - } - - return $value; - }, - $this->userService->getUsageForUser($userId) - ) - ); - } else { - $this->view->assign('disabled', false); - $this->view->assign('readonly', false); - } - - $this->view->assign( - 'showViewCustomPass', - $this->acl->checkUserAccess(ActionsInterface::CUSTOMFIELD_VIEW_PASS) - ); - $this->view->assign( - 'customFields', - $this->getCustomFieldsForItem(ActionsInterface::USER, $userId) - ); - } - - /** - * Edit action - * - * @param int $id - * - * @return bool - * @throws \DI\DependencyException - * @throws \DI\NotFoundException - * @throws \JsonException - */ - public function editAction(int $id): bool - { - try { - if (!$this->acl->checkUserAccess(ActionsInterface::USER_EDIT)) { - return $this->returnJsonResponse( - JsonResponse::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->view->assign('header', __('Edit User')); - $this->view->assign('isView', false); - $this->view->assign('route', 'user/saveEdit/' . $id); - - $this->setViewData($id); - - $this->eventDispatcher->notifyEvent( - 'show.user.edit', - new Event($this) - ); - - return $this->returnJsonResponseData(['html' => $this->render()]); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notifyEvent( - 'exception', - new Event($e) - ); - - return $this->returnJsonResponseException($e); - } - } - - /** - * Edit user's pass action - * - * @param int $id - * - * @return bool - * @throws \DI\DependencyException - * @throws \DI\NotFoundException - * @throws \JsonException - */ - public function editPassAction(int $id): bool - { - try { - // Comprobar si el usuario a modificar es distinto al de la sesión - if (!$this->acl->checkUserAccess(ActionsInterface::USER_EDIT_PASS, $id)) { - return $this->returnJsonResponse( - JsonResponse::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->view->addTemplate('user_pass', 'itemshow'); - - $this->view->assign('header', __('Password Change')); - $this->view->assign('isView', false); - $this->view->assign('route', 'user/saveEditPass/' . $id); - - $user = $id - ? $this->userService->getById($id) - : new UserData(); - - $this->view->assign('user', $user); - - $this->eventDispatcher->notifyEvent( - 'show.user.editPass', - new Event($this) - ); - - return $this->returnJsonResponseData(['html' => $this->render()]); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notifyEvent( - 'exception', - new Event($e) - ); - - return $this->returnJsonResponseException($e); - } - } - - /** - * Delete action - * - * @param int|null $id - * - * @return bool - * @throws \DI\DependencyException - * @throws \DI\NotFoundException - * @throws \JsonException - */ - public function deleteAction(?int $id = null): bool - { - try { - if (!$this->acl->checkUserAccess(ActionsInterface::USER_DELETE)) { - return $this->returnJsonResponse( - JsonResponse::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - if ($id === null) { - $this->userService - ->deleteByIdBatch($this->getItemsIdFromRequest($this->request)); - - $this->eventDispatcher->notifyEvent( - 'delete.user.selection', - new Event( - $this, - EventMessage::factory() - ->addDescription(__u('Users deleted')) - ->setExtra('userId', $this->getItemsIdFromRequest($this->request)) - ) - ); - - $this->deleteCustomFieldsForItem( - ActionsInterface::USER, - $id - ); - - return $this->returnJsonResponse( - JsonResponse::JSON_SUCCESS, - __u('Users deleted') - ); - } - - $this->userService->delete($id); - - $this->deleteCustomFieldsForItem( - ActionsInterface::USER, - $id - ); - - $this->eventDispatcher->notifyEvent( - 'delete.user', - new Event( - $this, - EventMessage::factory() - ->addDescription(__u('User deleted')) - ->addDetail(__u('User'), $id) - ->addExtra('userId', $id) - ) - ); - - return $this->returnJsonResponse( - JsonResponse::JSON_SUCCESS, - __u('User deleted') - ); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notifyEvent( - 'exception', - new Event($e) - ); - - return $this->returnJsonResponseException($e); - } - } - - /** - * @return bool - * @throws \DI\DependencyException - * @throws \DI\NotFoundException - * @throws \JsonException - */ - public function saveCreateAction() - { - try { - if (!$this->acl->checkUserAccess(ActionsInterface::USER_CREATE)) { - return $this->returnJsonResponse( - JsonResponse::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $form = new UserForm($this->dic); - $form->validateFor(Acl::USER_CREATE, null); - - $itemData = $form->getItemData(); - - $id = $this->userService->create($itemData); - - $this->eventDispatcher->notifyEvent( - 'create.user', - new Event( - $this, - EventMessage::factory() - ->addDescription(__u('User added')) - ->addDetail(__u('User'), $itemData->getName()) - ) - ); - - $this->addCustomFieldsForItem( - ActionsInterface::USER, - $id, - $this->request - ); - - $this->checkChangeUserPass($id, $itemData); - - return $this->returnJsonResponse( - JsonResponse::JSON_SUCCESS, - __u('User added') - ); - } catch (ValidationException $e) { - return $this->returnJsonResponseException($e); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notifyEvent( - 'exception', - new Event($e) - ); - - return $this->returnJsonResponseException($e); - } - } - - /** - * @param int $userId - * @param UserData $userData - * - * @throws \DI\DependencyException - * @throws \DI\NotFoundException - * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException - * @throws \PHPMailer\PHPMailer\Exception - * @throws \SP\Core\Exceptions\ConstraintException - * @throws \SP\Core\Exceptions\QueryException - * @throws \SP\Domain\Common\Services\ServiceException - */ - protected function checkChangeUserPass(int $userId, UserData $userData): void - { - if ($userData->isChangePass()) { - $hash = $this->dic->get(UserPassRecoverService::class) - ->requestForUserId($userId); - - $this->dic->get(MailService::class) - ->send( - __('Password Change'), - $userData->getEmail(), - UserPassRecoverService::getMailMessage($hash) - ); - } - } - - /** - * Saves edit action - * - * @param int $id - * - * @return bool - * @throws \DI\DependencyException - * @throws \DI\NotFoundException - * @throws \JsonException - */ - public function saveEditAction(int $id): bool - { - try { - if (!$this->acl->checkUserAccess(ActionsInterface::USER_EDIT)) { - return $this->returnJsonResponse( - JsonResponse::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $form = new UserForm($this->dic, $id); - $form->validateFor(ActionsInterface::USER_EDIT, null); - - $itemData = $form->getItemData(); - - $this->userService->update($itemData); - - $this->eventDispatcher->notifyEvent( - 'edit.user', - new Event( - $this, - EventMessage::factory() - ->addDescription(__u('User updated')) - ->addDetail(__u('User'), $itemData->getName()) - ->addExtra('userId', $id) - ) - ); - - $this->updateCustomFieldsForItem( - ActionsInterface::USER, - $id, - $this->request - ); - - $this->checkChangeUserPass($id, $itemData); - - return $this->returnJsonResponse( - JsonResponse::JSON_SUCCESS, - __u('User updated') - ); - } catch (ValidationException $e) { - return $this->returnJsonResponseException($e); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notifyEvent( - 'exception', - new Event($e) - ); - - return $this->returnJsonResponseException($e); - } - } - - /** - * Saves edit action - * - * @param int $id - * - * @return bool - * @throws \DI\DependencyException - * @throws \DI\NotFoundException - * @throws \JsonException - */ - public function saveEditPassAction(int $id): bool - { - try { - if (!$this->acl->checkUserAccess(ActionsInterface::USER_EDIT_PASS, $id)) { - return $this->returnJsonResponse( - JsonResponse::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $form = new UserForm($this->dic, $id); - $form->validateFor(ActionsInterface::USER_EDIT_PASS, null); - - $itemData = $form->getItemData(); - - $this->userService->updatePass($id, $itemData->getPass()); - - $this->eventDispatcher->notifyEvent( - 'edit.user.pass', - new Event( - $this, - EventMessage::factory() - ->addDescription(__u('Password updated')) - ->addDetail(__u('User'), $id) - ) - ); - - return $this->returnJsonResponse( - JsonResponse::JSON_SUCCESS, - __u('Password updated') - ); - } catch (ValidationException $e) { - return $this->returnJsonResponseException($e); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notifyEvent( - 'exception', - new Event($e) - ); - - return $this->returnJsonResponseException($e); - } - } - - /** - * View action - * - * @param int $id - * - * @return bool - * @throws \DI\DependencyException - * @throws \DI\NotFoundException - * @throws \JsonException - */ - public function viewAction(int $id): bool - { - try { - if (!$this->acl->checkUserAccess(ActionsInterface::USER_VIEW)) { - return $this->returnJsonResponse( - JsonResponse::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->view->assign('header', __('View User')); - $this->view->assign('isView', true); - - $this->setViewData($id); - - $this->eventDispatcher->notifyEvent( - 'show.user', - new Event($this) - ); - - return $this->returnJsonResponseData(['html' => $this->render()]); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notifyEvent( - 'exception', - new Event($e) - ); - - return $this->returnJsonResponseException($e); - } - } - - /** - * @throws AuthException - * @throws DependencyException - * @throws NotFoundException - * @throws SessionTimeout - */ - protected function initialize(): void - { - $this->checkLoggedIn(); - - $this->userService = $this->dic->get(UserService::class); - } -} \ No newline at end of file diff --git a/app/modules/web/Forms/UserForm.php b/app/modules/web/Forms/UserForm.php index f474eddb..1dcb7ff6 100644 --- a/app/modules/web/Forms/UserForm.php +++ b/app/modules/web/Forms/UserForm.php @@ -25,6 +25,7 @@ namespace SP\Modules\Web\Forms; use SP\Core\Acl\ActionsInterface; +use SP\Core\Exceptions\SPException; use SP\Core\Exceptions\ValidationException; use SP\DataModel\UserData; @@ -180,8 +181,15 @@ final class UserForm extends FormBase implements FormInterface } } - public function getItemData(): ?UserData + /** + * @throws \SP\Core\Exceptions\SPException + */ + public function getItemData(): UserData { + if (null === $this->userData) { + throw new SPException(__u('User data not set')); + } + return $this->userData; }