I need a little help here since my code doesn't work and I can't find where I'm failing. See this is the function I'm using to register users on my application (taked from here and changed a bit to suite my needs):
public function registerAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->container->get('fos_user.user_manager');
/** #var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
$dispatcher = $this->container->get('event_dispatcher');
$user = $userManager->createUser();
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$entity = new SysUsuario();
$form = $this->createForm(new UsuarioType(), $entity);
$form->handleRequest($request);
$user_data = $request->get('user_register');
$profile_data = $request->get('user_register')['perfil'];
if ($form->isValid()) {
$user->setUsername($profile_data['persJuridica'] . $profile_data['rif']);
$user->setEmail($user_data['email']);
$user->setPlainPassword($user_data['password']);
$role = $profile_data['roleType'];
if ($role === "O") {
$user->addRole("ROLE_OPERADOR");
}
elseif ($role === "CH") {
$user->addRole("ROLE_CENTRO_HIPICO");
}
$userManager->updateUser($user);
$profile = new SysPerfil();
$profile->setPersJuridica($profile_data['persJuridica']);
$profile->setRif($profile_data['rif']);
$ci = isset($profile_data['ci']) ? $profile_data['ci'] : null;
if ($ci != NULL) {
$profile->setCi($profile_data['ci']);
}
$profile->setNombre($profile_data['nombre']);
$profile->setApellido($profile_data['apellido']);
$profile->setRoleType($profile_data['roleType']);
$profile->setUser($user);
$em->persist($profile);
$em->flush();
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
if (null === $response = $event->getResponse()) {
$url = $this->container->get('router')->generate('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
else {
$errors = $this->getFormErrors($formProfile);
}
return new JsonResponse(array('status' => true, 'errors' => $errors));
}
The problem here is that my code is never triggering the REGISTRATION_SUCCESS event so I didn't get any email and therefore I can't confirm users, what I'm doing wrong?
After dig and dig deeper in my code I found where the problem was. Thanks to #tttony user who turns on the bulb, I, accidentally, delete the confirmation configuration at config.yml and for that reason the event never was triggered, so the easy solution:
fos_user:
....
registration:
confirmation:
from_email:
address: admin#local.com
sender_name: Myself
Now before found the previous solution I come with another one, which made me study and learn and I leave here too:
/** Disable the user by default - this is done in the event */
$user->setEnabled(false);
/** #var $mailer FOS\UserBundle\Mailer\MailerInterface */
$mailer = $this->container->get('fos_user.mailer');
if (null === $user->getConfirmationToken()) {
$user->setConfirmationToken($str->generateRandomString(32));
}
$mailer->sendConfirmationEmailMessage($user);
$session = new Session();
$session->set('fos_user_send_confirmation_email/email', $user->getEmail());
The only thing I wont be able to do here was use the FOS\UserBundle\Util\TokenGeneratorInterface I don't know how to, so if any knows I'll be grateful if leave the answer to that one, both solutions works since I tested.
Related
I wanted to validate my User Object ($user) with the Symfony Validator and return a JsonResponse ($response) if the form input data is valid / is not valid.
But I have the issue that I get logged out automatically when the data could not be validated. I have to login again and this is not the behaviour I expect when some data ist not valid. I found a workaround (see comments below) but this is not very satisfying :/
Here is the method of my Controller:
/**
* Update user profile data
*
* #Route("/api/users/updateprofile")
* #Security("is_granted('USERS_LIST')")
*/
public function apiProfileUpdate(ValidatorInterface $validator, FlashMessageBuilder $flashMessageBuilder)
{
$request = Request::createFromGlobals();
// Prepare Response
$response = new JsonResponse();
$response->setData([]);
/** #var User $user */
$user = $this->getUser();
$oldName = $user->getName();
$oldEmail = $user->getEmail();
$user->setName($request->request->get('name'));
$user->setEmail($request->request->get('email'));
$errors = $validator->validate($user);
if (count($errors) > 0) { // if this -> auto logout
$user->setName($oldName); // if I set the both attributes back to the old value
$user->setEmail($oldEmail); // then I don't get logged out automatically but this is just a workaround and not satisfying
$entityManager = $this->getDoctrine()->getManager(); // forgot to remove this
$entityManager->persist($user); // and this line, this is actually deleted in the real code
foreach ($errors as $error) {
$errorMessage = $error->getMessage();
$errorField = $error->getPropertyPath();
$flashMessageBuilder->addErrorMessage($errorMessage, $errorField);
};
return $response;
}
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
$flashMessageBuilder->addSuccessMessage("Success!");
return $response;
}
Sorry for my bad english and thank you in advance!
You are persisting the User Object even if there are errors in validation, which can cause the problem with the logout.
Try to update ONLY in case there is no validation error:
public function apiProfileUpdate(ValidatorInterface $validator, FlashMessageBuilder $flashMessageBuilder)
{
$request = Request::createFromGlobals();
// Prepare Response
$response = new JsonResponse();
$response->setData([]);
/** #var User $user */
$user = $this->getUser();
$user->setName($request->request->get('name'));
$user->setEmail($request->request->get('email'));
$errors = $validator->validate($user);
if (count($errors) == 0) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
$flashMessageBuilder->addSuccessMessage("Success!");
return $response;
}
foreach ($errors as $error) {
$errorMessage = $error->getMessage();
$errorField = $error->getPropertyPath();
$flashMessageBuilder->addErrorMessage($errorMessage, $errorField);
};
return $response;
}
But I think you should not mix API calls and the classical form approach utilizing FlashMessages, instead return a proper JSON result.
So consider to change the code accordingly:
public function apiProfileUpdate(ValidatorInterface $validator, FlashMessageBuilder $flashMessageBuilder)
{
$request = Request::createFromGlobals();
/** #var User $user */
$user = $this->getUser();
$user->setName($request->request->get('name'));
$user->setEmail($request->request->get('email'));
$errors = $validator->validate($user);
if (count($errors) == 0) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return new JsonResponse(['success' => true]);
}
$data = [];
foreach ($errors as $error) {
$data[$error->getPropertyPath()] = $error->getMessage();
};
return new JsonResponse(['success' => false, 'errors' => $data], 400);
}
Now your calling code can handle a 200 result (success) and the error case with status code 400 and display the error messages for all failed fields from the errors part in the result body.
I can do auto login with fosuserBundle,when he access the page adding clause he is auto login , When he accéd page adding article he redirect automatically to the login page but my objective is to auto login
routing :
ajouterapps:
path: /ajouterapps
defaults: { _controller: MedBundle:Apps:ajouter }
code controller :
public function ajouterAction()
{
$em = $this->getDoctrine();
$repo = $em->getRepository("UserBundle:User"); //Entity Repository
$user = $this->getUser();
if (!$user) {
throw new UsernameNotFoundException("User not found");
} else {
$token = new UsernamePasswordToken($user, null, "your_firewall_name", $user->getRoles());
$this->get("security.context")->setToken($token); //now the user is logged in
//now dispatch the login event
$request = $this->get("request");
$event = new InteractiveLoginEvent($request, $token);
$this->get("event_dispatcher")->dispatch("security.interactive_login", $event);
}
$msg = 'ajouter Apps';
$em = $this->getDoctrine()->getManager();
$app = new Apps();
$form = $this->createForm(new AppsType, $app);
$request = $this->getRequest();
if ($request->getMethod() == 'POST') {
$form->handleRequest($request);
$app->upload();
$em->persist($app);
$em->flush();
$msg = 'Apps ajouter avec success';
}
return $this->render('MedBundle:Apps:ajouter.html.twig',array(
'form'=>$form->createView(),
'msg'=>$msg
)
);
}
What is the solution and thank you in advance
I am new with Symfony and FOSUserBundle, I have a relation One To One between User and Stream, when a user want to register he check if he is a streamer or not. If he is a streamer I want to create a new stream in relation with the user so here is the registerAction from FOSUserBundle that I'm overriding :
$form = $this->container->get('fos_user.registration.form');
$formHandler = $this->container->get('fos_user.registration.form.handler');
$confirmationEnabled = $this->container->getParameter('fos_user.registration.confirmation.enabled');
$process = $formHandler->process($confirmationEnabled);
if ($process) {
$user = $form->getData();
/*This is what I added*/
if($user->getIsStreamer()){
$em = $this->getDoctrine()->getManager();
$stream = new Stream();
$stream->setUser($user);
$em->persist($stream);
$em->flush();
}
/********/
$authUser = false;
if ($confirmationEnabled) {
$this->container->get('session')->set('fos_user_send_confirmation_email/email', $user->getEmail());
$route = 'fos_user_registration_check_email';
} else {
$authUser = true;
$route = 'fos_user_registration_confirmed';
}
$this->setFlash('fos_user_success', 'registration.flash.user_created');
$url = $this->container->get('router')->generate($route);
$response = new RedirectResponse($url);
if ($authUser) {
$this->authenticateUser($user, $response);
}
return $response;
}
But nothing happened, what did I missed ?
You are missing the part that add the Stream to the user (and not only set the user of the stream).
First, be sure your association contains cascade={"persist"} to avoid need of manually persist the Stream :
/**
* #ORM\OneToOne(targetEntity="Stream", cascade={"persist"},
*/
protected $stream;
Then, change your setStream to make it calling $stream->setUser automatically :
public function setStream(Stream $stream = null)
{
$this->stream = $stream;
$stream->setUser($this); // Setter calling
return $this;
}
Now you can replace the logic of your condition like this :
if($user->getIsStreamer()){
$stream = new Stream();
$user->setStream($stream);
}
The association should be correctly stored when calling $em->flush at the end of your method.
In the case of FOSUB registration it should be :
$this->get('fos_user.user_manager')->updateUser($user);.
It's done in the confirmAction where your user is redirected in success.
I'm using Symfony2 with FOSUserBundle, the problem I have encountered was in editing a user account, when I tried to edit a specific user account, the retrieved user info is correct but when I tried to update the retrieved user info, the currently logged account would be the one being edited not the retrieved user account, how is it possible? What's wrong with my code?
ProfileController :
//edit user
public function editUserAction($id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('MatrixUserBundle:User')->find($id);
if (!is_object($user)) {
throw new AccessDeniedException('This user does not have access to this section.');
}
/** #var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
$formFactory = $this->get('fos_user.profile.form.factory');
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isValid()) {
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
$userManager->updateUser($user);
$session = $this->getRequest()->getSession();
$session->getFlashBag()->add('message', 'Successfully updated');
$url = $this->generateUrl('matrix_edi_viewUser');
$response = new RedirectResponse($url);
}
return $this->render('FOSUserBundle:Profile:edit.html.twig', array(
'form' => $form->createView()
));
}
After the given user is correctly updated, you are returning a redirection to a custom route.
I guess the route matrix_edi_viewUser is an override of the original FOSUB\ProfileController::showAction.
Also, you have to create a specific showUserAction and pass it the updated user as argument.
The following code should works :
public function showUserAction($id)
{
$user = $em->getDoctrine()
->getManager()
->getRepository('MatrixUserBundle:User')
->find($id);
if (!is_object($user)) {
throw new AccessDeniedException('This user does not have access to this section.');
}
return $this->render('FOSUserBundle:Profile:show.html.twig', array('user' => $user));
}
The route :
matrix_edi_viewUser:
path: /users/{id}/show
defaults: { _controller: MatrixUserBundle:Profile:showUser }
And in your editAction, change your redirection to :
$url = $this->generateUrl('matrix_edi_viewUser', array('id' => $user->getId());
$response = new RedirectResponse($url);
Now, the user informations displayed in show will be the informations of the updated user.
I'm trying to get "Registration Confirmation" working on my application but can't. Since I need to set some fields on profiles and so on this is how my method save for users is:
public function saveAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->container->get('fos_user.user_manager');
/** #var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
$dispatcher = $this->container->get('event_dispatcher');
$user = $userManager->createUser();
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$entityProfile = new SysPerfil();
$formProfile = $this->createForm(new PerfilType(), $entityProfile);
$formProfile->handleRequest($request);
$user_data = $request->get('user_profile');
if ($formProfile->isValid()) {
$event = new FormEvent($formProfile, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
$role = $request->get('user_profile')['roleType'];
$user->setUsername($user_data['rif']);
$user->setEmail($user_data['user']['email']);
$user->setPlainPassword($user_data['user']['password']);
if ($role === "O") {
$user->addRole("ROLE_OPERADOR");
}
elseif ($role === "CH") {
$user->addRole("ROLE_CENTRO_HIPICO");
}
$userManager->updateUser($user);
$entityProfile->setUser($user);
$em->persist($entityProfile);
$em->flush();
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request));
return $this->redirect($this->generateUrl('login'));
}
else {
$errors = $this->getFormErrors($formProfile);
}
return new JsonResponse(array('status' => true, 'errors' => $errors));
}
And this is what I've configured at config.yml file:
# FOSUserBundle
fos_user:
db_driver: orm
firewall_name: main
user_class: Sunahip\UserBundle\Entity\SysUsuario
group:
group_class: Sunahip\UserBundle\Entity\SysGrupos
registration:
confirmation:
enabled: true
But I'm getting this error:
Attempted to call method "setEnabled" on class "UserBundle\Entity\SysPerfil" in /var/www
/html/vendor/friendsofsymfony/user-bundle/FOS/UserBundle/EventListener
/EmailConfirmationListener.php line 50.
What I did wrong?
I found where the problem was so never mind, my entities was bad configured and I was doing things bad, anyway thanks