Set up registration FOSUserBundle with FOSRestBundle REST API Set up registration FOSUserBundle with FOSRestBundle REST API symfony symfony

Set up registration FOSUserBundle with FOSRestBundle REST API


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":"xxxxx@xxxx.com",        "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":"xxxxxx@xxxxxxx.com",        "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.


Another way is this registration without the forms from FOSUserBundle.Make a POST Request with params: 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;}


@Adel 'Sean' Helal your way doesn't work, at least with last versions of FOSRestBundle, FOSUserBundle and Symfony with Flex. I almost shoot myself in the head trying to make it work. At the end I found the solution and it's pretty simple. Only parse the request is required.

Fragment 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);}...

The composer.json dependencies:

..."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']);    }}