Added Role hierarchy service.
Signed-off-by: Gergely Polonkai <polesz@w00d5t0ck.info>
This commit is contained in:
		
							
								
								
									
										32
									
								
								app/DoctrineMigrations/Version20120815091637.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/DoctrineMigrations/Version20120815091637.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Application\Migrations; | ||||
|  | ||||
| use Doctrine\DBAL\Migrations\AbstractMigration, | ||||
|     Doctrine\DBAL\Schema\Schema; | ||||
|  | ||||
| /** | ||||
|  * Auto-generated Migration: Please modify to your need! | ||||
|  */ | ||||
| class Version20120815091637 extends AbstractMigration | ||||
| { | ||||
|     public function up(Schema $schema) | ||||
|     { | ||||
|         // this up() migration is autogenerated, please modify it to your needs | ||||
|         $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql"); | ||||
|          | ||||
|         $this->addSql("CREATE TABLE role_hierarchy (parent_role_id INT NOT NULL, child_role_id INT NOT NULL, INDEX IDX_AB8EFB72A44B56EA (parent_role_id), INDEX IDX_AB8EFB72B4B76AB7 (child_role_id), PRIMARY KEY(parent_role_id, child_role_id)) ENGINE = InnoDB"); | ||||
|         $this->addSql("ALTER TABLE role_hierarchy ADD CONSTRAINT FK_AB8EFB72A44B56EA FOREIGN KEY (parent_role_id) REFERENCES roles (id)"); | ||||
|         $this->addSql("ALTER TABLE role_hierarchy ADD CONSTRAINT FK_AB8EFB72B4B76AB7 FOREIGN KEY (child_role_id) REFERENCES roles (id)"); | ||||
|         $this->addSql("ALTER TABLE roles DROP admin, DROP superAdmin"); | ||||
|     } | ||||
|  | ||||
|     public function down(Schema $schema) | ||||
|     { | ||||
|         // this down() migration is autogenerated, please modify it to your needs | ||||
|         $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql"); | ||||
|          | ||||
|         $this->addSql("DROP TABLE role_hierarchy"); | ||||
|         $this->addSql("ALTER TABLE roles ADD admin TINYINT(1) NOT NULL, ADD superAdmin TINYINT(1) NOT NULL"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| <?php | ||||
| namespace KekRozsak\SecurityBundle\DependencyInjection\Compiler; | ||||
|  | ||||
| use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; | ||||
| use Symfony\Component\DependencyInjection\ContainerBuilder; | ||||
| use Symfony\Component\DependencyInjection\Reference; | ||||
|  | ||||
| class OverrideServiceCompilerPass implements CompilerPassInterface | ||||
| { | ||||
| 	public function process(ContainerBuilder $container) | ||||
| 	{ | ||||
| 		$definition = $container->getDefinition('security.role_hierarchy'); | ||||
| 		$definition->setClass('KekRozsak\SecurityBundle\Service\RoleHierarchy'); | ||||
| 		$definition->setArguments(array(new Reference('doctrine'))); | ||||
| 	} | ||||
| } | ||||
| @@ -78,62 +78,6 @@ class Role implements RoleInterface | ||||
| 		return $this; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @var boolean $admin | ||||
| 	 * @ORM\Column(type="boolean", nullable=false) | ||||
| 	 */ | ||||
| 	protected $admin; | ||||
|  | ||||
| 	/** | ||||
| 	 * Set admin | ||||
| 	 * | ||||
| 	 * @param boolean $admin | ||||
| 	 * @return Role | ||||
| 	 */ | ||||
| 	public function setAdmin($admin) | ||||
| 	{ | ||||
| 		$this->admin = $admin; | ||||
| 		return $this; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Get admin | ||||
| 	 * | ||||
| 	 * @return boolean | ||||
| 	 */ | ||||
| 	public function isAdmin() | ||||
| 	{ | ||||
| 		return $this->admin; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @var boolean $superadmin | ||||
| 	 * @ORM\Column(type="boolean", nullable=false) | ||||
| 	 */ | ||||
| 	protected $superAdmin; | ||||
|  | ||||
| 	/** | ||||
| 	 * Set superadmin | ||||
| 	 * | ||||
| 	 * @param boolean $superadmin | ||||
| 	 * @return Role | ||||
| 	 */ | ||||
| 	public function setSuperadmin($superadmin) | ||||
| 	{ | ||||
| 		$this->superadmin = $superadmin; | ||||
| 		return $this; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Get superadmin | ||||
| 	 * | ||||
| 	 * @return boolean | ||||
| 	 */ | ||||
| 	public function getSuperadmin() | ||||
| 	{ | ||||
| 		return $this->superadmin; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @var text description | ||||
| 	 * @ORM\Column(type="string", length=150, nullable=true) | ||||
| @@ -199,5 +143,27 @@ class Role implements RoleInterface | ||||
| 	{ | ||||
| 		return $this->shortDescription; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * List of inherited Roles | ||||
| 	 * | ||||
| 	 * @ORM\ManyToMany(targetEntity="Role", fetch="LAZY") | ||||
| 	 * @ORM\JoinTable(name="role_hierarchy", joinColumns={ | ||||
| 	 *     @ORM\JoinColumn(name="parent_role_id", referencedColumnName="id") | ||||
| 	 * }, inverseJoinColumns={ | ||||
| 	 *     @ORM\JoinColumn(name="child_role_id", referencedColumnName="id") | ||||
| 	 * }) | ||||
| 	 */ | ||||
| 	protected $inheritedRoles; | ||||
|  | ||||
| 	/** | ||||
| 	 * Get all inherited roles | ||||
| 	 * | ||||
| 	 * @return Doctrine\Common\Collections\ArrayCollection | ||||
| 	 */ | ||||
| 	public function getInheritedRoles() | ||||
| 	{ | ||||
| 		return $this->inheritedRoles; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -323,7 +323,18 @@ class User implements UserInterface, AdvancedUserInterface | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Get all roles | ||||
| 	 * Get all roles as an ArrayCollection | ||||
| 	 * | ||||
| 	 * @return Doctrine\Common\Collections\ArrayCollection | ||||
| 	 */ | ||||
| 	public function getRolesCollection() | ||||
| 	{ | ||||
| 		return $this->roles; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Get all roles, for UserInterface implementation. To get the | ||||
| 	 * collection, use getRolesCollection() instead | ||||
| 	 * | ||||
| 	 * @return array | ||||
| 	 */ | ||||
|   | ||||
| @@ -3,7 +3,15 @@ | ||||
| namespace KekRozsak\SecurityBundle; | ||||
|  | ||||
| use Symfony\Component\HttpKernel\Bundle\Bundle; | ||||
| use Symfony\Component\DependencyInjection\ContainerBuilder; | ||||
|  | ||||
| use KekRozsak\SecurityBundle\DependencyInjection\Compiler\OverrideServiceCompilerPass; | ||||
|  | ||||
| class KekRozsakSecurityBundle extends Bundle | ||||
| { | ||||
| 	public function build(ContainerBuilder $container) | ||||
| 	{ | ||||
| 		parent::build($container); | ||||
| 		$container->addCompilerPass(new OverrideServiceCompilerPass()); | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										57
									
								
								src/KekRozsak/SecurityBundle/Service/RoleHierarchy.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/KekRozsak/SecurityBundle/Service/RoleHierarchy.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| <?php | ||||
|  | ||||
| namespace KekRozsak\SecurityBundle\Service; | ||||
|  | ||||
| use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; | ||||
| use Symfony\Bridge\Doctrine\RegistryInterface; | ||||
|  | ||||
| class RoleHierarchy implements RoleHierarchyInterface | ||||
| { | ||||
|     private $hierarchy; | ||||
|     private $roleRepo; | ||||
|     private $map; | ||||
|      | ||||
|     public function __construct(RegistryInterface $doctrine) | ||||
|     { | ||||
|         $this->hierarchy = array(); | ||||
|         $this->roleRepo = $doctrine->getRepository('KekRozsakSecurityBundle:Role'); | ||||
|          | ||||
|         $this->buildRoleMap(); | ||||
|     } | ||||
|      | ||||
|     public function getReachableRoles(array $roles) | ||||
|     { | ||||
|         $reachableRoles = array(); | ||||
|         foreach ($roles as $role) { | ||||
|             if (!isset($this->map[$role->getRole()])) { | ||||
|                 continue; | ||||
|             } | ||||
|              | ||||
|             foreach ($this->map[$role->getRole()] as $r) { | ||||
|                 if (($childRole = $this->roleRepo->findOneByName($r)) !== null) { | ||||
|                     $reachableRoles[] = $childRole; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         return $reachableRoles; | ||||
|     } | ||||
|      | ||||
|     private function buildRoleMap() | ||||
|     { | ||||
|         $this->map = array(); | ||||
|         $roles = $this->roleRepo->findAll(); | ||||
|         foreach ($roles as $mainRole) { | ||||
|             $main = $mainRole->getRole(); | ||||
|             $this->map[$main] = array(); | ||||
|             foreach ($mainRole->getInheritedRoles() as $childRole) { | ||||
|                 $this->map[$main][] = $childRole->getRole(); | ||||
|                 // TODO: This is one-level only. Get as deep as possible. | ||||
|                 // BEWARE OF RECURSIVE NESTING! | ||||
|                 foreach ($childRole->getInheritedRoles() as $grandchildRole) { | ||||
|                     $this->map[$main][] = $grandchildRole->getRole(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user