Configure FOSUserBundle registration using the FOSRestBundle REST API

The problem is fixed, check my answer.

I am creating a registration endpoint on my Symfony2.7 rest api. I use FosRestBundle and FosUserBundle

Here is the user model:

<?php namespace AppBundle\Entity; use FOS\UserBundle\Model\User as BaseUser; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="fos_user") */ class User extends BaseUser { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; public function __construct() { parent::__construct(); // your own logic } } 

\ Here is the UserType form: \

 class UserType extends AbstractType { /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('email', 'email') ->add('username', null) ->add('plainPassword', 'repeated', array( 'type' => 'password', 'first_options' => array('label' => 'password'), 'second_options' => array('label' => 'password_confirmation'), )) ; } /** * @param OptionsResolverInterface $resolver */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'AppBundle\Entity\User', 'csrf_protection' => false, )); } /** * @return string */ public function getName() { return 'user'; } } 

And this post-user controller:

 public function postUserAction(\Symfony\Component\HttpFoundation\Request $request) { $user = new \AppBundle\Entity\User(); $form = $this->createForm(new \AppBundle\Form\UserType(), $user); $form->handleRequest($request); if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($user); $em->flush(); $view = $this->view(array('token'=>$this->get("lexik_jwt_authentication.jwt_manager")->create($user)), Codes::HTTP_CREATED); return $this->handleView($view); } return array( 'form' => $form, ); } 

The problem is that when I send incorrect information or empty information, the server returns an error with bad forms 500 with doctrine / mysql data of zero value for non-zero line in json response state with a list of bad formatted records.

Any idea on how to fix this behavior? How did it happen that the check passed, and

+6
source share
3 answers

Well, having spent a lot of time reading the FOSUserBundle code, and especially the registration controller and the factory form, I came up with a fully working solution.

Before doing anything, be sure to disable CSRF in your symfony2 configuration.

Here is the controller that I use to register:

  public function postUserAction(\Symfony\Component\HttpFoundation\Request $request) { /** @var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */ $formFactory = $this->get('fos_user.registration.form.factory'); /** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */ $userManager = $this->get('fos_user.user_manager'); /** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */ $dispatcher = $this->get('event_dispatcher'); $user = $userManager->createUser(); $user->setEnabled(true); $event = new \FOS\UserBundle\Event\GetResponseUserEvent($user, $request); $dispatcher->dispatch(\FOS\UserBundle\FOSUserEvents::REGISTRATION_INITIALIZE, $event); if (null !== $event->getResponse()) { return $event->getResponse(); } $form = $formFactory->createForm(); $form->setData($user); $form->handleRequest($request); if ($form->isValid()) { $event = new \FOS\UserBundle\Event\FormEvent($form, $request); $dispatcher->dispatch(\FOS\UserBundle\FOSUserEvents::REGISTRATION_SUCCESS, $event); $userManager->updateUser($user); if (null === $response = $event->getResponse()) { $url = $this->generateUrl('fos_user_registration_confirmed'); $response = new \Symfony\Component\HttpFoundation\RedirectResponse($url); } $dispatcher->dispatch(\FOS\UserBundle\FOSUserEvents::REGISTRATION_COMPLETED, new \FOS\UserBundle\Event\FilterUserResponseEvent($user, $request, $response)); $view = $this->view(array('token' => $this->get("lexik_jwt_authentication.jwt_manager")->create($user)), Codes::HTTP_CREATED); return $this->handleView($view); } $view = $this->view($form, Codes::HTTP_BAD_REQUEST); return $this->handleView($view); } 

Now the tricky part was representing the form using REST. The problem was that when I sent JSON, like this one:

 { "email":" xxxxx@xxxx.com ", "username":"xxx", "plainPassword":{ "first":"xxx", "second":"xxx" } } 

The API responded like nothing was sent.

The solution is that Symfony2 is waiting for you to encapsulate form data in the form name!

Question: "I did not create this form, so I do not know what its name is." So I again went to the package code and found out that the form type was fos_user_registration, and the getName function returned fos_user_registration_form.

As a result, I tried to present my JSON in this way:

 {"fos_user_registration_form":{ "email":" xxxxxx@xxxxxxx.com ", "username":"xxxxxx", "plainPassword":{ "first":"xxxxx", "second":"xxxxx" } }} 

And voila! it worked. If you are trying to set up your fosuserbundle using fosrestbundle and LexikJWTAuthenticationBundle, just ask me, I will be happy to help.

+12
source

Another way is to register without forms from FOSUserBundle. Make a POST request with the following parameters: email, user, password.

 public function postUserAction(Request $request) { $userManager = $this->get('fos_user.user_manager'); $email = $request->request->get('email'); $username = $request->request->get('user'); $password = $request->request->get('password'); $email_exist = $userManager->findUserByEmail($email); $username_exist = $userManager->findUserByUsername($username); if($email_exist || $username_exist){ $response = new JsonResponse(); $response->setData("Username/Email ".$username."/".$email." existiert bereits"); return $response; } $user = $userManager->createUser(); $user->setUsername($username); $user->setEmail($email); $user->setLocked(false); $user->setEnabled(true); $user->setPlainPassword($password); $userManager->updateUser($user, true); $response = new JsonResponse(); $response->setData("User: ".$user->getUsername()." wurde erstellt"); return $response; } 
0
source

@Adel 'Sean' Helal your method does not work, at least with the latest versions of FOSRestBundle, FOSUserBundle and Symfony with Flex. I almost shot into the head, trying to get it to work. In the end, I found a solution, and it's pretty simple. It is only required to analyze the request.

A snippet of my controller code

 ... $form->setData($user); // THIS LINE DO THE MAGIC $data = json_decode($request->getContent(), true); if ($data === null) { throw new BadRequestHttpException(); } $form->submit($data); if ( ! $form->isValid()) { $event = new FormEvent($form, $request); $dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event); if (null !== $response = $event->getResponse()) { return $response; } return new JsonResponse($this->getFormErrors($form), Response::HTTP_BAD_REQUEST); } ... 

Dependencies composer.json:

 ... "symfony/lts": "^3", "symfony/flex": "^1.0", "friendsofsymfony/rest-bundle": "^2.3", "friendsofsymfony/user-bundle": "^2.0", "lexik/jwt-authentication-bundle": "^2.4", ... 

My functional test code:

 namespace App\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Component\DependencyInjection\Container; class ApiUserControllerTest extends WebTestCase { /** * @var Container */ private $container; public function setUp() { self::bootKernel(); $this->container = self::$kernel->getContainer(); } public function testRegistration() { $userData = [ 'username' => 'test', 'email' => ' test@email.com ', 'plainPassword' => [ 'first' => 'test123', 'second' => 'test123' ] ]; $client = $this->container->get('eight_points_guzzle.client.rest'); $response = $client->post( 'api/registration', ['json' => $userData] ); $bodyResponse = \GuzzleHttp\json_decode($response->getBody(), true); $this->assertEquals(201, $response->getStatusCode()); $this->assertArrayHasKey('token', $bodyResponse); $this->assertNotEmpty($bodyResponse['token']); } } 
0
source

All Articles