From 2251045901875aa815dee43ec467fb1af8d416d0 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Sat, 29 Apr 2017 19:22:50 +0200 Subject: WIP Signed-off-by: Thomas Citharel --- .../ApiBundle/Controller/UserRestController.php | 98 ++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/Wallabag/ApiBundle/Controller/UserRestController.php (limited to 'src/Wallabag/ApiBundle/Controller/UserRestController.php') diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php new file mode 100644 index 00000000..c5ffbdf1 --- /dev/null +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php @@ -0,0 +1,98 @@ +validateAuthentication(); + + $serializationContext = SerializationContext::create()->setGroups(['user_api']); + $json = $this->get('serializer')->serialize($this->getUser(), 'json', $serializationContext); + + return (new JsonResponse())->setJson($json); + } + + /** + * Register an user + * + * @ApiDoc( + * requirements={ + * {"name"="username", "dataType"="string", "required"=true, "description"="The user's username"}, + * {"name"="password", "dataType"="string", "required"=true, "description"="The user's password"} + * {"name"="email", "dataType"="string", "required"=true, "description"="The user's email"} + * } + * ) + * @return JsonResponse + */ + // TODO : Make this method (or the whole API) accessible only through https + public function putUserAction($username, $password, $email) + { + if (!$this->container->getParameter('fosuser_registration')) { + $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); + return (new JsonResponse())->setJson($json)->setStatusCode(403); + } + + if ($password === '') { // TODO : might be a good idea to enforce restrictions here + $json = $this->get('serializer')->serialize(['error' => 'Password is blank'], 'json'); + return (new JsonResponse())->setJson($json)->setStatusCode(400); + } + + + // TODO : Make only one call to database by using a custom repository method + if ($this->getDoctrine() + ->getRepository('WallabagUserBundle:User') + ->findOneByUserName($username)) { + $json = $this->get('serializer')->serialize(['error' => 'Username is already taken'], 'json'); + return (new JsonResponse())->setJson($json)->setStatusCode(409); + } + + if ($this->getDoctrine() + ->getRepository('WallabagUserBundle:User') + ->findOneByEmail($email)) { + $json = $this->get('serializer')->serialize(['error' => 'An account with this email already exists'], 'json'); + return (new JsonResponse())->setJson($json)->setStatusCode(409); + } + + $em = $this->get('doctrine.orm.entity_manager'); + + $userManager = $this->get('fos_user.user_manager'); + $user = $userManager->createUser(); + + $user->setUsername($username); + + $user->setPlainPassword($password); + + $user->setEmail($email); + + $user->setEnabled(true); + $user->addRole('ROLE_USER'); + + $em->persist($user); + + // dispatch a created event so the associated config will be created + $event = new UserEvent($user); + $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); + + $serializationContext = SerializationContext::create()->setGroups(['user_api']); + $json = $this->get('serializer')->serialize($user, 'json', $serializationContext); + + return (new JsonResponse())->setJson($json); + + } + +} -- cgit v1.2.3 From 5709ecb36809fb009446a11a758232bbe8f264e4 Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Tue, 30 May 2017 07:56:01 +0200 Subject: Re-use `NewUserType` to validate registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only ugly things is how we handle error by generating the view and then parse the content to retrieve all errors… Fix exposition fields in User entity --- .../ApiBundle/Controller/UserRestController.php | 119 ++++++++++++++------- 1 file changed, 80 insertions(+), 39 deletions(-) (limited to 'src/Wallabag/ApiBundle/Controller/UserRestController.php') diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php index c5ffbdf1..a1b78e3f 100644 --- a/src/Wallabag/ApiBundle/Controller/UserRestController.php +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php @@ -6,12 +6,14 @@ use FOS\UserBundle\Event\UserEvent; use FOS\UserBundle\FOSUserEvents; use JMS\Serializer\SerializationContext; use Nelmio\ApiDocBundle\Annotation\ApiDoc; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; +use Wallabag\UserBundle\Entity\User; class UserRestController extends WallabagRestController { /** - * Retrieve user informations + * Retrieve current logged in user informations. * * @ApiDoc() * @@ -21,78 +23,117 @@ class UserRestController extends WallabagRestController { $this->validateAuthentication(); - $serializationContext = SerializationContext::create()->setGroups(['user_api']); - $json = $this->get('serializer')->serialize($this->getUser(), 'json', $serializationContext); - - return (new JsonResponse())->setJson($json); + return $this->sendUser($this->getUser()); } /** - * Register an user + * Register an user. * * @ApiDoc( * requirements={ * {"name"="username", "dataType"="string", "required"=true, "description"="The user's username"}, - * {"name"="password", "dataType"="string", "required"=true, "description"="The user's password"} + * {"name"="password", "dataType"="string", "required"=true, "description"="The user's password"}, * {"name"="email", "dataType"="string", "required"=true, "description"="The user's email"} * } * ) + * + * @todo Make this method (or the whole API) accessible only through https + * * @return JsonResponse */ - // TODO : Make this method (or the whole API) accessible only through https - public function putUserAction($username, $password, $email) + public function putUserAction(Request $request) { if (!$this->container->getParameter('fosuser_registration')) { $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); + return (new JsonResponse())->setJson($json)->setStatusCode(403); } - if ($password === '') { // TODO : might be a good idea to enforce restrictions here - $json = $this->get('serializer')->serialize(['error' => 'Password is blank'], 'json'); - return (new JsonResponse())->setJson($json)->setStatusCode(400); - } + $userManager = $this->get('fos_user.user_manager'); + $user = $userManager->createUser(); + // enable created user by default + $user->setEnabled(true); + $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [ + 'csrf_protection' => false, + ]); - // TODO : Make only one call to database by using a custom repository method - if ($this->getDoctrine() - ->getRepository('WallabagUserBundle:User') - ->findOneByUserName($username)) { - $json = $this->get('serializer')->serialize(['error' => 'Username is already taken'], 'json'); - return (new JsonResponse())->setJson($json)->setStatusCode(409); - } + // simulate form submission + $form->submit([ + 'username' => $request->request->get('username'), + 'plainPassword' => [ + 'first' => $request->request->get('password'), + 'second' => $request->request->get('password'), + ], + 'email' => $request->request->get('email'), + ]); - if ($this->getDoctrine() - ->getRepository('WallabagUserBundle:User') - ->findOneByEmail($email)) { - $json = $this->get('serializer')->serialize(['error' => 'An account with this email already exists'], 'json'); - return (new JsonResponse())->setJson($json)->setStatusCode(409); - } + if ($form->isSubmitted() && false === $form->isValid()) { + $view = $this->view($form, 400); + $view->setFormat('json'); - $em = $this->get('doctrine.orm.entity_manager'); + // handle errors in a more beautiful way than the default view + $data = json_decode($this->handleView($view)->getContent(), true)['children']; + $errors = []; - $userManager = $this->get('fos_user.user_manager'); - $user = $userManager->createUser(); + if (isset($data['username']['errors'])) { + $errors['username'] = $this->translateErrors($data['username']['errors']); + } - $user->setUsername($username); + if (isset($data['email']['errors'])) { + $errors['email'] = $this->translateErrors($data['email']['errors']); + } - $user->setPlainPassword($password); + if (isset($data['plainPassword']['children']['first']['errors'])) { + $errors['password'] = $this->translateErrors($data['plainPassword']['children']['first']['errors']); + } - $user->setEmail($email); + $json = $this->get('serializer')->serialize(['error' => $errors], 'json'); - $user->setEnabled(true); - $user->addRole('ROLE_USER'); + return (new JsonResponse())->setJson($json)->setStatusCode(400); + } - $em->persist($user); + $userManager->updateUser($user); // dispatch a created event so the associated config will be created - $event = new UserEvent($user); + $event = new UserEvent($user, $request); $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); - $serializationContext = SerializationContext::create()->setGroups(['user_api']); - $json = $this->get('serializer')->serialize($user, 'json', $serializationContext); + return $this->sendUser($user); + } - return (new JsonResponse())->setJson($json); + /** + * Send user response. + * + * @param User $user + * + * @return JsonResponse + */ + private function sendUser(User $user) + { + $json = $this->get('serializer')->serialize( + $user, + 'json', + SerializationContext::create()->setGroups(['user_api']) + ); + return (new JsonResponse())->setJson($json); } + /** + * Translate errors message. + * + * @param array $errors + * + * @return array + */ + private function translateErrors($errors) + { + $translatedErrors = []; + foreach ($errors as $error) { + $translatedErrors[] = $this->get('translator')->trans($error); + } + + return $translatedErrors; + } } -- cgit v1.2.3 From 426bb453d295900fb3e35dce2f9081a42639cf27 Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Fri, 2 Jun 2017 10:19:33 +0200 Subject: API user creation behing a toggle I've added a toggle feature (in internal settings) so that user api creation can be disabled while form registration still can be enabled. Also, the /api/user endpoint shouldn't require authentication. Even if we check the authentication when sending a GET request, to retrieve current user information. I've moved all the internal settings definition to config to avoid duplicated place to define them. I don't know why we didn't did that earlier. --- src/Wallabag/ApiBundle/Controller/UserRestController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/Wallabag/ApiBundle/Controller/UserRestController.php') diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php index a1b78e3f..1fc67d00 100644 --- a/src/Wallabag/ApiBundle/Controller/UserRestController.php +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php @@ -43,7 +43,7 @@ class UserRestController extends WallabagRestController */ public function putUserAction(Request $request) { - if (!$this->container->getParameter('fosuser_registration')) { + if (!$this->getParameter('fosuser_registration') || !$this->get('craue_config')->get('api_user_registration')) { $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); return (new JsonResponse())->setJson($json)->setStatusCode(403); @@ -51,8 +51,8 @@ class UserRestController extends WallabagRestController $userManager = $this->get('fos_user.user_manager'); $user = $userManager->createUser(); - // enable created user by default - $user->setEnabled(true); + // user will be disabled BY DEFAULT to avoid spamming account to be created + $user->setEnabled(false); $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [ 'csrf_protection' => false, -- cgit v1.2.3 From 1b9cd91782ed8341d2e608371201348c59986f23 Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Fri, 2 Jun 2017 10:27:15 +0200 Subject: Add translation --- src/Wallabag/ApiBundle/Controller/UserRestController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Wallabag/ApiBundle/Controller/UserRestController.php') diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php index 1fc67d00..a1d7c1ff 100644 --- a/src/Wallabag/ApiBundle/Controller/UserRestController.php +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php @@ -51,7 +51,7 @@ class UserRestController extends WallabagRestController $userManager = $this->get('fos_user.user_manager'); $user = $userManager->createUser(); - // user will be disabled BY DEFAULT to avoid spamming account to be created + // user will be disabled BY DEFAULT to avoid spamming account to be enabled $user->setEnabled(false); $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [ -- cgit v1.2.3 From a1e6187406289b6b54f8044ba1f209979454204b Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Fri, 2 Jun 2017 20:03:25 +0200 Subject: Return 201 on user creation --- .../ApiBundle/Controller/UserRestController.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/Wallabag/ApiBundle/Controller/UserRestController.php') diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php index a1d7c1ff..8f675b8d 100644 --- a/src/Wallabag/ApiBundle/Controller/UserRestController.php +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php @@ -46,7 +46,9 @@ class UserRestController extends WallabagRestController if (!$this->getParameter('fosuser_registration') || !$this->get('craue_config')->get('api_user_registration')) { $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); - return (new JsonResponse())->setJson($json)->setStatusCode(403); + return (new JsonResponse()) + ->setJson($json) + ->setStatusCode(JsonResponse::HTTP_FORBIDDEN); } $userManager = $this->get('fos_user.user_manager'); @@ -90,7 +92,9 @@ class UserRestController extends WallabagRestController $json = $this->get('serializer')->serialize(['error' => $errors], 'json'); - return (new JsonResponse())->setJson($json)->setStatusCode(400); + return (new JsonResponse()) + ->setJson($json) + ->setStatusCode(JsonResponse::HTTP_BAD_REQUEST); } $userManager->updateUser($user); @@ -99,17 +103,18 @@ class UserRestController extends WallabagRestController $event = new UserEvent($user, $request); $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); - return $this->sendUser($user); + return $this->sendUser($user, JsonResponse::HTTP_CREATED); } /** * Send user response. * * @param User $user + * @param int $status HTTP Status code to send * * @return JsonResponse */ - private function sendUser(User $user) + private function sendUser(User $user, $status = JsonResponse::HTTP_OK) { $json = $this->get('serializer')->serialize( $user, @@ -117,7 +122,9 @@ class UserRestController extends WallabagRestController SerializationContext::create()->setGroups(['user_api']) ); - return (new JsonResponse())->setJson($json); + return (new JsonResponse()) + ->setJson($json) + ->setStatusCode($status); } /** -- cgit v1.2.3 From 0c00e5251671c3648eabb8888271c09137ad902d Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Wed, 7 Jun 2017 23:23:28 +0200 Subject: Create a client when creating a user using the api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While creating a new user using the API, we also create a new client for the current user. So the app which just create the user can use its newly created client to configure the app. That new client is only return after creating the user. When calling the endpoint /api/user to get user information, the new client information won’t be return. --- .../ApiBundle/Controller/UserRestController.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/Wallabag/ApiBundle/Controller/UserRestController.php') diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php index 8f675b8d..becbbb9e 100644 --- a/src/Wallabag/ApiBundle/Controller/UserRestController.php +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php @@ -9,6 +9,7 @@ use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; use Wallabag\UserBundle\Entity\User; +use Wallabag\ApiBundle\Entity\Client; class UserRestController extends WallabagRestController { @@ -97,29 +98,38 @@ class UserRestController extends WallabagRestController ->setStatusCode(JsonResponse::HTTP_BAD_REQUEST); } + // create a default client + $client = new Client($user); + $client->setName('Default client'); + + $this->getDoctrine()->getManager()->persist($client); + + $user->addClient($client); + $userManager->updateUser($user); // dispatch a created event so the associated config will be created $event = new UserEvent($user, $request); $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); - return $this->sendUser($user, JsonResponse::HTTP_CREATED); + return $this->sendUser($user, 'user_api_with_client', JsonResponse::HTTP_CREATED); } /** * Send user response. * - * @param User $user - * @param int $status HTTP Status code to send + * @param User $user + * @param string $group Used to define with serialized group might be used + * @param int $status HTTP Status code to send * * @return JsonResponse */ - private function sendUser(User $user, $status = JsonResponse::HTTP_OK) + private function sendUser(User $user, $group = 'user_api', $status = JsonResponse::HTTP_OK) { $json = $this->get('serializer')->serialize( $user, 'json', - SerializationContext::create()->setGroups(['user_api']) + SerializationContext::create()->setGroups([$group]) ); return (new JsonResponse()) -- cgit v1.2.3 From a8d3fe50df52ec486add5691a3b67fe5205a032e Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Thu, 8 Jun 2017 14:25:44 +0200 Subject: Add ability to name the client --- src/Wallabag/ApiBundle/Controller/UserRestController.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/Wallabag/ApiBundle/Controller/UserRestController.php') diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php index becbbb9e..7471f5f6 100644 --- a/src/Wallabag/ApiBundle/Controller/UserRestController.php +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php @@ -28,13 +28,14 @@ class UserRestController extends WallabagRestController } /** - * Register an user. + * Register an user and create a client. * * @ApiDoc( * requirements={ * {"name"="username", "dataType"="string", "required"=true, "description"="The user's username"}, * {"name"="password", "dataType"="string", "required"=true, "description"="The user's password"}, - * {"name"="email", "dataType"="string", "required"=true, "description"="The user's email"} + * {"name"="email", "dataType"="string", "required"=true, "description"="The user's email"}, + * {"name"="client_name", "dataType"="string", "required"=true, "description"="The client name (to be used by your app)"} * } * ) * @@ -100,7 +101,7 @@ class UserRestController extends WallabagRestController // create a default client $client = new Client($user); - $client->setName('Default client'); + $client->setName($request->request->get('client_name', 'Default client')); $this->getDoctrine()->getManager()->persist($client); -- cgit v1.2.3 From f808b01692a835673f328d7221ba8c212caa9b61 Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Sat, 1 Jul 2017 09:52:38 +0200 Subject: Add a real configuration for CS-Fixer --- src/Wallabag/ApiBundle/Controller/UserRestController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/Wallabag/ApiBundle/Controller/UserRestController.php') diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php index 7471f5f6..6f47cff0 100644 --- a/src/Wallabag/ApiBundle/Controller/UserRestController.php +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php @@ -6,10 +6,10 @@ use FOS\UserBundle\Event\UserEvent; use FOS\UserBundle\FOSUserEvents; use JMS\Serializer\SerializationContext; use Nelmio\ApiDocBundle\Annotation\ApiDoc; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; -use Wallabag\UserBundle\Entity\User; +use Symfony\Component\HttpFoundation\Request; use Wallabag\ApiBundle\Entity\Client; +use Wallabag\UserBundle\Entity\User; class UserRestController extends WallabagRestController { -- cgit v1.2.3 From f40c88eb1fa349aab600f9c1c94364f317fe62dd Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Mon, 9 Oct 2017 16:45:09 +0200 Subject: Jump to Symfony 3.3 & update others deps Also update tests urls --- src/Wallabag/ApiBundle/Controller/UserRestController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/Wallabag/ApiBundle/Controller/UserRestController.php') diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php index 6f47cff0..a1378fc5 100644 --- a/src/Wallabag/ApiBundle/Controller/UserRestController.php +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php @@ -46,7 +46,7 @@ class UserRestController extends WallabagRestController public function putUserAction(Request $request) { if (!$this->getParameter('fosuser_registration') || !$this->get('craue_config')->get('api_user_registration')) { - $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); + $json = $this->get('jms_serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); return (new JsonResponse()) ->setJson($json) @@ -92,7 +92,7 @@ class UserRestController extends WallabagRestController $errors['password'] = $this->translateErrors($data['plainPassword']['children']['first']['errors']); } - $json = $this->get('serializer')->serialize(['error' => $errors], 'json'); + $json = $this->get('jms_serializer')->serialize(['error' => $errors], 'json'); return (new JsonResponse()) ->setJson($json) @@ -127,7 +127,7 @@ class UserRestController extends WallabagRestController */ private function sendUser(User $user, $group = 'user_api', $status = JsonResponse::HTTP_OK) { - $json = $this->get('serializer')->serialize( + $json = $this->get('jms_serializer')->serialize( $user, 'json', SerializationContext::create()->setGroups([$group]) -- cgit v1.2.3