aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag/ApiBundle/Controller/UserRestController.php
diff options
context:
space:
mode:
authorJeremy Benoist <jeremy.benoist@gmail.com>2017-05-30 07:56:01 +0200
committerJeremy Benoist <jeremy.benoist@gmail.com>2017-05-30 07:56:01 +0200
commit5709ecb36809fb009446a11a758232bbe8f264e4 (patch)
tree0880f40fe8e6e563ef5648c267bb1f65251a0355 /src/Wallabag/ApiBundle/Controller/UserRestController.php
parent2251045901875aa815dee43ec467fb1af8d416d0 (diff)
downloadwallabag-5709ecb36809fb009446a11a758232bbe8f264e4.tar.gz
wallabag-5709ecb36809fb009446a11a758232bbe8f264e4.tar.zst
wallabag-5709ecb36809fb009446a11a758232bbe8f264e4.zip
Re-use `NewUserType` to validate registration
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
Diffstat (limited to 'src/Wallabag/ApiBundle/Controller/UserRestController.php')
-rw-r--r--src/Wallabag/ApiBundle/Controller/UserRestController.php119
1 files changed, 80 insertions, 39 deletions
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;
6use FOS\UserBundle\FOSUserEvents; 6use FOS\UserBundle\FOSUserEvents;
7use JMS\Serializer\SerializationContext; 7use JMS\Serializer\SerializationContext;
8use Nelmio\ApiDocBundle\Annotation\ApiDoc; 8use Nelmio\ApiDocBundle\Annotation\ApiDoc;
9use Symfony\Component\HttpFoundation\Request;
9use Symfony\Component\HttpFoundation\JsonResponse; 10use Symfony\Component\HttpFoundation\JsonResponse;
11use Wallabag\UserBundle\Entity\User;
10 12
11class UserRestController extends WallabagRestController 13class UserRestController extends WallabagRestController
12{ 14{
13 /** 15 /**
14 * Retrieve user informations 16 * Retrieve current logged in user informations.
15 * 17 *
16 * @ApiDoc() 18 * @ApiDoc()
17 * 19 *
@@ -21,78 +23,117 @@ class UserRestController extends WallabagRestController
21 { 23 {
22 $this->validateAuthentication(); 24 $this->validateAuthentication();
23 25
24 $serializationContext = SerializationContext::create()->setGroups(['user_api']); 26 return $this->sendUser($this->getUser());
25 $json = $this->get('serializer')->serialize($this->getUser(), 'json', $serializationContext);
26
27 return (new JsonResponse())->setJson($json);
28 } 27 }
29 28
30 /** 29 /**
31 * Register an user 30 * Register an user.
32 * 31 *
33 * @ApiDoc( 32 * @ApiDoc(
34 * requirements={ 33 * requirements={
35 * {"name"="username", "dataType"="string", "required"=true, "description"="The user's username"}, 34 * {"name"="username", "dataType"="string", "required"=true, "description"="The user's username"},
36 * {"name"="password", "dataType"="string", "required"=true, "description"="The user's password"} 35 * {"name"="password", "dataType"="string", "required"=true, "description"="The user's password"},
37 * {"name"="email", "dataType"="string", "required"=true, "description"="The user's email"} 36 * {"name"="email", "dataType"="string", "required"=true, "description"="The user's email"}
38 * } 37 * }
39 * ) 38 * )
39 *
40 * @todo Make this method (or the whole API) accessible only through https
41 *
40 * @return JsonResponse 42 * @return JsonResponse
41 */ 43 */
42 // TODO : Make this method (or the whole API) accessible only through https 44 public function putUserAction(Request $request)
43 public function putUserAction($username, $password, $email)
44 { 45 {
45 if (!$this->container->getParameter('fosuser_registration')) { 46 if (!$this->container->getParameter('fosuser_registration')) {
46 $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); 47 $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json');
48
47 return (new JsonResponse())->setJson($json)->setStatusCode(403); 49 return (new JsonResponse())->setJson($json)->setStatusCode(403);
48 } 50 }
49 51
50 if ($password === '') { // TODO : might be a good idea to enforce restrictions here 52 $userManager = $this->get('fos_user.user_manager');
51 $json = $this->get('serializer')->serialize(['error' => 'Password is blank'], 'json'); 53 $user = $userManager->createUser();
52 return (new JsonResponse())->setJson($json)->setStatusCode(400); 54 // enable created user by default
53 } 55 $user->setEnabled(true);
54 56
57 $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [
58 'csrf_protection' => false,
59 ]);
55 60
56 // TODO : Make only one call to database by using a custom repository method 61 // simulate form submission
57 if ($this->getDoctrine() 62 $form->submit([
58 ->getRepository('WallabagUserBundle:User') 63 'username' => $request->request->get('username'),
59 ->findOneByUserName($username)) { 64 'plainPassword' => [
60 $json = $this->get('serializer')->serialize(['error' => 'Username is already taken'], 'json'); 65 'first' => $request->request->get('password'),
61 return (new JsonResponse())->setJson($json)->setStatusCode(409); 66 'second' => $request->request->get('password'),
62 } 67 ],
68 'email' => $request->request->get('email'),
69 ]);
63 70
64 if ($this->getDoctrine() 71 if ($form->isSubmitted() && false === $form->isValid()) {
65 ->getRepository('WallabagUserBundle:User') 72 $view = $this->view($form, 400);
66 ->findOneByEmail($email)) { 73 $view->setFormat('json');
67 $json = $this->get('serializer')->serialize(['error' => 'An account with this email already exists'], 'json');
68 return (new JsonResponse())->setJson($json)->setStatusCode(409);
69 }
70 74
71 $em = $this->get('doctrine.orm.entity_manager'); 75 // handle errors in a more beautiful way than the default view
76 $data = json_decode($this->handleView($view)->getContent(), true)['children'];
77 $errors = [];
72 78
73 $userManager = $this->get('fos_user.user_manager'); 79 if (isset($data['username']['errors'])) {
74 $user = $userManager->createUser(); 80 $errors['username'] = $this->translateErrors($data['username']['errors']);
81 }
75 82
76 $user->setUsername($username); 83 if (isset($data['email']['errors'])) {
84 $errors['email'] = $this->translateErrors($data['email']['errors']);
85 }
77 86
78 $user->setPlainPassword($password); 87 if (isset($data['plainPassword']['children']['first']['errors'])) {
88 $errors['password'] = $this->translateErrors($data['plainPassword']['children']['first']['errors']);
89 }
79 90
80 $user->setEmail($email); 91 $json = $this->get('serializer')->serialize(['error' => $errors], 'json');
81 92
82 $user->setEnabled(true); 93 return (new JsonResponse())->setJson($json)->setStatusCode(400);
83 $user->addRole('ROLE_USER'); 94 }
84 95
85 $em->persist($user); 96 $userManager->updateUser($user);
86 97
87 // dispatch a created event so the associated config will be created 98 // dispatch a created event so the associated config will be created
88 $event = new UserEvent($user); 99 $event = new UserEvent($user, $request);
89 $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); 100 $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event);
90 101
91 $serializationContext = SerializationContext::create()->setGroups(['user_api']); 102 return $this->sendUser($user);
92 $json = $this->get('serializer')->serialize($user, 'json', $serializationContext); 103 }
93 104
94 return (new JsonResponse())->setJson($json); 105 /**
106 * Send user response.
107 *
108 * @param User $user
109 *
110 * @return JsonResponse
111 */
112 private function sendUser(User $user)
113 {
114 $json = $this->get('serializer')->serialize(
115 $user,
116 'json',
117 SerializationContext::create()->setGroups(['user_api'])
118 );
95 119
120 return (new JsonResponse())->setJson($json);
96 } 121 }
97 122
123 /**
124 * Translate errors message.
125 *
126 * @param array $errors
127 *
128 * @return array
129 */
130 private function translateErrors($errors)
131 {
132 $translatedErrors = [];
133 foreach ($errors as $error) {
134 $translatedErrors[] = $this->get('translator')->trans($error);
135 }
136
137 return $translatedErrors;
138 }
98} 139}