Tak ACL jest drogą do zrobienia. utwórz usługę CompanyVoter implementującą VoterInterface i sprawdź, czy użytkownik znajduje się w tej samej firmie w ramach metody vote().
wpis do książki kucharskiej "How to implement your own Voter to blacklist IP Addresses" stanowi dobre wprowadzenie.
zmienić strategię "dostęp-decyzja-menedżer" na "jednomyślność". Oznacza to, że jeśli tylko jeden głosujący odmawia dostępu (np. CompanyVoter), dostęp nie jest przyznawany użytkownikowi końcowemu.
# app/config/security.yml
security:
access_decision_manager:
strategy: unanimous
teraz tworzyć Wyborcy
// src/Acme/AcmeBundle/YourBundle/Security/Authorization/Voter/CompanyVoter.php
namespace Acme\YourBundle\Security\Authorization\Voter;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Acme\YourUserBundleBundle\Entity\User;
use Symfony\Component\Security\Core\User\UserInterface;
class CompanyVoter implements VoterInterface
{
private $container;
public function __construct($container)
{
$this->container = $container;
}
public function supportsAttribute($attribute)
{
return in_array($attribute, array(
'EDIT',
'ACTIVATE',
// ...
));
}
public function supportsClass($class)
{
return in_array("FOS\UserBundle\Model\UserInterface", class_implements($class));
}
public function vote(TokenInterface $token, $object, array $attributes)
{
if (!($this->supportsClass(get_class($object)))) {
return VoterInterface::ACCESS_ABSTAIN;
}
foreach ($attributes as $attribute) {
if (!$this->supportsAttribute($attribute)) {
return VoterInterface::ACCESS_ABSTAIN;
}
}
$user = $token->getUser();
if (!($user instanceof UserInterface)) {
return VoterInterface::ACCESS_DENIED;
}
// check if the user has the same company
if ($user->getCompany() == $object->getCompany()) {
return VoterInterface::ACCESS_GRANTED;
}
return VoterInterface::ACCESS_DENIED;
}
}
Wreszcie zarejestrować jako wyborcy jako usługa
# src/Acme/AcmeBundle/Resources/config/services.yml
services:
security.access.company_voter:
class: Acme\YourBundle\Security\Authorization\Voter\CompanyVoter
public: false
tags:
- { name: security.voter }
... teraz używać go w szablonie gałązka
{% if is_granted('EDIT', user) %}<a href="#">Edit</a>{% endif %}
{% if is_granted('ACTIVATE', user) %}<a href="#">activate</a>{% endif %}
lub w kontrolerze ...
public function editAction(UserInterface $user)
{
if ($this->get('security.context')->isGranted('EDIT',$user)) {
throw new \Symfony\ComponentSecurity\Core\Exception\AccessDeniedException();
}
}
lub używając JMSSecurityExtraBundle ...
/**
* @SecureParam(name="user", permissions="EDIT")
*/
public function editUser(UserInterface $user)
{
// ...
}
Próbowałem w ten sposób, że pracuje dla edycji (uniemożliwia wydanie dla innych firm), ale nadal wyświetla listę wszystkich użytkowników. Wygląda na to, że wyborca nie jest wezwany do wyświetlenia linii. –
co masz na myśli wyświetlając linię? – nifr
Ponieważ muszę pokazywać tylko niektórych użytkowników w siatce list, nie powinien być wyświetlany żaden wiersz (zamiast pojawiać się tylko do odczytu) Uwaga Mówię o siatce SonataAdmin –