AdminObjectAclManipulator.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. <?php
  2. /*
  3. * This file is part of the Sonata project.
  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\Exception\NoAceFoundException;
  14. use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
  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. * @return \Symfony\Component\Form\Form
  53. */
  54. public function createForm(AdminObjectAclData $data)
  55. {
  56. // Retrieve object identity
  57. $objectIdentity = ObjectIdentity::fromDomainObject($data->getObject());
  58. $acl = $data->getSecurityHandler()->getObjectAcl($objectIdentity);
  59. if (!$acl) {
  60. $acl = $this->getSecurityHandler()->createAcl($objectIdentity);
  61. }
  62. $data->setAcl($acl);
  63. $masks = $data->getMasks();
  64. // Create a form to set ACL
  65. $formBuilder = $this->formFactory->createBuilder('form');
  66. foreach ($data->getAclUsers() as $aclUser) {
  67. $securityIdentity = UserSecurityIdentity::fromAccount($aclUser);
  68. foreach ($data->getUserPermissions() as $permission) {
  69. try {
  70. $checked = $acl->isGranted(array($masks[$permission]), array($securityIdentity));
  71. } catch (NoAceFoundException $e) {
  72. $checked = false;
  73. }
  74. $formBuilder->add($aclUser->getId() . $permission, 'checkbox', array('required' => false, 'data' => $checked));
  75. }
  76. }
  77. $form = $formBuilder->getForm();
  78. $data->setForm($form);
  79. return $form;
  80. }
  81. /**
  82. * Updates ACL
  83. *
  84. * @param \Sonata\AdminBundle\Util\AdminObjectAclData $data
  85. */
  86. public function updateAcl(AdminObjectAclData $data)
  87. {
  88. foreach ($data->getAclUsers() as $aclUser) {
  89. $securityIdentity = UserSecurityIdentity::fromAccount($aclUser);
  90. $maskBuilder = new $this->maskBuilderClass();
  91. foreach ($data->getUserPermissions() as $permission) {
  92. if ($data->getForm()->get($aclUser->getId() . $permission)->getData()) {
  93. $maskBuilder->add($permission);
  94. }
  95. }
  96. $masks = $data->getMasks();
  97. $acl = $data->getAcl();
  98. // Restore OWNER and MASTER permissions
  99. if (!$data->isOwner()) {
  100. foreach ($data->getOwnerPermissions() as $permission) {
  101. if ($acl->isGranted(array($masks[$permission]), array($securityIdentity))) {
  102. $maskBuilder->add($permission);
  103. }
  104. }
  105. }
  106. $mask = $maskBuilder->get();
  107. $index = null;
  108. $ace = null;
  109. foreach ($acl->getObjectAces() as $currentIndex => $currentAce) {
  110. if ($currentAce->getSecurityIdentity()->equals($securityIdentity)) {
  111. $index = $currentIndex;
  112. $ace = $currentAce;
  113. break;
  114. }
  115. }
  116. if ($ace) {
  117. $acl->updateObjectAce($index, $mask);
  118. } else {
  119. $acl->insertObjectAce($securityIdentity, $mask);
  120. }
  121. }
  122. $data->getSecurityHandler()->updateAcl($acl);
  123. }
  124. }