aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag/ApiBundle/Controller/UserRestController.php
blob: 7471f5f62bea79c1d211fd9d1a926dfb2cb42701 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<?php

namespace Wallabag\ApiBundle\Controller;

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 Wallabag\ApiBundle\Entity\Client;

class UserRestController extends WallabagRestController
{
    /**
     * Retrieve current logged in user informations.
     *
     * @ApiDoc()
     *
     * @return JsonResponse
     */
    public function getUserAction()
    {
        $this->validateAuthentication();

        return $this->sendUser($this->getUser());
    }

    /**
     * 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"="client_name", "dataType"="string", "required"=true, "description"="The client name (to be used by your app)"}
     *      }
     * )
     *
     * @todo Make this method (or the whole API) accessible only through https
     *
     * @return JsonResponse
     */
    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');

            return (new JsonResponse())
                ->setJson($json)
                ->setStatusCode(JsonResponse::HTTP_FORBIDDEN);
        }

        $userManager = $this->get('fos_user.user_manager');
        $user = $userManager->createUser();
        // user will be disabled BY DEFAULT to avoid spamming account to be enabled
        $user->setEnabled(false);

        $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [
            'csrf_protection' => false,
        ]);

        // 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 ($form->isSubmitted() && false === $form->isValid()) {
            $view = $this->view($form, 400);
            $view->setFormat('json');

            // handle errors in a more beautiful way than the default view
            $data = json_decode($this->handleView($view)->getContent(), true)['children'];
            $errors = [];

            if (isset($data['username']['errors'])) {
                $errors['username'] = $this->translateErrors($data['username']['errors']);
            }

            if (isset($data['email']['errors'])) {
                $errors['email'] = $this->translateErrors($data['email']['errors']);
            }

            if (isset($data['plainPassword']['children']['first']['errors'])) {
                $errors['password'] = $this->translateErrors($data['plainPassword']['children']['first']['errors']);
            }

            $json = $this->get('serializer')->serialize(['error' => $errors], 'json');

            return (new JsonResponse())
                ->setJson($json)
                ->setStatusCode(JsonResponse::HTTP_BAD_REQUEST);
        }

        // create a default client
        $client = new Client($user);
        $client->setName($request->request->get('client_name', '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, 'user_api_with_client', JsonResponse::HTTP_CREATED);
    }

    /**
     * Send user response.
     *
     * @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, $group = 'user_api', $status = JsonResponse::HTTP_OK)
    {
        $json = $this->get('serializer')->serialize(
            $user,
            'json',
            SerializationContext::create()->setGroups([$group])
        );

        return (new JsonResponse())
            ->setJson($json)
            ->setStatusCode($status);
    }

    /**
     * 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;
    }
}