vendor/pimcore/pimcore/bundles/AdminBundle/Controller/Admin/UserController.php line 1049

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Enterprise License (PEL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  * @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  * @license    http://www.pimcore.org/license     GPLv3 and PEL
  13.  */
  14. namespace Pimcore\Bundle\AdminBundle\Controller\Admin;
  15. use Pimcore\Bundle\AdminBundle\Controller\AdminController;
  16. use Pimcore\Bundle\AdminBundle\HttpFoundation\JsonResponse;
  17. use Pimcore\Config;
  18. use Pimcore\Controller\EventedControllerInterface;
  19. use Pimcore\Logger;
  20. use Pimcore\Model\DataObject;
  21. use Pimcore\Model\Element;
  22. use Pimcore\Model\User;
  23. use Pimcore\Tool;
  24. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\Response;
  27. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
  28. use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
  29. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  30. use Symfony\Component\Routing\Annotation\Route;
  31. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  32. class UserController extends AdminController implements EventedControllerInterface
  33. {
  34.     /**
  35.      * @Route("/user/tree-get-childs-by-id", name="pimcore_admin_user_treegetchildsbyid", methods={"GET"})
  36.      *
  37.      * @param Request $request
  38.      *
  39.      * @return JsonResponse
  40.      */
  41.     public function treeGetChildsByIdAction(Request $request)
  42.     {
  43.         $list = new User\Listing();
  44.         $list->setCondition('parentId = ?'intval($request->get('node')));
  45.         $list->setOrder('ASC');
  46.         $list->setOrderKey('name');
  47.         $list->load();
  48.         $users = [];
  49.         if (is_array($list->getUsers())) {
  50.             foreach ($list->getUsers() as $user) {
  51.                 if ($user->getId() && $user->getName() != 'system') {
  52.                     $users[] = $this->getTreeNodeConfig($user);
  53.                 }
  54.             }
  55.         }
  56.         return $this->adminJson($users);
  57.     }
  58.     /**
  59.      * @param User $user
  60.      *
  61.      * @return array
  62.      */
  63.     protected function getTreeNodeConfig($user)
  64.     {
  65.         $tmpUser = [
  66.             'id' => $user->getId(),
  67.             'text' => $user->getName(),
  68.             'elementType' => 'user',
  69.             'type' => $user->getType(),
  70.             'qtipCfg' => [
  71.                 'title' => 'ID: ' $user->getId()
  72.             ]
  73.         ];
  74.         // set type specific settings
  75.         if ($user instanceof User\Folder) {
  76.             $tmpUser['leaf'] = false;
  77.             $tmpUser['iconCls'] = 'pimcore_icon_folder';
  78.             $tmpUser['expanded'] = true;
  79.             $tmpUser['allowChildren'] = true;
  80.             if ($user->hasChildren()) {
  81.                 $tmpUser['expanded'] = false;
  82.             } else {
  83.                 $tmpUser['loaded'] = true;
  84.             }
  85.         } else {
  86.             $tmpUser['leaf'] = true;
  87.             $tmpUser['iconCls'] = 'pimcore_icon_user';
  88.             if (!$user->getActive()) {
  89.                 $tmpUser['cls'] = ' pimcore_unpublished';
  90.             }
  91.             $tmpUser['allowChildren'] = false;
  92.             $tmpUser['admin'] = $user->isAdmin();
  93.         }
  94.         return $tmpUser;
  95.     }
  96.     /**
  97.      * @Route("/user/add", name="pimcore_admin_user_add", methods={"POST"})
  98.      *
  99.      * @param Request $request
  100.      *
  101.      * @return JsonResponse
  102.      */
  103.     public function addAction(Request $request)
  104.     {
  105.         try {
  106.             $type $request->get('type');
  107.             $className User\Service::getClassNameForType($type);
  108.             $user $className::create([
  109.                 'parentId' => intval($request->get('parentId')),
  110.                 'name' => trim($request->get('name')),
  111.                 'password' => '',
  112.                 'active' => $request->get('active')
  113.             ]);
  114.             if ($request->get('rid')) {
  115.                 $rid $request->get('rid');
  116.                 $rObject $className::getById($rid);
  117.                 if ($rObject) {
  118.                     if ($type == 'user' || $type == 'role') {
  119.                         $user->setParentId($rObject->getParentId());
  120.                         if ($rObject->getClasses()) {
  121.                             $user->setClasses(implode(','$rObject->getClasses()));
  122.                         }
  123.                         if ($rObject->getDocTypes()) {
  124.                             $user->setDocTypes(implode(','$rObject->getDocTypes()));
  125.                         }
  126.                         $keys = ['asset''document''object'];
  127.                         foreach ($keys as $key) {
  128.                             $getter 'getWorkspaces' ucfirst($key);
  129.                             $setter 'setWorkspaces' ucfirst($key);
  130.                             $workspaces $rObject->$getter();
  131.                             $clonedWorkspaces = [];
  132.                             if (is_array($workspaces)) {
  133.                                 foreach ($workspaces as $workspace) {
  134.                                     $vars get_object_vars($workspace);
  135.                                     if ($key == 'object') {
  136.                                         $workspaceClass '\\Pimcore\\Model\\User\\Workspace\\DataObject';
  137.                                     } else {
  138.                                         $workspaceClass '\\Pimcore\\Model\\User\\Workspace\\' ucfirst($key);
  139.                                     }
  140.                                     $newWorkspace = new $workspaceClass();
  141.                                     foreach ($vars as $varKey => $varValue) {
  142.                                         $newWorkspace->$varKey $varValue;
  143.                                     }
  144.                                     $newWorkspace->setUserId($user->getId());
  145.                                     $clonedWorkspaces[] = $newWorkspace;
  146.                                 }
  147.                             }
  148.                             $user->$setter($clonedWorkspaces);
  149.                         }
  150.                         $user->setPerspectives($rObject->getPerspectives());
  151.                         $user->setPermissions($rObject->getPermissions());
  152.                         if ($type == 'user') {
  153.                             $user->setAdmin(false);
  154.                             if ($this->getAdminUser()->isAdmin()) {
  155.                                 $user->setAdmin($rObject->getAdmin());
  156.                             }
  157.                             $user->setActive($rObject->getActive());
  158.                             $user->setRoles($rObject->getRoles());
  159.                             $user->setWelcomeScreen($rObject->getWelcomescreen());
  160.                             $user->setMemorizeTabs($rObject->getMemorizeTabs());
  161.                             $user->setCloseWarning($rObject->getCloseWarning());
  162.                         }
  163.                         $user->setWebsiteTranslationLanguagesView($rObject->getWebsiteTranslationLanguagesView());
  164.                         $user->setWebsiteTranslationLanguagesEdit($rObject->getWebsiteTranslationLanguagesEdit());
  165.                         $user->save();
  166.                     }
  167.                 }
  168.             }
  169.             return $this->adminJson([
  170.                 'success' => true,
  171.                 'id' => $user->getId()
  172.             ]);
  173.         } catch (\Exception $e) {
  174.             return $this->adminJson(['success' => false'message' => $e->getMessage()]);
  175.         }
  176.     }
  177.     /**
  178.      * @param User $node
  179.      * @param array $currentList
  180.      * @param bool $roleMode
  181.      *
  182.      * @return array
  183.      *
  184.      * @throws \Exception
  185.      */
  186.     protected function populateChildNodes($node, &$currentList$roleMode)
  187.     {
  188.         $currentUser = \Pimcore\Tool\Admin::getCurrentUser();
  189.         $list $roleMode ? new User\Role\Listing() : new User\Listing();
  190.         $list->setCondition('parentId = ?'$node->getId());
  191.         $list->setOrder('ASC');
  192.         $list->setOrderKey('name');
  193.         $list->load();
  194.         $childList $roleMode $list->getRoles() : $list->getUsers();
  195.         if (is_array($childList)) {
  196.             foreach ($childList as $user) {
  197.                 if ($user->getId() == $currentUser->getId()) {
  198.                     throw new \Exception('Cannot delete current user');
  199.                 }
  200.                 if ($user->getId() && $currentUser->getId() && $user->getName() != 'system') {
  201.                     $currentList[] = $user;
  202.                     $this->populateChildNodes($user$currentList$roleMode);
  203.                 }
  204.             }
  205.         }
  206.         return $currentList;
  207.     }
  208.     /**
  209.      * @Route("/user/delete", name="pimcore_admin_user_delete", methods={"DELETE"})
  210.      *
  211.      * @param Request $request
  212.      *
  213.      * @return JsonResponse
  214.      *
  215.      * @throws \Exception
  216.      */
  217.     public function deleteAction(Request $request)
  218.     {
  219.         $user User\AbstractUser::getById(intval($request->get('id')));
  220.         // only admins are allowed to delete admins and folders
  221.         // because a folder might contain an admin user, so it is simply not allowed for users with the "users" permission
  222.         if (($user instanceof User\Folder && !$this->getAdminUser()->isAdmin()) || ($user instanceof User && $user->isAdmin() && !$this->getAdminUser()->isAdmin())) {
  223.             throw new \Exception('You are not allowed to delete this user');
  224.         } else {
  225.             if ($user instanceof User\Role\Folder) {
  226.                 $list = [$user];
  227.                 $this->populateChildNodes($user$list$user instanceof User\Role\Folder);
  228.                 $listCount count($list);
  229.                 for ($i $listCount 1$i >= 0$i--) {
  230.                     // iterate over the list from the so that nothing can get "lost"
  231.                     $user $list[$i];
  232.                     $user->delete();
  233.                 }
  234.             } else {
  235.                 if ($user->getId()) {
  236.                     if ($user instanceof User\Role) {
  237.                         // #1431 remove user-role relations
  238.                         $userRoleRelationListing = new User\Listing();
  239.                         $userRoleRelationListing->setCondition('FIND_IN_SET(' $user->getId() . ',roles)');
  240.                         $userRoleRelationListing $userRoleRelationListing->load();
  241.                         if ($userRoleRelationListing) {
  242.                             /** @var User $relatedUser */
  243.                             foreach ($userRoleRelationListing as $relatedUser) {
  244.                                 $userRoles $relatedUser->getRoles();
  245.                                 if (is_array($userRoles)) {
  246.                                     $key array_search($user->getId(), $userRoles);
  247.                                     if (false !== $key) {
  248.                                         unset($userRoles[$key]);
  249.                                         $relatedUser->setRoles($userRoles);
  250.                                         $relatedUser->save();
  251.                                     }
  252.                                 }
  253.                             }
  254.                         }
  255.                     }
  256.                     $user->delete();
  257.                 }
  258.             }
  259.         }
  260.         return $this->adminJson(['success' => true]);
  261.     }
  262.     /**
  263.      * @Route("/user/update", name="pimcore_admin_user_update", methods={"PUT"})
  264.      *
  265.      * @param Request $request
  266.      *
  267.      * @return JsonResponse
  268.      *
  269.      * @throws \Exception
  270.      */
  271.     public function updateAction(Request $request)
  272.     {
  273.         /** @var User|User\Role $user */
  274.         $user User\AbstractUser::getById(intval($request->get('id')));
  275.         if ($user instanceof User && $user->isAdmin() && !$this->getAdminUser()->isAdmin()) {
  276.             throw new \Exception('Only admin users are allowed to modify admin users');
  277.         }
  278.         if ($request->get('data')) {
  279.             $values $this->decodeJson($request->get('data'), true);
  280.             if (!empty($values['password'])) {
  281.                 if (strlen($values['password']) < 10) {
  282.                     throw new \Exception('Passwords have to be at least 10 characters long');
  283.                 }
  284.                 $values['password'] = Tool\Authentication::getPasswordHash($user->getName(), $values['password']);
  285.             }
  286.             // check if there are permissions transmitted, if so reset them all to false (they will be set later)
  287.             foreach ($values as $key => $value) {
  288.                 if (strpos($key'permission_') === 0) {
  289.                     if (method_exists($user'setAllAclToFalse')) {
  290.                         $user->setAllAclToFalse();
  291.                     }
  292.                     break;
  293.                 }
  294.             }
  295.             if ($user instanceof User && isset($values['2fa_required'])) {
  296.                 $user->setTwoFactorAuthentication('required', (bool) $values['2fa_required']);
  297.             }
  298.             $user->setValues($values);
  299.             // only admins are allowed to create admin users
  300.             // if the logged in user isn't an admin, set admin always to false
  301.             if (!$this->getAdminUser()->isAdmin() && $user instanceof User) {
  302.                 if ($user instanceof User) {
  303.                     $user->setAdmin(false);
  304.                 }
  305.             }
  306.             // check for permissions
  307.             $availableUserPermissionsList = new User\Permission\Definition\Listing();
  308.             $availableUserPermissions $availableUserPermissionsList->load();
  309.             foreach ($availableUserPermissions as $permission) {
  310.                 if (isset($values['permission_' $permission->getKey()])) {
  311.                     $user->setPermission($permission->getKey(), (bool) $values['permission_' $permission->getKey()]);
  312.                 }
  313.             }
  314.             // check for workspaces
  315.             if ($request->get('workspaces')) {
  316.                 $processedPaths = ['object' => [], 'asset' => [], 'document' => []]; //array to find if there are multiple entries for a path
  317.                 $workspaces $this->decodeJson($request->get('workspaces'), true);
  318.                 foreach ($workspaces as $type => $spaces) {
  319.                     $newWorkspaces = [];
  320.                     foreach ($spaces as $space) {
  321.                         if (in_array($space['path'], $processedPaths[$type])) {
  322.                             throw new \Exception('Error saving workspaces as multiple entries found for path "' $space['path'] .'" in '.$this->trans("$type") . 's');
  323.                         }
  324.                         $element Element\Service::getElementByPath($type$space['path']);
  325.                         if ($element) {
  326.                             $className '\\Pimcore\\Model\\User\\Workspace\\' Element\Service::getBaseClassNameForElement($type);
  327.                             $workspace = new $className();
  328.                             $workspace->setValues($space);
  329.                             $workspace->setCid($element->getId());
  330.                             $workspace->setCpath($element->getRealFullPath());
  331.                             $workspace->setUserId($user->getId());
  332.                             $newWorkspaces[] = $workspace;
  333.                             $processedPaths[$type][] = $space['path'];
  334.                         }
  335.                     }
  336.                     $user->{'setWorkspaces' ucfirst($type)}($newWorkspaces);
  337.                 }
  338.             }
  339.         }
  340.         if ($request->get('keyBindings')) {
  341.             $keyBindings json_decode($request->get('keyBindings'), true);
  342.             $tmpArray = [];
  343.             foreach ($keyBindings as $action => $item) {
  344.                 $tmpArray[] = json_decode($itemtrue);
  345.             }
  346.             $tmpArray array_values(array_filter($tmpArray));
  347.             $tmpArray json_encode($tmpArray);
  348.             $user->setKeyBindings($tmpArray);
  349.         }
  350.         $user->save();
  351.         return $this->adminJson(['success' => true]);
  352.     }
  353.     /**
  354.      * @Route("/user/get", name="pimcore_admin_user_get", methods={"GET"})
  355.      *
  356.      * @param Request $request
  357.      * @param Config $config
  358.      *
  359.      * @return JsonResponse
  360.      *
  361.      * @throws \Exception
  362.      */
  363.     public function getAction(Request $requestConfig $config)
  364.     {
  365.         if (intval($request->get('id')) < 1) {
  366.             return $this->adminJson(['success' => false]);
  367.         }
  368.         /** @var User $user */
  369.         $user User::getById(intval($request->get('id')));
  370.         if ($user->isAdmin() && !$this->getAdminUser()->isAdmin()) {
  371.             throw new \Exception('Only admin users are allowed to modify admin users');
  372.         }
  373.         // workspaces
  374.         $types = ['asset''document''object'];
  375.         foreach ($types as $type) {
  376.             $workspaces $user->{'getWorkspaces' ucfirst($type)}();
  377.             foreach ($workspaces as $workspace) {
  378.                 $el Element\Service::getElementById($type$workspace->getCid());
  379.                 if ($el) {
  380.                     // direct injection => not nice but in this case ok ;-)
  381.                     $workspace->path $el->getRealFullPath();
  382.                 }
  383.             }
  384.         }
  385.         // object <=> user dependencies
  386.         $userObjects DataObject\Service::getObjectsReferencingUser($user->getId());
  387.         $userObjectData = [];
  388.         $hasHidden false;
  389.         foreach ($userObjects as $o) {
  390.             if ($o->isAllowed('list')) {
  391.                 $userObjectData[] = [
  392.                     'path' => $o->getRealFullPath(),
  393.                     'id' => $o->getId(),
  394.                     'subtype' => $o->getClass()->getName()
  395.                 ];
  396.             } else {
  397.                 $hasHidden true;
  398.             }
  399.         }
  400.         // get available permissions
  401.         $availableUserPermissionsList = new User\Permission\Definition\Listing();
  402.         $availableUserPermissions $availableUserPermissionsList->load();
  403.         // get available roles
  404.         $list = new User\Role\Listing();
  405.         $list->setCondition('`type` = ?', ['role']);
  406.         $list->load();
  407.         $roles = [];
  408.         if (is_array($list->getItems())) {
  409.             foreach ($list->getItems() as $role) {
  410.                 $roles[] = [$role->getId(), $role->getName()];
  411.             }
  412.         }
  413.         // unset confidential informations
  414.         $userData $user->getObjectVars();
  415.         $contentLanguages Tool\Admin::reorderWebsiteLanguages($userTool::getValidLanguages());
  416.         $userData['contentLanguages'] = $contentLanguages;
  417.         $userData['twoFactorAuthentication']['isActive'] = ($user->getTwoFactorAuthentication('enabled') || $user->getTwoFactorAuthentication('secret'));
  418.         unset($userData['password']);
  419.         unset($userData['twoFactorAuthentication']['secret']);
  420.         $availablePerspectives = \Pimcore\Config::getAvailablePerspectives(null);
  421.         return $this->adminJson([
  422.             'success' => true,
  423.             'wsenabled' => $config['webservice']['enabled'],
  424.             'user' => $userData,
  425.             'roles' => $roles,
  426.             'permissions' => $user->generatePermissionList(),
  427.             'availablePermissions' => $availableUserPermissions,
  428.             'availablePerspectives' => $availablePerspectives,
  429.             'validLanguages' => Tool::getValidLanguages(),
  430.             'objectDependencies' => [
  431.                 'hasHidden' => $hasHidden,
  432.                 'dependencies' => $userObjectData
  433.             ]
  434.         ]);
  435.     }
  436.     /**
  437.      * @Route("/user/get-minimal", name="pimcore_admin_user_getminimal", methods={"GET"})
  438.      *
  439.      * @param Request $request
  440.      *
  441.      * @return JsonResponse
  442.      */
  443.     public function getMinimalAction(Request $request)
  444.     {
  445.         /** @var User $user */
  446.         $user User::getById(intval($request->get('id')));
  447.         $user->setPassword(null);
  448.         $minimalUserData['id'] = $user->getId();
  449.         $minimalUserData['admin'] = $user->isAdmin();
  450.         $minimalUserData['active'] = $user->isActive();
  451.         $minimalUserData['permissionInfo']['assets'] = $user->isAllowed('assets');
  452.         $minimalUserData['permissionInfo']['documents'] = $user->isAllowed('documents');
  453.         $minimalUserData['permissionInfo']['objects'] = $user->isAllowed('objects');
  454.         return $this->adminJson($minimalUserData);
  455.     }
  456.     /**
  457.      * @Route("/user/upload-current-user-image", name="pimcore_admin_user_uploadcurrentuserimage", methods={"POST"})
  458.      *
  459.      * @param Request $request
  460.      *
  461.      * @return JsonResponse
  462.      */
  463.     public function uploadCurrentUserImageAction(Request $request)
  464.     {
  465.         $user $this->getAdminUser();
  466.         if ($user != null) {
  467.             if ($user->getId() == $request->get('id')) {
  468.                 return $this->uploadImageAction($request);
  469.             } else {
  470.                 Logger::warn('prevented save current user, because ids do not match. ');
  471.                 return $this->adminJson(false);
  472.             }
  473.         } else {
  474.             return $this->adminJson(false);
  475.         }
  476.     }
  477.     /**
  478.      * @Route("/user/update-current-user", name="pimcore_admin_user_updatecurrentuser", methods={"PUT"})
  479.      *
  480.      * @param Request $request
  481.      *
  482.      * @return JsonResponse
  483.      */
  484.     public function updateCurrentUserAction(Request $request)
  485.     {
  486.         $user $this->getAdminUser();
  487.         if ($user != null) {
  488.             if ($user->getId() == $request->get('id')) {
  489.                 $values $this->decodeJson($request->get('data'), true);
  490.                 unset($values['name']);
  491.                 unset($values['id']);
  492.                 unset($values['admin']);
  493.                 unset($values['permissions']);
  494.                 unset($values['roles']);
  495.                 unset($values['active']);
  496.                 if (!empty($values['new_password'])) {
  497.                     $oldPasswordCheck false;
  498.                     if (empty($values['old_password'])) {
  499.                         // if the user want to reset the password, the old password isn't required
  500.                         $oldPasswordCheck Tool\Session::useSession(function (AttributeBagInterface $adminSession) {
  501.                             if ($adminSession->get('password_reset')) {
  502.                                 return true;
  503.                             }
  504.                             return false;
  505.                         });
  506.                     } else {
  507.                         // the password has to match
  508.                         $checkUser Tool\Authentication::authenticatePlaintext($user->getName(), $values['old_password']);
  509.                         if ($checkUser) {
  510.                             $oldPasswordCheck true;
  511.                         }
  512.                     }
  513.                     if (strlen($values['new_password']) < 10) {
  514.                         throw new \Exception('Passwords have to be at least 10 characters long');
  515.                     }
  516.                     if ($oldPasswordCheck && $values['new_password'] == $values['retype_password']) {
  517.                         $values['password'] = Tool\Authentication::getPasswordHash($user->getName(), $values['new_password']);
  518.                     } else {
  519.                         return $this->adminJson(['success' => false'message' => 'password_cannot_be_changed']);
  520.                     }
  521.                 }
  522.                 $user->setValues($values);
  523.                 if ($request->get('keyBindings')) {
  524.                     $keyBindings json_decode($request->get('keyBindings'), true);
  525.                     $tmpArray = [];
  526.                     foreach ($keyBindings as $action => $item) {
  527.                         $tmpArray[] = json_decode($itemtrue);
  528.                     }
  529.                     $tmpArray array_values(array_filter($tmpArray));
  530.                     $tmpArray json_encode($tmpArray);
  531.                     $user->setKeyBindings($tmpArray);
  532.                 }
  533.                 $user->save();
  534.                 return $this->adminJson(['success' => true]);
  535.             } else {
  536.                 Logger::warn('prevented save current user, because ids do not match. ');
  537.                 return $this->adminJson(false);
  538.             }
  539.         } else {
  540.             return $this->adminJson(false);
  541.         }
  542.     }
  543.     /**
  544.      * @Route("/user/get-current-user", name="pimcore_admin_user_getcurrentuser", methods={"GET"})
  545.      *
  546.      * @param Request $request
  547.      *
  548.      * @return Response
  549.      */
  550.     public function getCurrentUserAction(Request $request)
  551.     {
  552.         $user $this->getAdminUser();
  553.         $list = new User\Permission\Definition\Listing();
  554.         $definitions $list->load();
  555.         foreach ($definitions as $definition) {
  556.             $user->setPermission($definition->getKey(), $user->isAllowed($definition->getKey()));
  557.         }
  558.         // unset confidential informations
  559.         $userData $user->getObjectVars();
  560.         $contentLanguages Tool\Admin::reorderWebsiteLanguages($userTool::getValidLanguages());
  561.         $userData['contentLanguages'] = $contentLanguages;
  562.         $userData['keyBindings'] = $user->getKeyBindings();
  563.         unset($userData['password']);
  564.         $userData['twoFactorAuthentication'] = $user->getTwoFactorAuthentication();
  565.         unset($userData['twoFactorAuthentication']['secret']);
  566.         $userData['twoFactorAuthentication']['isActive'] = $user->getTwoFactorAuthentication('enabled') && $user->getTwoFactorAuthentication('secret');
  567.         $userData['isPasswordReset'] = Tool\Session::useSession(function (AttributeBagInterface $adminSession) {
  568.             return $adminSession->get('password_reset');
  569.         });
  570.         $response = new Response('pimcore.currentuser = ' $this->encodeJson($userData));
  571.         $response->headers->set('Content-Type''text/javascript');
  572.         return $response;
  573.     }
  574.     /* ROLES */
  575.     /**
  576.      * @Route("/user/role-tree-get-childs-by-id", name="pimcore_admin_user_roletreegetchildsbyid", methods={"GET"})
  577.      *
  578.      * @param Request $request
  579.      *
  580.      * @return JsonResponse
  581.      */
  582.     public function roleTreeGetChildsByIdAction(Request $request)
  583.     {
  584.         $list = new User\Role\Listing();
  585.         $list->setCondition('parentId = ?'intval($request->get('node')));
  586.         $list->load();
  587.         $roles = [];
  588.         if (is_array($list->getItems())) {
  589.             foreach ($list->getItems() as $role) {
  590.                 $roles[] = $this->getRoleTreeNodeConfig($role);
  591.             }
  592.         }
  593.         return $this->adminJson($roles);
  594.     }
  595.     /**
  596.      * @param User\Role $role
  597.      *
  598.      * @return array
  599.      */
  600.     protected function getRoleTreeNodeConfig($role)
  601.     {
  602.         $tmpUser = [
  603.             'id' => $role->getId(),
  604.             'text' => $role->getName(),
  605.             'elementType' => 'role',
  606.             'qtipCfg' => [
  607.                 'title' => 'ID: ' $role->getId()
  608.             ]
  609.         ];
  610.         // set type specific settings
  611.         if ($role instanceof User\Role\Folder) {
  612.             $tmpUser['leaf'] = false;
  613.             $tmpUser['iconCls'] = 'pimcore_icon_folder';
  614.             $tmpUser['expanded'] = true;
  615.             $tmpUser['allowChildren'] = true;
  616.             if ($role->hasChildren()) {
  617.                 $tmpUser['expanded'] = false;
  618.             } else {
  619.                 $tmpUser['loaded'] = true;
  620.             }
  621.         } else {
  622.             $tmpUser['leaf'] = true;
  623.             $tmpUser['iconCls'] = 'pimcore_icon_roles';
  624.             $tmpUser['allowChildren'] = false;
  625.         }
  626.         return $tmpUser;
  627.     }
  628.     /**
  629.      * @Route("/user/role-get", name="pimcore_admin_user_roleget", methods={"GET"})
  630.      *
  631.      * @param Request $request
  632.      *
  633.      * @return JsonResponse
  634.      */
  635.     public function roleGetAction(Request $request)
  636.     {
  637.         /** @var User\UserRole $role */
  638.         $role User\Role::getById(intval($request->get('id')));
  639.         // workspaces
  640.         $types = ['asset''document''object'];
  641.         foreach ($types as $type) {
  642.             $workspaces $role->{'getWorkspaces' ucfirst($type)}();
  643.             foreach ($workspaces as $workspace) {
  644.                 $el Element\Service::getElementById($type$workspace->getCid());
  645.                 if ($el) {
  646.                     // direct injection => not nice but in this case ok ;-)
  647.                     $workspace->path $el->getRealFullPath();
  648.                 }
  649.             }
  650.         }
  651.         // get available permissions
  652.         $availableUserPermissionsList = new User\Permission\Definition\Listing();
  653.         $availableUserPermissions $availableUserPermissionsList->load();
  654.         $availablePerspectives = \Pimcore\Config::getAvailablePerspectives(null);
  655.         return $this->adminJson([
  656.             'success' => true,
  657.             'role' => $role,
  658.             'permissions' => $role->generatePermissionList(),
  659.             'classes' => $role->getClasses(),
  660.             'docTypes' => $role->getDocTypes(),
  661.             'availablePermissions' => $availableUserPermissions,
  662.             'availablePerspectives' => $availablePerspectives,
  663.             'validLanguages' => Tool::getValidLanguages()
  664.         ]);
  665.     }
  666.     /**
  667.      * @Route("/user/upload-image", name="pimcore_admin_user_uploadimage", methods={"POST"})
  668.      *
  669.      * @param Request $request
  670.      *
  671.      * @throws \Exception
  672.      *
  673.      * @return JsonResponse
  674.      */
  675.     public function uploadImageAction(Request $request)
  676.     {
  677.         if ($request->get('id')) {
  678.             if ($this->getAdminUser()->getId() != $request->get('id')) {
  679.                 $this->checkPermission('users');
  680.             }
  681.             $id $request->get('id');
  682.         } else {
  683.             $id $this->getAdminUser()->getId();
  684.         }
  685.         /** @var User $userObj */
  686.         $userObj User::getById($id);
  687.         if ($userObj->isAdmin() && !$this->getAdminUser()->isAdmin()) {
  688.             throw new \Exception('Only admin users are allowed to modify admin users');
  689.         }
  690.         $userObj->setImage($_FILES['Filedata']['tmp_name']);
  691.         // set content-type to text/html, otherwise (when application/json is sent) chrome will complain in
  692.         // Ext.form.Action.Submit and mark the submission as failed
  693.         $response $this->adminJson(['success' => true]);
  694.         $response->headers->set('Content-Type''text/html');
  695.         return $response;
  696.     }
  697.     /**
  698.      * @Route("/user/renew-2fa-qr-secret", name="pimcore_admin_user_renew2fasecret", methods={"GET"})
  699.      *
  700.      * @param Request $request
  701.      *
  702.      * @return BinaryFileResponse
  703.      */
  704.     public function renew2FaSecretAction(Request $request)
  705.     {
  706.         $user $this->getAdminUser();
  707.         $proxyUser $this->getAdminUser(true);
  708.         $twoFactorService $this->get('scheb_two_factor.security.google_authenticator');
  709.         $newSecret $twoFactorService->generateSecret();
  710.         $user->setTwoFactorAuthentication('enabled'true);
  711.         $user->setTwoFactorAuthentication('type''google');
  712.         $user->setTwoFactorAuthentication('secret'$newSecret);
  713.         $user->save();
  714.         Tool\Session::useSession(function (AttributeBagInterface $adminSession) {
  715.             Tool\Session::regenerateId();
  716.             $adminSession->set('2fa_required'true);
  717.         });
  718.         $twoFactorService $this->get('scheb_two_factor.security.google_authenticator');
  719.         $url $twoFactorService->getQRContent($proxyUser);
  720.         $code = new \Endroid\QrCode\QrCode;
  721.         $code->setWriterByName('png');
  722.         $code->setText($url);
  723.         $code->setSize(200);
  724.         $qrCodeFile PIMCORE_PRIVATE_VAR '/qr-code-' uniqid() . '.png';
  725.         $code->writeFile($qrCodeFile);
  726.         $response = new BinaryFileResponse($qrCodeFile);
  727.         return $response;
  728.     }
  729.     /**
  730.      * @Route("/user/disable-2fa", name="pimcore_admin_user_disable2fasecret", methods={"DELETE"})
  731.      *
  732.      * @param Request $request
  733.      *
  734.      * @return JsonResponse
  735.      */
  736.     public function disable2FaSecretAction(Request $request)
  737.     {
  738.         $user $this->getAdminUser();
  739.         $success false;
  740.         if (!$user->getTwoFactorAuthentication('required')) {
  741.             $user->setTwoFactorAuthentication([]);
  742.             $user->save();
  743.             $success true;
  744.         }
  745.         return $this->adminJson([
  746.             'success' => $success
  747.         ]);
  748.     }
  749.     /**
  750.      * @Route("/user/reset-2fa-secret", name="pimcore_admin_user_reset2fasecret", methods={"PUT"})
  751.      *
  752.      * @param Request $request
  753.      *
  754.      * @return JsonResponse
  755.      */
  756.     public function reset2FaSecretAction(Request $request)
  757.     {
  758.         /**
  759.          * @var User $user
  760.          */
  761.         $user User::getById(intval($request->get('id')));
  762.         $success true;
  763.         $user->setTwoFactorAuthentication('enabled'false);
  764.         $user->setTwoFactorAuthentication('secret''');
  765.         $user->save();
  766.         return $this->adminJson([
  767.             'success' => $success
  768.         ]);
  769.     }
  770.     /**
  771.      * @Route("/user/get-image", name="pimcore_admin_user_getimage", methods={"GET"})
  772.      *
  773.      * @param Request $request
  774.      *
  775.      * @return BinaryFileResponse
  776.      */
  777.     public function getImageAction(Request $request)
  778.     {
  779.         if ($request->get('id')) {
  780.             if ($this->getAdminUser()->getId() != $request->get('id')) {
  781.                 $this->checkPermission('users');
  782.             }
  783.             $id $request->get('id');
  784.         } else {
  785.             $id $this->getAdminUser()->getId();
  786.         }
  787.         /** @var User $userObj */
  788.         $userObj User::getById($id);
  789.         $thumb $userObj->getImage();
  790.         $response = new BinaryFileResponse($thumb);
  791.         $response->headers->set('Content-Type''image/png');
  792.         return $response;
  793.     }
  794.     /**
  795.      * @Route("/user/get-token-login-link", name="pimcore_admin_user_gettokenloginlink", methods={"GET"})
  796.      *
  797.      * @param Request $request
  798.      *
  799.      * @return JsonResponse
  800.      *
  801.      * @throws \Exception
  802.      */
  803.     public function getTokenLoginLinkAction(Request $request)
  804.     {
  805.         /** @var User $user */
  806.         $user User::getById($request->get('id'));
  807.         if (!$user) {
  808.             return $this->adminJson([
  809.                 'success' => false,
  810.                 'message' => $this->trans('login_token_invalid_user_error'),
  811.             ], Response::HTTP_NOT_FOUND);
  812.         }
  813.         if ($user->isAdmin() && !$this->getAdminUser()->isAdmin()) {
  814.             return $this->adminJson([
  815.                 'success' => false,
  816.                 'message' => $this->trans('login_token_as_admin_non_admin_user_error'),
  817.             ], Response::HTTP_FORBIDDEN);
  818.         }
  819.         if (empty($user->getPassword())) {
  820.             return $this->adminJson([
  821.                 'success' => false,
  822.                 'message' => $this->trans('login_token_no_password_error'),
  823.             ], Response::HTTP_FORBIDDEN);
  824.         }
  825.         $token Tool\Authentication::generateToken($user->getName());
  826.         $link $this->generateCustomUrl([
  827.             'token' => $token,
  828.         ]);
  829.         return $this->adminJson([
  830.             'success' => true,
  831.             'link' => $link
  832.         ]);
  833.     }
  834.     /**
  835.      * @Route("/user/search", name="pimcore_admin_user_search", methods={"GET"})
  836.      *
  837.      * @param Request $request
  838.      *
  839.      * @return JsonResponse
  840.      */
  841.     public function searchAction(Request $request)
  842.     {
  843.         $q '%' $request->get('query') . '%';
  844.         $list = new User\Listing();
  845.         $list->setCondition('name LIKE ? OR firstname LIKE ? OR lastname LIKE ? OR email LIKE ? OR id = ?', [$q$q$q$qintval($request->get('query'))]);
  846.         $list->setOrder('ASC');
  847.         $list->setOrderKey('name');
  848.         $list->load();
  849.         $users = [];
  850.         if (is_array($list->getUsers())) {
  851.             foreach ($list->getUsers() as $user) {
  852.                 if ($user instanceof User && $user->getId() && $user->getName() != 'system') {
  853.                     $users[] = [
  854.                         'id' => $user->getId(),
  855.                         'name' => $user->getName(),
  856.                         'email' => $user->getEmail(),
  857.                         'firstname' => $user->getFirstname(),
  858.                         'lastname' => $user->getLastname(),
  859.                     ];
  860.                 }
  861.             }
  862.         }
  863.         return $this->adminJson([
  864.             'success' => true,
  865.             'users' => $users
  866.         ]);
  867.     }
  868.     /**
  869.      * @param FilterControllerEvent $event
  870.      */
  871.     public function onKernelController(FilterControllerEvent $event)
  872.     {
  873.         $isMasterRequest $event->isMasterRequest();
  874.         if (!$isMasterRequest) {
  875.             return;
  876.         }
  877.         // check permissions
  878.         $unrestrictedActions = [
  879.             'getCurrentUserAction''updateCurrentUserAction''getAvailablePermissionsAction''getMinimalAction',
  880.             'getImageAction''uploadCurrentUserImageAction''disable2FaSecretAction''renew2FaSecretAction',
  881.             'getUsersForSharingAction''getRolesForSharingAction'
  882.         ];
  883.         $this->checkActionPermission($event'users'$unrestrictedActions);
  884.     }
  885.     /**
  886.      * @param FilterResponseEvent $event
  887.      */
  888.     public function onKernelResponse(FilterResponseEvent $event)
  889.     {
  890.         // nothing to do
  891.     }
  892.     /**
  893.      * @param Request $request
  894.      *
  895.      * @return JsonResponse
  896.      *
  897.      * @Route("/user/get-users-for-sharing", name="pimcore_admin_user_getusersforsharing", methods={"GET"})
  898.      */
  899.     public function getUsersForSharingAction(Request $request)
  900.     {
  901.         $this->checkPermission('share_configurations');
  902.         return $this->getUsersAction($request);
  903.     }
  904.     /**
  905.      * @param Request $request
  906.      *
  907.      * @return JsonResponse
  908.      *
  909.      * @Route("/user/get-roles-for-sharing", name="pimcore_admin_user_getrolesforsharing", methods={"GET"}))
  910.      */
  911.     public function getRolesForSharingAction(Request $request)
  912.     {
  913.         $this->checkPermission('share_configurations');
  914.         return $this->getRolesAction($request);
  915.     }
  916.     /**
  917.      * @Route("/user/get-users", name="pimcore_admin_user_getusers", methods={"GET"})
  918.      *
  919.      * @param Request $request
  920.      *
  921.      * @return JsonResponse
  922.      */
  923.     public function getUsersAction(Request $request)
  924.     {
  925.         $users = [];
  926.         // get available user
  927.         $list = new \Pimcore\Model\User\Listing();
  928.         $conditions = [ 'type = "user"' ];
  929.         if (!$request->get('include_current_user')) {
  930.             $conditions[] = 'id != ' $this->getAdminUser()->getId();
  931.         }
  932.         $list->setCondition(implode(' AND '$conditions));
  933.         $list->load();
  934.         $userList $list->getUsers();
  935.         foreach ($userList as $user) {
  936.             if (!$request->get('permission') || $user->isAllowed($request->get('permission'))) {
  937.                 $users[] = [
  938.                     'id' => $user->getId(),
  939.                     'label' => $user->getUsername()
  940.                 ];
  941.             }
  942.         }
  943.         return $this->adminJson(['success' => true'total' => count($users), 'data' => $users]);
  944.     }
  945.     /**
  946.      * @Route("/user/get-roles", name="pimcore_admin_user_getroles", methods={"GET"})
  947.      *
  948.      * @param Request $request
  949.      *
  950.      * @return JsonResponse
  951.      */
  952.     public function getRolesAction(Request $request)
  953.     {
  954.         $roles = [];
  955.         $list = new \Pimcore\Model\User\Role\Listing();
  956.         $list->setCondition('type = "role"');
  957.         $list->load();
  958.         $roleList $list->getRoles();
  959.         /** @var User\Role $role */
  960.         foreach ($roleList as $role) {
  961.             if (!$request->get('permission') || in_array($request->get('permission'), $role->getPermissions())) {
  962.                 $roles[] = [
  963.                     'id' => $role->getId(),
  964.                     'label' => $role->getName()
  965.                 ];
  966.             }
  967.         }
  968.         return $this->adminJson(['success' => true'total' => count($roles), 'data' => $roles]);
  969.     }
  970.     /**
  971.      * @Route("/user/get-default-key-bindings", name="pimcore_admin_user_getdefaultkeybindings", methods={"GET"})
  972.      *
  973.      * @param Request $request
  974.      *
  975.      * @return JsonResponse
  976.      */
  977.     public function getDefaultKeyBindingsAction(Request $request)
  978.     {
  979.         $data User::getDefaultKeyBindings();
  980.         return $this->adminJson(['success' => true'data' => $data]);
  981.     }
  982.     /**
  983.      * @Route("/user/invitationlink", name="pimcore_admin_user_invitationlink", methods={"POST"})
  984.      *
  985.      * @param Request $request
  986.      *
  987.      * @return JsonResponse
  988.      *
  989.      * @throws \Exception
  990.      */
  991.     public function invitationLinkAction(Request $request)
  992.     {
  993.         $success false;
  994.         $message '';
  995.         if ($username $request->get('username')) {
  996.             /** @var User $user */
  997.             $user User::getByName($username);
  998.             if ($user instanceof User) {
  999.                 if (!$user->isActive()) {
  1000.                     $message .= 'User inactive  <br />';
  1001.                 }
  1002.                 if (!$user->getEmail()) {
  1003.                     $message .= 'User has no email address <br />';
  1004.                 }
  1005.             } else {
  1006.                 $message .= 'User unknown <br />';
  1007.             }
  1008.             if (empty($message)) {
  1009.                 //generate random password if user has no password
  1010.                 if (!$user->getPassword()) {
  1011.                     $user->setPassword(md5(uniqid()));
  1012.                     $user->save();
  1013.                 }
  1014.                 $token Tool\Authentication::generateToken($user->getName());
  1015.                 $loginUrl $this->generateCustomUrl([
  1016.                     'token' => $token,
  1017.                     'reset' => true,
  1018.                 ]);
  1019.                 try {
  1020.                     $mail Tool::getMail([$user->getEmail()], 'Pimcore login invitation for ' Tool::getHostname());
  1021.                     $mail->setIgnoreDebugMode(true);
  1022.                     $mail->setBodyText("Login to pimcore and change your password using the following link. This temporary login link will expire in  24 hours: \r\n\r\n" $loginUrl);
  1023.                     $res $mail->send();
  1024.                     $success true;
  1025.                     $message sprintf($this->trans('invitation_link_sent'), $user->getEmail());
  1026.                 } catch (\Exception $e) {
  1027.                     $message .= 'could not send email';
  1028.                 }
  1029.             }
  1030.         }
  1031.         return $this->adminJson([
  1032.             'success' => $success,
  1033.             'message' => $message
  1034.         ]);
  1035.     }
  1036.     /**
  1037.      *
  1038.      * @param array $params
  1039.      * @param string $fallbackUrl
  1040.      * @param int $referenceType //UrlGeneratorInterface::ABSOLUTE_URL, ABSOLUTE_PATH, RELATIVE_PATH, NETWORK_PATH
  1041.      *
  1042.      * @return string The generated URL
  1043.      */
  1044.     private function generateCustomUrl(array $params$fallbackUrl 'pimcore_admin_login_check'$referenceType UrlGeneratorInterface::ABSOLUTE_URL): string
  1045.     {
  1046.         try {
  1047.             //try to generate invitation link for custom admin point
  1048.             $loginUrl $this->generateUrl('my_custom_admin_entry_point'$params$referenceType);
  1049.         } catch (\Exception $e) {
  1050.             //use default login check for invitation link
  1051.             $loginUrl $this->generateUrl($fallbackUrl$params$referenceType);
  1052.         }
  1053.         return $loginUrl;
  1054.     }
  1055. }