Dzięki za pomoc. Athabus zrobilem to przy pomocy Voterów i raczej nie będzie potrzebne inne rozwiązanie. Jest mi to potrzebne do ustalania dostępu do danej akcji dla id grupy użytkownika z bazy danych ( administrator ma dostęp do wszystkich akcji, moderator do wybranych itd.) i administrowania dostępem poprzez bazę danych. Dodatkowo udało mi się stworzyć dodawanie indywidualnych uprawnień do akcji dla danego użytkownika. Jutro postaram się wrzucić moje rozwiązanie.
Poniżej udostępniam voter sprawdzający uprawnienia do akcji dla rangi użytkownika oraz uprawnienia do akcji dla id użytkownika. Voter operuje na dwóch tabelach. Jeżeli nie zostanie znalezione id rangi użytkownika w jednej tabeli to szuka id uprawnionego użytkownika w drugiej tabeli.
<?php
/**
* Created by PhpStorm.
* User: E
* Date: 23.09.2018
* Time: 19:54
*/
namespace AppBundle\Security;
use AppBundle\Entity\Pageroutes;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class RankroutesVoter extends Voter
{
const EDIT = 'edit';
private $entityManager;
private $request;
public function __construct(EntityManagerInterface $entityManager, RequestStack $requestStack)
{
$this->entityManager = $entityManager;
$this->request = $requestStack->getCurrentRequest()->attributes->get('_route');
}
/**
* Determines if the attribute and subject are supported by this voter.
*
* @param string $attribute An attribute
* @param mixed $subject The subject to secure, e.g. an object the user wants to access or any other PHP type
*
* @return bool True if the attribute and subject are supported, false otherwise
*/
protected function supports($attribute, $subject)
{
return false;
}
return true;
}
/**
* Perform a single access check operation on a given attribute, subject and token.
* It is safe to assume that $attribute and $subject already passed the "supports()" method check.
*
* @param string $attribute
* @param mixed $subject
* @param TokenInterface $token
*
* @return bool
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
//get current user
$user = $token->getUser();
//get repository
$pageroutes = $this->entityManager->getRepository(Pageroutes::class);
//check that logged user rank is granted to actual request route
$findroute = $pageroutes->findPageroutesRankRoute($user, $this->request);
//check that logged user id is granted to actual request route
$finduserroute = $pageroutes->findUserranksRankRoute($user, $this->request);
$getPageroutesData = null;
foreach($findroute as $userRankId)
{
foreach($userRankId->getRankid() as $fielddata)
{
$getPageroutesData = $fielddata;
}
}
foreach($finduserroute as $userRankId)
{
$getPageroutesData = $userRankId;
}
switch ($attribute) {
case self::EDIT:
// if the user rank is granted to pageroute allow them to edit page
if ($user->getRankid() === (object)$getPageroutesData) {
return true;
}
// if the user id is granted to pageroute allow them to edit page
if ($user === (object)$getPageroutesData) {
return true;
}
return false;
break;
}
return false;
}
}
poniżej fragmenty repozytorium, odpowiedzialne za wyszukiwanie id rangi lub id użytkownika, dla którego mają zostać przyznane uprawnienia do akcji:
PageroutesRepository.php:
/**
* @param Users $users
* @param $string
* @return array
*/
public function findPageroutesRankRoute(Users $users, $string)
{
return $this->getEntityManager()
->createQuery(
"SELECT p
FROM AppBundle:Pageroutes p
LEft Join p.rankid a
WHERE a.rankid = :rankid
And p.routename = :routename"
)
->setParameter("rankid", $users->getRankid())
->setParameter("routename", $string)
->getResult();
}
/**
* @param Users $users
* @param $string
* @return array
*/
public function findUserranksRankRoute(Users $users, $string)
{
return $this->getEntityManager()
->createQuery(
"SELECT u
FROM AppBundle:Users u
LEft Join u.routeid r
WHERE u.userid = :userid
And r.routename = :routename"
)
->setParameter("userid", $users->getUserid())
->setParameter("routename", $string)
->getResult();
}
Wszytko działa tylko, że problem pojawi się w momencie, gdy będę chciał zmienić nazwę stałej wywołującej określone działanie votera. Wtedy będę musiał ją zmienić we wszystkich akcjach, w których doczepiłem adnotację @security. Oczywiście nie będzie problemem wyedytowanie tych nazw ale jak będę miał 200 lub więcej akcji to zajmie to trochę czasu