我们说我有一个Book
实体,其字段为$grantedTo
,内容为用户角色。
此字段允许根据用户角色授予或拒绝对书籍的访问。
让我们考虑另一个名为Library
的实体与OneToMany
关系$books
。
现在从树枝上看,我想这样做:
{{ myLibrary.grantedBooks }}
grantedBooks
方法会返回允许用户查看的所有图书馆图书。
但是要在我的类库中构建这样的方法,我需要调用像isGranted($book->grantedTo)
这样的东西,我认为这是不可能的,因为我无法从我的实体中访问安全上下文
所以我想我应该提供一个服务,我会注入安全上下文,并从Twig访问这个服务。
我不确定这是最好的解决方案,并且很高兴听到其他可能性。
答案 0 :(得分:1)
您可以在Library类中添加一个getter,如下所示:
public function getGrantedBook($role) {
return array_filter($this->books, function(Book $book) use($role){
return $book->getGrantedTo() == $role;
});
}
在您的观点中,您需要将其传递给当前用户的角色。
修改强>
如果你需要处理具有高级角色的用户的情况,我建议使用一个doctrine实体监听器并将@ security.role_hierarchy和@token_storage注入其中,然后在onPostLoad事件中你可以放置你的逻辑:
<service id="my_bundle.library_listener" class="AppBundle\EntityListener\LibraryListener">
<tag name="doctrine.orm.entity_listener" entity="AppBundle\Entity\Library" event="postLoad" />
<argument type="service" id="security.token_storage" />
<argument type="service" id="security.role_hierarchy" />
</service>
在你的听众中:
class LibraryListener {
private $roleHierarchy;
private $tokenStorage;
//Constructor...
/**
* @param Library $library
* @param LifecycleEventArgs $eventArgs
*/
public function postLoad(Library $library, LifecycleEventArgs $eventArgs)
{
$currentUser = $this->tokenStorage->getToken()->getUser();
$library->setGrantedBooks(array_filter($library->getBooks(), function($book) use($currentUser){
return $this->isGranted($book, $currentUser);
}));
}
/**
* isGranted
*
* @param Book $book
* @param $user
* @return bool
*/
private function isGranted($book, $user) {
$role = new Role($book->getGrantedTo();
foreach($user->getRoles() as $userRole) {
if (in_array($role, $this->roleHierarchy->getReachableRoles(array(new Role($userRole)))))
return true;
}
return false;
}
}
显然,您需要在Library类中添加getGrantedBooks方法,希望这会有所帮助!