EditableRolesBuilder.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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\UserBundle\Security;
  11. use Sonata\AdminBundle\Admin\Pool;
  12. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  13. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  14. use Symfony\Component\Security\Core\SecurityContextInterface;
  15. class EditableRolesBuilder
  16. {
  17. /**
  18. * @var TokenStorageInterface|SecurityContextInterface
  19. */
  20. protected $tokenStorage;
  21. /**
  22. * @var AuthorizationCheckerInterface|SecurityContextInterface
  23. */
  24. protected $authorizationChecker;
  25. /**
  26. * @var Pool
  27. */
  28. protected $pool;
  29. /**
  30. * @var array
  31. */
  32. protected $rolesHierarchy;
  33. /**
  34. * NEXT_MAJOR: Go back to type hinting check when bumping requirements to SF 2.6+.
  35. *
  36. * @param TokenStorageInterface|SecurityContextInterface $tokenStorage
  37. * @param AuthorizationCheckerInterface|SecurityContextInterface $authorizationChecker
  38. * @param Pool $pool
  39. * @param array $rolesHierarchy
  40. */
  41. public function __construct($tokenStorage, $authorizationChecker, Pool $pool, array $rolesHierarchy = array())
  42. {
  43. if (!$tokenStorage instanceof TokenStorageInterface && !$tokenStorage instanceof SecurityContextInterface) {
  44. throw new \InvalidArgumentException(
  45. 'Argument 1 should be an instance of Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface or Symfony\Component\Security\Core\SecurityContextInterface'
  46. );
  47. }
  48. if (!$authorizationChecker instanceof AuthorizationCheckerInterface && !$authorizationChecker instanceof SecurityContextInterface) {
  49. throw new \InvalidArgumentException(
  50. 'Argument 2 should be an instance of Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface or Symfony\Component\Security\Core\SecurityContextInterface'
  51. );
  52. }
  53. $this->tokenStorage = $tokenStorage;
  54. $this->authorizationChecker = $authorizationChecker;
  55. $this->pool = $pool;
  56. $this->rolesHierarchy = $rolesHierarchy;
  57. }
  58. /**
  59. * @return array
  60. */
  61. public function getRoles()
  62. {
  63. $roles = array();
  64. $rolesReadOnly = array();
  65. if (!$this->tokenStorage->getToken()) {
  66. return array($roles, $rolesReadOnly);
  67. }
  68. // get roles from the Admin classes
  69. foreach ($this->pool->getAdminServiceIds() as $id) {
  70. try {
  71. $admin = $this->pool->getInstance($id);
  72. } catch (\Exception $e) {
  73. continue;
  74. }
  75. $isMaster = $admin->isGranted('MASTER');
  76. $securityHandler = $admin->getSecurityHandler();
  77. // TODO get the base role from the admin or security handler
  78. $baseRole = $securityHandler->getBaseRole($admin);
  79. if (strlen($baseRole) == 0) { // the security handler related to the admin does not provide a valid string
  80. continue;
  81. }
  82. foreach ($admin->getSecurityInformation() as $role => $permissions) {
  83. $role = sprintf($baseRole, $role);
  84. if ($isMaster) {
  85. // if the user has the MASTER permission, allow to grant access the admin roles to other users
  86. $roles[$role] = $role;
  87. } elseif ($this->authorizationChecker->isGranted($role)) {
  88. // although the user has no MASTER permission, allow the currently logged in user to view the role
  89. $rolesReadOnly[$role] = $role;
  90. }
  91. }
  92. }
  93. $isMaster = $this->authorizationChecker->isGranted(
  94. $this->pool->getOption('role_super_admin', 'ROLE_SUPER_ADMIN')
  95. );
  96. // get roles from the service container
  97. foreach ($this->rolesHierarchy as $name => $rolesHierarchy) {
  98. if ($this->authorizationChecker->isGranted($name) || $isMaster) {
  99. $roles[$name] = $name.': '.implode(', ', $rolesHierarchy);
  100. foreach ($rolesHierarchy as $role) {
  101. if (!isset($roles[$role])) {
  102. $roles[$role] = $role;
  103. }
  104. }
  105. }
  106. }
  107. return array($roles, $rolesReadOnly);
  108. }
  109. }