Reputation: 1369
Okay, i'm trying to check if an user has a specific role, i did this
however, when i do this:
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('nombre',null,array('label' => 'Usuario'))
->add('email')
->add('password', 'repeated', array(
'type' => 'password',
'invalid_message' => 'Los campos deben coincidir',
'first_name' => 'password',
'second_name' => 'confirmar password',
'options' => array('required' => false)
))
->add('cliente', 'entity', array(
'class' => 'ClientesBundle:Cliente',
'empty_value' => 'Company',
'required' => false,
'empty_data' => null)
**)**
$user = $this->securityContext->getToken()->getUser();
**if ($user->getRol() == 'ROLE_SUPER_ADMIN'){**
->add('rol')
**}**
;
}
tried this as well:
**if ($this->securityContext->getToken()->getUser()->getRol() === 'ROLE_SUPER_ADMIN'){**
->add('rol')
**}**
the bolded lines (the ones with **) have the tiny red line that indicates an error, and it's says unexpected if... How do i fix this?
Upvotes: 13
Views: 13914
Reputation: 1372
I know this is an old question, but I'd like to put forward a better alternative for checking roles inside a form type.
The issue with using the TokenInterface and the User object is that it does not check for inheritance. For example, consider the following security.yml
:
security:
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
If your user has ROLE_SUPER_ADMIN
but not ROLE_ADMIN
added to their roles, the above solutions will fail if you are using $user->hasRole('ROLE_ADMIN')
, as the user does not explicitly have ROLE_ADMIN
assigned to their user and hasRole()
does not check hierarchy.
Use the AuthorizationCheckerInterface
instead to gain access to the isGranted()
function.
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
class MyFormType extends AbstractType {
protected $auth;
public function __construct(AuthorizationCheckerInterface $auth) {
$this->auth = $auth;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
// ...
if($this->auth->isGranted('ROLE_ADMIN')) {
// Do the thing here
}
}
}
This will respect any hierarchy defined in security.yml
. If we use the same yml file as above, $auth->isGranted('ROLE_ADMIN')
will return true if a user has ROLE_SUPER_ADMIN
but not ROLE_ADMIN
assigned to their profile.
The previous solution will still work in Symfony 5 and and above, however there are a few tweaks that can be made given Symfony 5's recommendations.
Security
is now preferred over AuthorizationCheckerInterface
, and if using PHP 8, you can use Constructor Promotion
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Security;
class MyFormType extends AbstractType {
public function __construct(protected Security $security) {
}
public function buildForm(FormBuilderInterface $builder, array $options) {
// ...
if($this->security->isGranted('ROLE_ADMIN')) {
// Do the thing here
}
}
}
Upvotes: 8
Reputation: 367
I succeed in doing this thing without pass to a service in symfony 3.4. I know my method is not the most "professionnal" but it is simple and it works.
First, send the user in your formType from your controller
$form = $this->get('form.factory')->create(addPlanExpectedType::class, $business,
array('user' => $this->getUser())
);
Secondly, recover the roles, and verify if "ROLE_AMIN" is in this $roles array
public function buildForm(FormBuilderInterface $builder, array $options)
{
$businessId = $options['data']->getId();
$user = $options['user'];
$roles = $user->getRoles();
$boolAdmin = in_array('ROLE_ADMIN', $roles);
Upvotes: 1
Reputation: 8372
If you declare your form type as a service, you can inject the token storage in your class.
So you declare the service in services.yml
like this:
my_form:
class: AppBundle\Services\MyFormType
public: true
arguments: ['@security.token_storage']
And the form class like this:
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
class MyFormType extends AbstractType
{
protected $tokenStorage;
public function __construct(TokenStorage $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$user = $this->tokenStorage->getToken()->getUser();
// Use the user object to build the form
}
}
Upvotes: 16
Reputation: 17986
From controller you have to pass user object to form builder
$form = $this->createForm(
new YourType(),
$data,
array('user' => $this->getUser())
);
Then in form builder you can fetch it from $options
:
public function buildForm(FormBuilder $builder, array $options)
{
$user = $options['user']
}
Don't forget to extend setDefaultOptions()
with user
index:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
...
'user' => null
));
}
Upvotes: 17