AdminObjectAclManipulator.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <?php
  2. /*
  3. * This file is part of the Sonata Project package.
  4. *
  5. * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Sonata\AdminBundle\Util;
  11. use Symfony\Component\Form\FormFactoryInterface;
  12. use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
  13. use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
  14. use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
  15. /**
  16. * A manipulator for updating ACL related to an object.
  17. *
  18. * @author Kévin Dunglas <kevin@les-tilleuls.coop>
  19. */
  20. class AdminObjectAclManipulator
  21. {
  22. /**
  23. * @var \Symfony\Component\Form\FormFactoryInterface
  24. */
  25. protected $formFactory;
  26. /**
  27. * @var string
  28. */
  29. protected $maskBuilderClass;
  30. /**
  31. * @param \Symfony\Component\Form\FormFactoryInterface $formFactory
  32. * @param string $maskBuilderClass
  33. */
  34. public function __construct(FormFactoryInterface $formFactory, $maskBuilderClass)
  35. {
  36. $this->formFactory = $formFactory;
  37. $this->maskBuilderClass = $maskBuilderClass;
  38. }
  39. /**
  40. * Gets mask builder class name.
  41. *
  42. * @return string
  43. */
  44. public function getMaskBuilderClass()
  45. {
  46. return $this->maskBuilderClass;
  47. }
  48. /**
  49. * Gets the form.
  50. *
  51. * @param \Sonata\AdminBundle\Util\AdminObjectAclData $data
  52. *
  53. * @return \Symfony\Component\Form\Form
  54. */
  55. public function createForm(AdminObjectAclData $data)
  56. {
  57. // Retrieve object identity
  58. $objectIdentity = ObjectIdentity::fromDomainObject($data->getObject());
  59. $acl = $data->getSecurityHandler()->getObjectAcl($objectIdentity);
  60. if (!$acl) {
  61. $acl = $data->getSecurityHandler()->createAcl($objectIdentity);
  62. }
  63. $data->setAcl($acl);
  64. $masks = $data->getMasks();
  65. // Create a form to set ACL
  66. $formBuilder = $this->formFactory->createBuilder('form');
  67. foreach ($data->getAclUsers() as $aclUser) {
  68. $securityIdentity = UserSecurityIdentity::fromAccount($aclUser);
  69. foreach ($data->getUserPermissions() as $permission) {
  70. try {
  71. $checked = $acl->isGranted(array($masks[$permission]), array($securityIdentity));
  72. } catch (NoAceFoundException $e) {
  73. $checked = false;
  74. }
  75. $formBuilder->add($aclUser->getId().$permission, 'checkbox', array('required' => false, 'data' => $checked));
  76. }
  77. }
  78. $form = $formBuilder->getForm();
  79. $data->setForm($form);
  80. return $form;
  81. }
  82. /**
  83. * Updates ACL.
  84. *
  85. * @param \Sonata\AdminBundle\Util\AdminObjectAclData $data
  86. */
  87. public function updateAcl(AdminObjectAclData $data)
  88. {
  89. foreach ($data->getAclUsers() as $aclUser) {
  90. $securityIdentity = UserSecurityIdentity::fromAccount($aclUser);
  91. $maskBuilder = new $this->maskBuilderClass();
  92. foreach ($data->getUserPermissions() as $permission) {
  93. if ($data->getForm()->get($aclUser->getId().$permission)->getData()) {
  94. $maskBuilder->add($permission);
  95. }
  96. }
  97. $masks = $data->getMasks();
  98. $acl = $data->getAcl();
  99. // Restore OWNER and MASTER permissions
  100. if (!$data->isOwner()) {
  101. foreach ($data->getOwnerPermissions() as $permission) {
  102. if ($acl->isGranted(array($masks[$permission]), array($securityIdentity))) {
  103. $maskBuilder->add($permission);
  104. }
  105. }
  106. }
  107. $mask = $maskBuilder->get();
  108. $index = null;
  109. $ace = null;
  110. foreach ($acl->getObjectAces() as $currentIndex => $currentAce) {
  111. if ($currentAce->getSecurityIdentity()->equals($securityIdentity)) {
  112. $index = $currentIndex;
  113. $ace = $currentAce;
  114. break;
  115. }
  116. }
  117. if ($ace) {
  118. $acl->updateObjectAce($index, $mask);
  119. } else {
  120. $acl->insertObjectAce($securityIdentity, $mask);
  121. }
  122. }
  123. $data->getSecurityHandler()->updateAcl($acl);
  124. }
  125. }