Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set up registration FOSUserBundle with FOSRestBundle REST API

Problem fixed, check my answer.

I'm building a registration endpoint on my Symfony2.7 rest api. I am using 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 the 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 submit wrong information, or empty information, the server return a bad formated 500 error with doctrine / mysql details of null value for not null row in state of a json response with the list of bad formated entries.

Any idea on how to fix this behaviour ? How come the validation get by passed and

like image 709
Adel 'Sean' Helal Avatar asked Sep 09 '15 21:09

Adel 'Sean' Helal


1 Answers

Ok after spending a lot of time reading the FOSUserBundle code, and particularly the registration controller and the form factory, i came up with a fully working solution.

Before doing anything don't forget to disable CSRF in your symfony2 configuration.

Here is the controller 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 submiting the form using REST. The problem was that when I sent i JSON like this one :

{
        "email":"[email protected]",
        "username":"xxx",
        "plainPassword":{
            "first":"xxx",
            "second":"xxx"
        }
    }

The API was responding like nothing was submited.

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

The question was "I didnt create this form so i dont know what is its name..". So i went again in the bundle code and found out that the form type was fos_user_registration and the getName function was returning fos_user_registration_form.

As a result i tried to submit my JSON this way :

{"fos_user_registration_form":{
        "email":"[email protected]",
        "username":"xxxxxx",
        "plainPassword":{
            "first":"xxxxx",
            "second":"xxxxx"
        }
    }}

And voila! it worked. If you are struggling setting up your fosuserbundle with fosrestbundle and LexikJWTAuthenticationBundle just ask me i'll be glad to help.

like image 158
Adel 'Sean' Helal Avatar answered Oct 03 '22 16:10

Adel 'Sean' Helal