The controller for URI is not callable - symfony

I'm working on Symfony 2 and create a new action named "newAction" in "UserController":
/**
* #Route("/new", name="user_new")
*/
public function newAction()
{
if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
return $this->forward('RikkeiLunchOrderBundle:User:access_denied.html.twig', Array());
}
}
I want to check if the user has role Admin to create a new user. But I got this error(when user is not an admin):
The controller for URI "/user/new" is not callable.
500 Internal Server Error - InvalidArgumentException
Below is access_control and role_hierarchy in security.yml:
access_control:
- { path: ^/user/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/user/list, roles: ROLE_ADMIN }
- { path: ^/user/delete, roles: ROLE_ADMIN }
- { path: ^/order/dish/new, roles: ROLE_ADMIN }
- { path: ^/API/admin/, roles: ROLE_ADMIN }
- { path: ^/, roles: ROLE_USER }
role_hierarchy:
ROLE_ADMIN: ROLE_USER
Please help if you know the solution!

Related

Symfony Role and security explained

I'm trying to learn the Symfony roles and security. My current security.yml file, looks like this:
role_hierarchy:
ROLE_USER: ROLE_DO_ALMOST_NOTHING
ROLE_EDITOR: [ ROLE_USER, ROLE_ALLOWED_TO_EDIT ]
ROLE_CONTRIBUTOR: [ ROLE_EDITOR, ROLE_ALLOWED_TO_CONTRIBUTE ]
ROLE_ADMIN: [ ROLE_CONTRIBUTOR ]
ROLE_SUPER_ADMIN: [ ROLE_ADMIN, ROLE_ALLOWED_TO_DO_ANY_THING ]
access_control:
- { path: ^/admin, roles: ROLE_USER }
- { path: ^/admin/editor, roles: ROLE_ADMIN }
- { path: ^/editor, roles: ROLE_EDITOR }
- { path: ^/contributor, roles: ROLE_CONTRIBUTOR }
- { path: ^/super, roles: ROLE_SUPER_ADMIN }
And I'm using this setup for my users:
providers:
in_memory:
memory:
users:
person:
password: password!
roles: 'ROLE_USER'
admin:
password: password2
roles: 'ROLE_ADMIN'
Here is my problem. I'm been missing around with the access_control portion of security, however, the path ^/admin/editor with the roles marked as ROLE_ADMIN will allow the user person to access the route even though the person user didn't have the role of ROLE_ADMIN. I was wondering if this is because the route itself is shared by the same controller as the ^admin route? Or done someone see where I might have gone wrong with the code, since the user person can access the route that I they shouldn't.
The other routes:
- { path: ^/editor, roles: ROLE_EDITOR }
- { path: ^/contributor, roles: ROLE_CONTRIBUTOR }
- { path: ^/super, roles: ROLE_SUPER_ADMIN }
Work as expected.
The issue is you are matching /admin before you match admin/editor, and that only requires the ROLE_USER role. When you have:
- { path: ^/admin, roles: ROLE_USER }
That matches everything that starts with /admin, including admin/editor. As soon as Symfony finds the appropriate route it will not check the first of them.
So your ^/admin/editor/ check is never reached. Try this instead:
access_control:
- { path: ^/admin/editor, roles: ROLE_ADMIN }
- { path: ^/admin, roles: ROLE_USER }
- { path: ^/editor, roles: ROLE_EDITOR }
- { path: ^/contributor, roles: ROLE_CONTRIBUTOR }
- { path: ^/super, roles: ROLE_SUPER_ADMIN }
As a good rule of thumb, your most granular/specific routes should be put first. Any sub-routes should always be put ahead of the main route.

Symfony app login and Sonata admin dashboard login

In my app I have 2 parts, a frontend generated manually and a backend dashboard generated with Sonata admin. And I have an issue with the login of both parts:
app/config/security.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
m_and_m\UsuariosBundle\Entity\Usuarios: { algorithm: sha512, iterations: 10 }
m_and_m\ClientesBundle\Entity\Clientes: { algorithm: sha512, iterations: 10 }
access_control:
# URL of FOSUserBundle which need to be available to anonymous users
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
# Admin login page needs to be access without credential
- { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY }
# Secured part of the site
# This config requires being logged for the whole site and having the admin role for the admin part.
# Change these rules to adapt them to your needs
- { path: ^/admin/login ,role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/logout ,role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/* ,role: [ROLE_ADMIN, ROLE_SONATA_ADMIN,TOTAL] }
- { path: ^/usuarios/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/usuarios/registro, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/usuarios/*, roles: ROLE_USUARIO }
- { path: ^/clientes/*, roles: ROLE_CLIENTES }
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_SONATA_ADMIN,ROLE_USUARIO,ROLE_CLIENTE]
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
#SONATA:
#- ROLE_SONATA_PAGE_ADMIN_PAGE_EDIT # If you are using acl then this line must be commented
providers:
fos_userbundle:
id: fos_user.user_manager
chain_provider:
chain:
providers: [usuarios, clientes]
usuarios:
entity: { class: m_and_m\UsuariosBundle\Entity\Usuarios, property: email }
clientes:
entity: { class: m_and_m\ClientesBundle\Entity\Clientes, property: email }
firewalls:
# -> custom firewall for the admin area of the URL
admin:
pattern: /admin(.*)
context: user
form_login:
provider: fos_userbundle
login_path: /admin/login
use_forward: false
check_path: /admin/login_check
failure_path: /admin/login
logout:
path: /admin/logout
target: /admin
anonymous: true
# -> end custom configuration
# default login area for standard users
frontend:
pattern: ^/*
context: frontend
provider: chain_provider
anonymous: ~
form_login:
login_path: usuarios_login
check_path: usuarios_login_check
logout:
path: usuarios_logout
UsuariosBundle/Resources/config/services.yml
services:
usuarios.admin.usuarios:
class: m_and_m\UsuariosBundle\Admin\UsuariosAdmin
arguments: [~, m_and_m\UsuariosBundle\Entity\Usuarios, SonataAdminBundle:CRUD]
tags:
- {name: sonata.admin, manager_type: orm, group: Usuarios(Admin), label: Usuarios}
login_listener:
class: m_and_m\UsuariosBundle\Listener\LoginListener
arguments: [#security.context, #router]
tags:
- { name: kernel.event_listener, event: security.interactive_login }
- { name: kernel.event_listener, event: kernel.response }
Following the doc I have created a LoginListener in my usuariosbundle.
When I log in from the frontend all goes perfect. But the Sonata admin dashboard login goes to the LoginListener.php file and returns an error:
FatalErrorException: Error: Call to undefined method Application\Sonata\UserBundle\Entity\User::getNombre() in
C:\wamp\www\m_and_m\src\m_and_m\UsuariosBundle\Listener\LoginListener.php
line 24
LoginListener.php
<?php
namespace m_and_m\UsuariosBundle\Listener;
use Symfony\Componene\EventDispatcher\Event;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Routing\Router;
use Symfony\Component\HttpFoundation\RedirectResponse;
class LoginListener
{
private $contexto, $router, $usuario=null,$role=null;
public function __construct(SecurityContext $context, Router $router)
{
$this->contexto=$context;
$this->router = $router;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
$token = $event->getAuthenticationToken();
$this->usuario = $token->getUser()->getNombre();
$this->role = $token->getRoles();
$this->role=$this->role[0]->getrole();
if($this->role=='ROLE_CLIENTE' && $token->getUser()->getActivo()==false){
$this->usuario = null;
}
}
public function onKernelResponse(FilterResponseEvent $event)
{
if(null != $this->usuario)
{
if($this->role=='ROLE_USUARIO'){
$portada=$this->router->generate('portada_usuario');
}
else{
$portada=$this->router->generate('portada_cliente');
}
$event->setResponse(new RedirectResponse($portada));
$event->stopPropagation();
}
}
}
?>
And I don´t know why is this happening, cause both providers are in different context. Do I need to do something more to separate both logins?
You are calling a method that does not exist in that entity. If you pay attention in the error you will see that the user class that comes from the token is not the one you think it is.

Allow admin user all access in access_control in security.yml

noob question, I'm working in Symfony 2.8 and I want to grant all access to the role ROLE_ADMIN in access control, is there a way to do this without writing 'ROLE_ADMIN' in every rule over access_control?
What I´m trying to avoid in my security.yml, is going from this:
access_control:
- { path: ^/application, roles: ROLE_STUDENT }
- { path: ^/keyword, roles: ROLE_MENTOR }
- { path: ^/department, roles: ROLE_ADMIN }
- { path: ^/requirement, roles: ROLE_MENTOR}
To this:
access_control:
- { path: ^/application, roles: [ROLE_ADMIN, ROLE_STUDENT ]}
- { path: ^/keyword, roles: [ROLE_ADMIN, ROLE_MENTOR ]}
- { path: ^/department, roles: ROLE_ADMIN }
- { path: ^/requirement, roles: [ROLE_ADMIN, ROLE_MENTOR ]}
in a most larger file
Yes, you can add role hierarchy:
security:
role_hierarchy:
ROLE_ADMIN: [ROLE_STUDENT, ROLE_MENTOR]
That way if you have ROLE_ADMIN, you have also ROLE_STUDENT and ROLE_MENTOR.

FOSUserBundle allow access to whole site

guys!
I'am trying to configure user system (FOSUserBundle) for my Symfony app. All was going Ok until I tried to allow access to whole site and restrict access to some routes using access control in security configuration file.
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
default_target_path: /
logout: true
anonymous: true
access_control:
- { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/profile$, roles: ROLE_USER }
- { path: ^/admin$, roles: ROLE_ADMIN }
I've tried also
#
- { path: ^/.*, roles: IS_AUTHENTICATED_ANONYMOUSLY }
#
and when i go to index page (/), it redirects me to login page. I want to have index page visible for all visitors, not only for those who logged in.
Just can't figure out this moment. Thank you for answers.
try this:
access_control:
- { path: ^/profile$, roles: ROLE_USER }
- { path: ^/admin$, roles: ROLE_ADMIN }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
Your problem may be related to trying to specify the role as an array of role but you give only one value:
- { path: ^/*, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/profile$, role: ROLE_USER }
- { path: ^/admin$, role: ROLE_ADMIN }
for more roles you need the []
I resolved the issue. Sorry for my dumbness, i've been wandering for 2 days why this happen.
Redirect was from controller. My mistake, sorry. Thank you for answers anyway.
public function startAction()
{
$user = $this->getUser();
if ($user) {
return $this->render('HellfireCommonBundle:Index:index.html.twig', array('user' => $user));
} else {
return $this->redirect($this->generateUrl('fos_user_security_login'));
}
}

Symfony2 Access Control/Security

Okay, So I'm trying to setup my security in symfony2 via config. I have created a role_hierarchy:
role_hierarchy:
ROLE_USER_ADMIN: ROLE_USER
ROLE_VENDOR: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_VENDOR, ROLE_USER_ADMIN, ROLE_ALLOWED_TO_SWITCH]
And I've setup my access_control:
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/administration/, roles: ROLE_VENDOR }
- { path: ^/administration/vendor/new, roles: ROLE_SUPER_ADMIN }
- { path: ^/administration/taxonomy, roles: ROLE_SUPER_ADMIN }
- { path: ^/administration/property, roles: ROLE_SUPER_ADMIN }
- { path: ^/administration/usagelimit, roles: ROLE_SUPER_ADMIN }
- { path: ^/account, roles: ROLE_USER }
- { path: ^/library, roles: ROLE_USER }
- { path: ^/profile, roles: ROLE_USER }
- { path: ^/vendors, roles: ROLE_USER }
- { path: ^/community, roles: ROLE_USER }
And yet, when I login with a user who has only the "ROLE_VENDOR", I can access the routes like /administration/taxonomy, /administration/property, etc...
What am I doing wrong???
Your routes are in the wrong order.
It's a first come, first served everything after /administration/ with the directory are being caught by that directive and so allowing access by ROLE_VENDOR.
You should change it to...
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, roles: IS_AUTHENTICATED_ANONYMOUSLY }
# - { path: ^/administration/, roles: ROLE_VENDOR } // Old home...
- { path: ^/administration/vendor/new, roles: ROLE_SUPER_ADMIN }
- { path: ^/administration/taxonomy, roles: ROLE_SUPER_ADMIN }
- { path: ^/administration/property, roles: ROLE_SUPER_ADMIN }
- { path: ^/administration/usagelimit, roles: ROLE_SUPER_ADMIN }
- { path: ^/administration/, roles: ROLE_VENDOR } // New home...
- { path: ^/account, roles: ROLE_USER }
- { path: ^/library, roles: ROLE_USER }
- { path: ^/profile, roles: ROLE_USER }
- { path: ^/vendors, roles: ROLE_USER }
- { path: ^/community, roles: ROLE_USER }

Resources