How to override logout action in symfony2 - php

I know logout action can be performed by symfony2 security controller by default.
when we give the path Logout like this it works fine.
but I need to perform some action like storing some data into the database when logout is happened.So how can i achieve this thing.
If any have an idea please help me.

you need to define new rule for logout action in routing.yml or annotation (it`s up to you)
logout_user:
pattern: /logoutUser
defaults: { _controller: YourBundle:YourController:logout }
Then it`s only writing code for this action like this:
public function logoutAction() {
//do whatever you want here
//clear the token, cancel session and redirect
$this->get('security.context')->setToken(null);
$this->get('request')->getSession()->invalidate();
return $this->redirect($this->generateUrl('login'));
}
There is also way to do the job proposed by tesmojones
here symfony2 logout

Related

Can't redirect within a constructor in Symfony 4

I'm working on a client project that wasn't conceived with services and authorizations, so the user gets logged in and creates a user session.
I have to control the access in a basic "UserboardController".
I have a constructor before any methods :
class UserboardController extends Controller
{
public function __construct() {
$session = new Session();
$uSession = $session->get('user');
if (!isset($uSession)){
return $this->redirectToRoute('logout');
}
}
I tried many ways to redirect and always get this error :
Call to a member function get() on null
Symfony will show me two other traces inside redirectToRoute from ControllerTrait.php :
return $this->redirect($this->generateUrl($route, $parameters), $status);
and
return $this->container->get('router')->generate($route, $parameters, $referenceType);
Any idea how I could simply redirect the user to the logout route ?
This is an important step as the logout method will do other actions based on cookies before logging out and redirecting to the login form.
Logout route is defined and works if the user accesses it from the URL.
Thank you
First of all, if you want to access session you should pass it as argument and get benefit of autowiring. Secondly, this shouldn't be done in a controller's constructor.
Thirdly this looks like the case for the security module of symfony. Symfony when properly configure will return use by default to /logout route of any route that is defined as logout route
So what you need to do is define in security.yaml your firewalls and define in access_control the path that should be under the firewall
Check this for more clues https://symfony.com/doc/current/security/form_login_setup.html

Create route without path [Symfony3]

In security.yml in firewall/main/form_login I have this:
default_target_path: after_login
always_use_default_target_path: true
I want to create a route named after_login, but without a path, but symfony redirects me to homepage after login.
/**
* #Route(name="after_login")
*/
public function afterloginAction()
I want to nobody have access to this controller's method.
Is it possible to create such route or maybe another way to redirect after login to this method?
I want to add some variables to session but only once after login.
Best way approaching this would be listen on the security.interactive_login event:
default_target_path is not meant for that. That is just an redirect to an controller action, the user profile for example.
Using an controller action once and then make it not-accessible by setting a session key would be an ugly hack.
Read https://symfony.com/doc/current/components/security/authentication.html#authentication-events for that purpose. Using an event listener would make it hidden form the outside world automatically.
This is not possible with #Route. Is there wrong something here, why you want it?

Session conditions in a symfony2 controller

When working with symfony2, I'd like to show different layouts (base.html.twig for guests, and layout.html.twig for logged users).
And when a user is connected to his account, he can also (As facebook does) "connect as" a page or a group (always inside his account), and for these two I have to show different layouts as well (pagelayout.html.twig and grouplayout.html.twig).
It seems that the solution is to create a controller (indexAction for example), containing all the conditions over the sessions and database queries.
For example (I changed the code for simplification):
public function indexAction(){
// ...
if (!$mySession) { //the user is not connected
//redirection to home controller that uses base.twig.html
} else { //the user is logged in
if ($connectAs=='profile') {
//redirection to home controller that uses layout.twig.html
} else if($connectAs=='page') {
//redirection to page controller that uses pagelayout.twig.html
} else if($connectAs=='group') {
//redirection to group controller that uses grouplayout.twig.html
}
}
}
I wanted to use these conditions in one redirecting controller, but I think it's not a flexible solution. For I can integrate other types of layouts and controllers, I may need to add more conditions.
Is there a better solution, Than can be more flexible?
Edit : Another problem with this solution, is that even if a user is connected as a "Page" , he can still type in the URL of the route to the Group or User controller and get access to them too... unless I added conditions in these controllers too.
What I need exactly, is creating a controller that acts like a frontController
If you want a frontcontroller like logic you need to catch all possible routes with one controller and then forword from there.
# all other routed efinitions should go above this,
# so that _frontcontroller acts like a fallback
_frontcontroller:
path: /{url}
defaults: { _controller: YourFrontBundle:Front:index }
requirements:
name: ".+" #allow / in the route
And your controller should then forward to the controller based on conditions and url
public function indexAction($url)
{
// ...
} else if ($connectAs=='group') {
$this->forward('YourGroupBundle:Group:index');
// or something else based on the url parameter
}
// ...
}
Also there is the CMF Bundle which has dynamic routing but i didn't digg into that yet.

Passing Delete Method Through sfGuard

I have an application with people and groups in Symfony, where a person may have a membership with multiple groups. To remove a person from a group, I currently have an action in a 'groupMembers' module that takes a 'delete' method and removes the pair from a many-to-many entity 'group_membership'. The route currently looks something like this:
remove_membership:
url: /group-membership/:group_id/:person_id
class: sfPropelRoute
options: { model: GroupMembership, type: object }
param: { module: groupMembers, action: remove }
requirements:
sf_method: [delete]
To perform this action, the user needs to be logged in, so I restricted it using sfGuard in the module's security.yml:
remove:
is_secure: true
So after clicking a 'remove' link, a user who isn't logged in is taken to the log in screen, but after clicking 'submit' the request is no longer a 'delete' but a 'get', meaning the similar add_to_group route is called instead!
add_to_group:
url: /group-membership/:group_id/:person_id
param: { module: groupMembers, action: create }
...
Is there any way to make sfGuard emulate a delete action and pass the parameters properly, or will I have to use a different route?
It seems that there is no way to achieve this without writing custom code or editing code of sfGuard plugin.
See plugins/sfGuardPlugin/modules/sfGuardAuth/lib/BasesfGuardAuthActions.class.php (its executeSignin method for details) how sign in is handled.
sfGuard gets user referrer and performs redirect with appropriate method of sfAction. This redirect is performed by using http header Location. So browser will use GET method to receive url content.
You can override default signin action and perform redirects from remove_membership route to an action which will use sfBrowser component to emulate POST request, but I highly recommend you to change routing scheme.

do I need a preExecute() function in action class to check proper credentials in Symfony?

to implement credentials do I need to implement a preExecute function like this:
public function preExecute() {
$this->configuration = new jobGeneratorConfiguration();
if (!$this->getUser()->hasCredential(
$this->configuration->getCredentials($this->getActionName())
));
}
Or is it suffice to have it defined in the module/config/security.yml like this:
all:
is_secure: true
credentials: [ admin ]
However I am not able to work it out using security.yml only! I thought preExecute is not necessary and symfony automatically handles it by loading the security.yml definition!
Please help!
I am using sfDoctrineGuardPlugin and sfForkedDoctrineApply plugin..
There is no need for you to do a pre-execute for this.
The security.yml file is enough to stop people without the appropriate credentials from getting to the specified module or action.

Categories