/** * Returns the Response object associated to the acl action. * * @param int|string|null $id * * @return Response|RedirectResponse * * @throws AccessDeniedException If access is not granted. * @throws NotFoundHttpException If the object does not exist or the ACL is not enabled */ public function aclAction($id = null) { if (!$this->admin->isAclEnabled()) { throw new NotFoundHttpException('ACL are not enabled for this admin'); } $id = $this->get('request')->get($this->admin->getIdParameter()); $object = $this->admin->getObject($id); if (!$object) { throw new NotFoundHttpException(sprintf('unable to find the object with id : %s', $id)); } if (false === $this->admin->isGranted('MASTER', $object)) { throw new AccessDeniedException(); } $this->admin->setSubject($object); $aclUsers = $this->getAclUsers(); $adminObjectAclManipulator = $this->get('sonata.admin.object.manipulator.acl.admin'); $adminObjectAclData = new AdminObjectAclData($this->admin, $object, $aclUsers, $adminObjectAclManipulator->getMaskBuilderClass()); $form = $adminObjectAclManipulator->createForm($adminObjectAclData); $request = $this->getRequest(); if ($request->getMethod() === 'POST') { $form->submit($request); if ($form->isValid()) { $adminObjectAclManipulator->updateAcl($adminObjectAclData); $this->addFlash('sonata_flash_success', 'flash_acl_edit_success'); return new RedirectResponse($this->admin->generateObjectUrl('acl', $object)); } } return $this->render($this->admin->getTemplate('acl'), array('action' => 'acl', 'permissions' => $adminObjectAclData->getUserPermissions(), 'object' => $object, 'users' => $aclUsers, 'form' => $form->createView())); }
/** * @param \Sonata\AdminBundle\Admin\AdminInterface $admin * @param \Sonata\AdminBundle\Route\RouteCollection $collection */ public function build(AdminInterface $admin, RouteCollection $collection) { $collection->add('list'); $collection->add('create'); $collection->add('batch'); $collection->add('edit'); $collection->add('delete'); $collection->add('show'); $collection->add('export'); if ($this->manager->hasReader($admin->getClass())) { $collection->add('history', '/audit-history'); $collection->add('history_view_revision', '/audit-history-view'); } if ($admin->isAclEnabled()) { $collection->add('acl', $admin->getRouterIdParameter() . '/acl'); } // an admin can have only one level of nested child if ($admin->getParent()) { return; } // add children urls foreach ($admin->getChildren() as $children) { $collection->addCollection($children->getRoutes()); } }
/** * RouteBuilder that allows slashes in the ids. * * {@inheritDoc} */ function build(AdminInterface $admin, RouteCollection $collection) { $collection->add('list'); $collection->add('create'); $collection->add('batch', null, array(), array('_method' => 'POST')); $collection->add('edit', $admin->getRouterIdParameter() . '/edit', array(), array('id' => '.+')); $collection->add('delete', $admin->getRouterIdParameter() . '/delete', array(), array('id' => '.+')); $collection->add('export'); $collection->add('show', $admin->getRouterIdParameter() . '/show', array(), array('id' => '.+', '_method' => 'GET')); if ($admin->isAclEnabled()) { $collection->add('acl', $admin->getRouterIdParameter() . '/acl', array(), array('id' => '.+')); } // add children urls foreach ($admin->getChildren() as $children) { $collection->addCollection($children->getRoutes()); } }
/** * Returns the Response object associated to the acl action. * * @param int|string|null $id * @param Request $request * * @return Response|RedirectResponse * * @throws AccessDeniedException If access is not granted. * @throws NotFoundHttpException If the object does not exist or the ACL is not enabled */ public function aclAction($id = null) { $request = $this->getRequest(); if (!$this->admin->isAclEnabled()) { throw $this->createNotFoundException('ACL are not enabled for this admin'); } $id = $request->get($this->admin->getIdParameter()); $object = $this->admin->getObject($id); if (!$object) { throw $this->createNotFoundException(sprintf('unable to find the object with id : %s', $id)); } $this->admin->checkAccess('acl', $object); $this->admin->setSubject($object); $aclUsers = $this->getAclUsers(); $aclRoles = $this->getAclRoles(); $adminObjectAclManipulator = $this->get('sonata.admin.object.manipulator.acl.admin'); $adminObjectAclData = new AdminObjectAclData($this->admin, $object, $aclUsers, $adminObjectAclManipulator->getMaskBuilderClass(), $aclRoles); $aclUsersForm = $adminObjectAclManipulator->createAclUsersForm($adminObjectAclData); $aclRolesForm = $adminObjectAclManipulator->createAclRolesForm($adminObjectAclData); if ($request->getMethod() === 'POST') { if ($request->request->has(AdminObjectAclManipulator::ACL_USERS_FORM_NAME)) { $form = $aclUsersForm; $updateMethod = 'updateAclUsers'; } elseif ($request->request->has(AdminObjectAclManipulator::ACL_ROLES_FORM_NAME)) { $form = $aclRolesForm; $updateMethod = 'updateAclRoles'; } if (isset($form)) { $form->handleRequest($request); if ($form->isValid()) { $adminObjectAclManipulator->{$updateMethod}($adminObjectAclData); $this->addFlash('sonata_flash_success', 'flash_acl_edit_success'); return new RedirectResponse($this->admin->generateObjectUrl('acl', $object)); } } } return $this->render($this->admin->getTemplate('acl'), array('action' => 'acl', 'permissions' => $adminObjectAclData->getUserPermissions(), 'object' => $object, 'users' => $aclUsers, 'roles' => $aclRoles, 'aclUsersForm' => $aclUsersForm->createView(), 'aclRolesForm' => $aclRolesForm->createView()), null, $request); }
/** * Filters with ACL * * @param AdminInterface $admin * @param ProxyQueryInterface $query * @param string $context * @throws \RuntimeException */ public function configureQuery(AdminInterface $admin, ProxyQueryInterface $query = null, $query2 = null, $context = 'list', $isTheMaster = false) { if (!$query) { $query = $query2; } // Don't filter for admins and for not ACL enabled classes and for command cli if (!$admin->isAclEnabled() && !method_exists($admin, 'getMasterAclClass') || !$this->securityContext->getToken() || $admin->isGranted(sprintf($admin->getSecurityHandler()->getBaseRole($admin), 'ADMIN'))) { return; } // Retrieve current logged user SecurityIdentity $user = $this->securityContext->getToken()->getUser(); $securityIdentity = UserSecurityIdentity::fromAccount($user); // Get identity ACL identifier $identifier = sprintf('%s-%s', $securityIdentity->getClass(), $securityIdentity->getUsername()); $identityStmt = $this->databaseConnection->prepare('SELECT id FROM acl_security_identities WHERE identifier = :identifier'); $identityStmt->bindValue('identifier', $identifier); $identityStmt->execute(); $identityId = $identityStmt->fetchColumn(); // Get class ACL identifier $classType = $admin->getClass(); $classStmt = $this->databaseConnection->prepare('SELECT id FROM acl_classes WHERE class_type = :classType'); $classStmt->bindValue('classType', $classType); $classStmt->execute(); $classId = $classStmt->fetchColumn(); if ($identityId && ($classId || method_exists($admin, 'getMasterAclClass'))) { $entriesStmt = $this->databaseConnection->prepare('SELECT object_identifier FROM acl_entries AS ae JOIN acl_object_identities AS aoi ON ae.object_identity_id = aoi.id WHERE ae.class_id = :classId AND ae.security_identity_id = :identityId AND (:view = ae.mask & :view OR :operator = ae.mask & :operator OR :master = ae.mask & :master OR :owner = ae.mask & :owner)'); $entriesStmt->bindValue('classId', $classId); $entriesStmt->bindValue('identityId', $identityId); $entriesStmt->bindValue('view', MaskBuilder::MASK_VIEW); $entriesStmt->bindValue('operator', MaskBuilder::MASK_OPERATOR); $entriesStmt->bindValue('master', MaskBuilder::MASK_MASTER); $entriesStmt->bindValue('owner', MaskBuilder::MASK_OWNER); $entriesStmt->execute(); $ids = array(); foreach ($entriesStmt->fetchAll() as $row) { $ids[] = $row['object_identifier']; } //Test if method getMasterAclClass and getMasterAclPath exist on the admin CLASS -> SEE THE DOC if (method_exists($admin, 'getMasterAclClass') && method_exists($admin, 'getMasterAclPath')) { $classStmt = $this->databaseConnection->prepare('SELECT id FROM acl_classes WHERE class_type = :classType'); //QUERY ON MASTER ACL CLASS (method $admin->getMasterAclClass() return a string like 'Acme\Bundle\Entity\MasterACLEntity'); $classStmt->bindValue('classType', $admin->getMasterAclClass()); $classStmt->execute(); $classId = $classStmt->fetchColumn(); $entriesStmt = $this->databaseConnection->prepare('SELECT object_identifier FROM acl_entries AS ae JOIN acl_object_identities AS aoi ON ae.object_identity_id = aoi.id WHERE ae.class_id = :classId AND ae.security_identity_id = :identityId AND (:view = ae.mask & :view OR :operator = ae.mask & :operator OR :master = ae.mask & :master OR :owner = ae.mask & :owner)'); $entriesStmt->bindValue('classId', $classId); $entriesStmt->bindValue('identityId', $identityId); $entriesStmt->bindValue('view', MaskBuilder::MASK_VIEW); $entriesStmt->bindValue('operator', MaskBuilder::MASK_OPERATOR); $entriesStmt->bindValue('master', MaskBuilder::MASK_MASTER); $entriesStmt->bindValue('owner', MaskBuilder::MASK_OWNER); $entriesStmt->execute(); //ARRAY OF idsMaster $idsMaster = array(); foreach ($entriesStmt->fetchAll() as $row) { $idsMaster[] = $row['object_identifier']; } $parents = $admin->getMasterAclPath(); //HERE UPDATE THE QUERY if (!$isTheMaster) { //HERE UPDATE THE QUERY foreach ($parents as $key => $parent) { //FIRST shorcut is 'o' if ($key == 0) { $query->leftJoin('o.' . $parent[0], $parent[1]); } else { //Shortcut is precedent shortcut $query->leftJoin($parents[$key - 1][1] . '.' . $parent[0], $parent[1]); } //HERE WE ARE AFTER THE LEFT JOIN ON MASTER ACL CLASS WE PASS idsMaster array param if ($key + 1 == count($parents)) { //HERE FOR OBJECT CREATED BY CURRENT USER AND WITH STRICT MODE IS OF if (count($ids) && method_exists($admin, 'getMasterAclStrict') && !$admin->getMasterAclStrict()) { //OR EXPRESSION WITH PARENTHESIS $orCondition = $query->expr()->orx(); $orCondition->add($query->expr()->in('o.id', ':ids')); $orCondition->add($query->expr()->in($parent[1] . '.id', ':idsMaster')); $query->andWhere($orCondition)->setParameter('ids', $ids)->setParameter('idsMaster', $idsMaster); } else { $query->andWhere($parent[1] . '.id IN (:idsMaster' . $key . ')')->setParameter('idsMaster' . $key, $idsMaster); } } } } else { $query->andWhere('o.id IN (:idsMaster)')->setParameter('idsMaster', $idsMaster); } return; } elseif (count($ids)) { //NORMAL BEHAVIOR $query->andWhere('o.id IN (:ids)')->setParameter('ids', $ids); return; } } // Display an empty list $query->andWhere('1 = 2'); }