diff options
author | Jérémy Benoist <j0k3r@users.noreply.github.com> | 2017-06-08 17:24:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-08 17:24:49 +0200 |
commit | 3f474025d889c3eff20b481f005f4d292f1ef29d (patch) | |
tree | e74288b7df91e226b1d23a4047a3af5cc04a6484 | |
parent | 2da8f071cfcc6e50be7be66c037de23f0d073bea (diff) | |
parent | a8d3fe50df52ec486add5691a3b67fe5205a032e (diff) | |
download | wallabag-3f474025d889c3eff20b481f005f4d292f1ef29d.tar.gz wallabag-3f474025d889c3eff20b481f005f4d292f1ef29d.tar.zst wallabag-3f474025d889c3eff20b481f005f4d292f1ef29d.zip |
Merge pull request #3187 from wallabag/api-client-credentials
Create (and return) a client after creating a new user using the API
7 files changed, 88 insertions, 19 deletions
diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php index 8f675b8d..7471f5f6 100644 --- a/src/Wallabag/ApiBundle/Controller/UserRestController.php +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php | |||
@@ -9,6 +9,7 @@ use Nelmio\ApiDocBundle\Annotation\ApiDoc; | |||
9 | use Symfony\Component\HttpFoundation\Request; | 9 | use Symfony\Component\HttpFoundation\Request; |
10 | use Symfony\Component\HttpFoundation\JsonResponse; | 10 | use Symfony\Component\HttpFoundation\JsonResponse; |
11 | use Wallabag\UserBundle\Entity\User; | 11 | use Wallabag\UserBundle\Entity\User; |
12 | use Wallabag\ApiBundle\Entity\Client; | ||
12 | 13 | ||
13 | class UserRestController extends WallabagRestController | 14 | class UserRestController extends WallabagRestController |
14 | { | 15 | { |
@@ -27,13 +28,14 @@ class UserRestController extends WallabagRestController | |||
27 | } | 28 | } |
28 | 29 | ||
29 | /** | 30 | /** |
30 | * Register an user. | 31 | * Register an user and create a client. |
31 | * | 32 | * |
32 | * @ApiDoc( | 33 | * @ApiDoc( |
33 | * requirements={ | 34 | * requirements={ |
34 | * {"name"="username", "dataType"="string", "required"=true, "description"="The user's username"}, | 35 | * {"name"="username", "dataType"="string", "required"=true, "description"="The user's username"}, |
35 | * {"name"="password", "dataType"="string", "required"=true, "description"="The user's password"}, | 36 | * {"name"="password", "dataType"="string", "required"=true, "description"="The user's password"}, |
36 | * {"name"="email", "dataType"="string", "required"=true, "description"="The user's email"} | 37 | * {"name"="email", "dataType"="string", "required"=true, "description"="The user's email"}, |
38 | * {"name"="client_name", "dataType"="string", "required"=true, "description"="The client name (to be used by your app)"} | ||
37 | * } | 39 | * } |
38 | * ) | 40 | * ) |
39 | * | 41 | * |
@@ -97,29 +99,38 @@ class UserRestController extends WallabagRestController | |||
97 | ->setStatusCode(JsonResponse::HTTP_BAD_REQUEST); | 99 | ->setStatusCode(JsonResponse::HTTP_BAD_REQUEST); |
98 | } | 100 | } |
99 | 101 | ||
102 | // create a default client | ||
103 | $client = new Client($user); | ||
104 | $client->setName($request->request->get('client_name', 'Default client')); | ||
105 | |||
106 | $this->getDoctrine()->getManager()->persist($client); | ||
107 | |||
108 | $user->addClient($client); | ||
109 | |||
100 | $userManager->updateUser($user); | 110 | $userManager->updateUser($user); |
101 | 111 | ||
102 | // dispatch a created event so the associated config will be created | 112 | // dispatch a created event so the associated config will be created |
103 | $event = new UserEvent($user, $request); | 113 | $event = new UserEvent($user, $request); |
104 | $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); | 114 | $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); |
105 | 115 | ||
106 | return $this->sendUser($user, JsonResponse::HTTP_CREATED); | 116 | return $this->sendUser($user, 'user_api_with_client', JsonResponse::HTTP_CREATED); |
107 | } | 117 | } |
108 | 118 | ||
109 | /** | 119 | /** |
110 | * Send user response. | 120 | * Send user response. |
111 | * | 121 | * |
112 | * @param User $user | 122 | * @param User $user |
113 | * @param int $status HTTP Status code to send | 123 | * @param string $group Used to define with serialized group might be used |
124 | * @param int $status HTTP Status code to send | ||
114 | * | 125 | * |
115 | * @return JsonResponse | 126 | * @return JsonResponse |
116 | */ | 127 | */ |
117 | private function sendUser(User $user, $status = JsonResponse::HTTP_OK) | 128 | private function sendUser(User $user, $group = 'user_api', $status = JsonResponse::HTTP_OK) |
118 | { | 129 | { |
119 | $json = $this->get('serializer')->serialize( | 130 | $json = $this->get('serializer')->serialize( |
120 | $user, | 131 | $user, |
121 | 'json', | 132 | 'json', |
122 | SerializationContext::create()->setGroups(['user_api']) | 133 | SerializationContext::create()->setGroups([$group]) |
123 | ); | 134 | ); |
124 | 135 | ||
125 | return (new JsonResponse()) | 136 | return (new JsonResponse()) |
diff --git a/src/Wallabag/ApiBundle/Entity/Client.php b/src/Wallabag/ApiBundle/Entity/Client.php index 9ed9f980..c15fd3fa 100644 --- a/src/Wallabag/ApiBundle/Entity/Client.php +++ b/src/Wallabag/ApiBundle/Entity/Client.php | |||
@@ -5,6 +5,9 @@ namespace Wallabag\ApiBundle\Entity; | |||
5 | use Doctrine\ORM\Mapping as ORM; | 5 | use Doctrine\ORM\Mapping as ORM; |
6 | use FOS\OAuthServerBundle\Entity\Client as BaseClient; | 6 | use FOS\OAuthServerBundle\Entity\Client as BaseClient; |
7 | use Wallabag\UserBundle\Entity\User; | 7 | use Wallabag\UserBundle\Entity\User; |
8 | use JMS\Serializer\Annotation\Groups; | ||
9 | use JMS\Serializer\Annotation\SerializedName; | ||
10 | use JMS\Serializer\Annotation\VirtualProperty; | ||
8 | 11 | ||
9 | /** | 12 | /** |
10 | * @ORM\Table("oauth2_clients") | 13 | * @ORM\Table("oauth2_clients") |
@@ -23,6 +26,8 @@ class Client extends BaseClient | |||
23 | * @var string | 26 | * @var string |
24 | * | 27 | * |
25 | * @ORM\Column(name="name", type="text", nullable=false) | 28 | * @ORM\Column(name="name", type="text", nullable=false) |
29 | * | ||
30 | * @Groups({"user_api_with_client"}) | ||
26 | */ | 31 | */ |
27 | protected $name; | 32 | protected $name; |
28 | 33 | ||
@@ -37,6 +42,14 @@ class Client extends BaseClient | |||
37 | protected $accessTokens; | 42 | protected $accessTokens; |
38 | 43 | ||
39 | /** | 44 | /** |
45 | * @var string | ||
46 | * | ||
47 | * @SerializedName("client_secret") | ||
48 | * @Groups({"user_api_with_client"}) | ||
49 | */ | ||
50 | protected $secret; | ||
51 | |||
52 | /** | ||
40 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="clients") | 53 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="clients") |
41 | */ | 54 | */ |
42 | private $user; | 55 | private $user; |
@@ -78,4 +91,14 @@ class Client extends BaseClient | |||
78 | { | 91 | { |
79 | return $this->user; | 92 | return $this->user; |
80 | } | 93 | } |
94 | |||
95 | /** | ||
96 | * @VirtualProperty | ||
97 | * @SerializedName("client_id") | ||
98 | * @Groups({"user_api_with_client"}) | ||
99 | */ | ||
100 | public function getClientId() | ||
101 | { | ||
102 | return $this->getId().'_'.$this->getRandomId(); | ||
103 | } | ||
81 | } | 104 | } |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Developer/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Developer/index.html.twig index b3f0affb..528b055c 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/common/Developer/index.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/common/Developer/index.html.twig | |||
@@ -33,7 +33,7 @@ | |||
33 | <table class="striped"> | 33 | <table class="striped"> |
34 | <tr> | 34 | <tr> |
35 | <td>{{ 'developer.existing_clients.field_id'|trans }}</td> | 35 | <td>{{ 'developer.existing_clients.field_id'|trans }}</td> |
36 | <td><strong><code>{{ client.id }}_{{ client.randomId }}</code></strong></td> | 36 | <td><strong><code>{{ client.clientId }}</code></strong></td> |
37 | </tr> | 37 | </tr> |
38 | <tr> | 38 | <tr> |
39 | <td>{{ 'developer.existing_clients.field_secret'|trans }}</td> | 39 | <td>{{ 'developer.existing_clients.field_secret'|trans }}</td> |
diff --git a/src/Wallabag/UserBundle/Entity/User.php b/src/Wallabag/UserBundle/Entity/User.php index ed6ce331..aba76ca7 100644 --- a/src/Wallabag/UserBundle/Entity/User.php +++ b/src/Wallabag/UserBundle/Entity/User.php | |||
@@ -6,6 +6,7 @@ use Doctrine\Common\Collections\ArrayCollection; | |||
6 | use Doctrine\ORM\Mapping as ORM; | 6 | use Doctrine\ORM\Mapping as ORM; |
7 | use JMS\Serializer\Annotation\Groups; | 7 | use JMS\Serializer\Annotation\Groups; |
8 | use JMS\Serializer\Annotation\XmlRoot; | 8 | use JMS\Serializer\Annotation\XmlRoot; |
9 | use JMS\Serializer\Annotation\Accessor; | ||
9 | use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface; | 10 | use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface; |
10 | use Scheb\TwoFactorBundle\Model\TrustedComputerInterface; | 11 | use Scheb\TwoFactorBundle\Model\TrustedComputerInterface; |
11 | use FOS\UserBundle\Model\User as BaseUser; | 12 | use FOS\UserBundle\Model\User as BaseUser; |
@@ -36,7 +37,7 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
36 | * @ORM\Id | 37 | * @ORM\Id |
37 | * @ORM\GeneratedValue(strategy="AUTO") | 38 | * @ORM\GeneratedValue(strategy="AUTO") |
38 | * | 39 | * |
39 | * @Groups({"user_api"}) | 40 | * @Groups({"user_api", "user_api_with_client"}) |
40 | */ | 41 | */ |
41 | protected $id; | 42 | protected $id; |
42 | 43 | ||
@@ -45,21 +46,21 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
45 | * | 46 | * |
46 | * @ORM\Column(name="name", type="text", nullable=true) | 47 | * @ORM\Column(name="name", type="text", nullable=true) |
47 | * | 48 | * |
48 | * @Groups({"user_api"}) | 49 | * @Groups({"user_api", "user_api_with_client"}) |
49 | */ | 50 | */ |
50 | protected $name; | 51 | protected $name; |
51 | 52 | ||
52 | /** | 53 | /** |
53 | * @var string | 54 | * @var string |
54 | * | 55 | * |
55 | * @Groups({"user_api"}) | 56 | * @Groups({"user_api", "user_api_with_client"}) |
56 | */ | 57 | */ |
57 | protected $username; | 58 | protected $username; |
58 | 59 | ||
59 | /** | 60 | /** |
60 | * @var string | 61 | * @var string |
61 | * | 62 | * |
62 | * @Groups({"user_api"}) | 63 | * @Groups({"user_api", "user_api_with_client"}) |
63 | */ | 64 | */ |
64 | protected $email; | 65 | protected $email; |
65 | 66 | ||
@@ -68,7 +69,7 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
68 | * | 69 | * |
69 | * @ORM\Column(name="created_at", type="datetime") | 70 | * @ORM\Column(name="created_at", type="datetime") |
70 | * | 71 | * |
71 | * @Groups({"user_api"}) | 72 | * @Groups({"user_api", "user_api_with_client"}) |
72 | */ | 73 | */ |
73 | protected $createdAt; | 74 | protected $createdAt; |
74 | 75 | ||
@@ -77,7 +78,7 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
77 | * | 78 | * |
78 | * @ORM\Column(name="updated_at", type="datetime") | 79 | * @ORM\Column(name="updated_at", type="datetime") |
79 | * | 80 | * |
80 | * @Groups({"user_api"}) | 81 | * @Groups({"user_api", "user_api_with_client"}) |
81 | */ | 82 | */ |
82 | protected $updatedAt; | 83 | protected $updatedAt; |
83 | 84 | ||
@@ -97,7 +98,8 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
97 | private $authCode; | 98 | private $authCode; |
98 | 99 | ||
99 | /** | 100 | /** |
100 | * @var bool Enabled yes/no | 101 | * @var bool |
102 | * | ||
101 | * @ORM\Column(type="boolean") | 103 | * @ORM\Column(type="boolean") |
102 | */ | 104 | */ |
103 | private $twoFactorAuthentication = false; | 105 | private $twoFactorAuthentication = false; |
@@ -108,10 +110,20 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
108 | private $trusted; | 110 | private $trusted; |
109 | 111 | ||
110 | /** | 112 | /** |
113 | * @var ArrayCollection | ||
114 | * | ||
111 | * @ORM\OneToMany(targetEntity="Wallabag\ApiBundle\Entity\Client", mappedBy="user", cascade={"remove"}) | 115 | * @ORM\OneToMany(targetEntity="Wallabag\ApiBundle\Entity\Client", mappedBy="user", cascade={"remove"}) |
112 | */ | 116 | */ |
113 | protected $clients; | 117 | protected $clients; |
114 | 118 | ||
119 | /** | ||
120 | * @see getFirstClient() below | ||
121 | * | ||
122 | * @Groups({"user_api_with_client"}) | ||
123 | * @Accessor(getter="getFirstClient") | ||
124 | */ | ||
125 | protected $default_client; | ||
126 | |||
115 | public function __construct() | 127 | public function __construct() |
116 | { | 128 | { |
117 | parent::__construct(); | 129 | parent::__construct(); |
@@ -288,4 +300,16 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
288 | { | 300 | { |
289 | return $this->clients; | 301 | return $this->clients; |
290 | } | 302 | } |
303 | |||
304 | /** | ||
305 | * Only used by the API when creating a new user it'll also return the first client (which was also created at the same time). | ||
306 | * | ||
307 | * @return Client | ||
308 | */ | ||
309 | public function getFirstClient() | ||
310 | { | ||
311 | if (!empty($this->clients)) { | ||
312 | return $this->clients->first(); | ||
313 | } | ||
314 | } | ||
291 | } | 315 | } |
diff --git a/tests/Wallabag/AnnotationBundle/Controller/AnnotationControllerTest.php b/tests/Wallabag/AnnotationBundle/Controller/AnnotationControllerTest.php index 8f87ccf3..3c94382c 100644 --- a/tests/Wallabag/AnnotationBundle/Controller/AnnotationControllerTest.php +++ b/tests/Wallabag/AnnotationBundle/Controller/AnnotationControllerTest.php | |||
@@ -85,7 +85,7 @@ class AnnotationControllerTest extends WallabagAnnotationTestCase | |||
85 | 'text' => 'my annotation', | 85 | 'text' => 'my annotation', |
86 | 'quote' => 'my quote', | 86 | 'quote' => 'my quote', |
87 | 'ranges' => [ | 87 | 'ranges' => [ |
88 | ['start' => '', 'startOffset' => 24, 'end' => '', 'endOffset' => 31] | 88 | ['start' => '', 'startOffset' => 24, 'end' => '', 'endOffset' => 31], |
89 | ], | 89 | ], |
90 | ]); | 90 | ]); |
91 | $this->client->request('POST', $prefixUrl.'/'.$entry->getId().'.json', [], [], $headers, $content); | 91 | $this->client->request('POST', $prefixUrl.'/'.$entry->getId().'.json', [], [], $headers, $content); |
@@ -130,7 +130,7 @@ class AnnotationControllerTest extends WallabagAnnotationTestCase | |||
130 | 'text' => 'my annotation', | 130 | 'text' => 'my annotation', |
131 | 'quote' => $longQuote, | 131 | 'quote' => $longQuote, |
132 | 'ranges' => [ | 132 | 'ranges' => [ |
133 | ['start' => '', 'startOffset' => 24, 'end' => '', 'endOffset' => 31] | 133 | ['start' => '', 'startOffset' => 24, 'end' => '', 'endOffset' => 31], |
134 | ], | 134 | ], |
135 | ]); | 135 | ]); |
136 | $this->client->request('POST', $prefixUrl.'/'.$entry->getId().'.json', [], [], $headers, $content); | 136 | $this->client->request('POST', $prefixUrl.'/'.$entry->getId().'.json', [], [], $headers, $content); |
diff --git a/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php index 5735bc58..4e65f130 100644 --- a/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php +++ b/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php | |||
@@ -61,10 +61,16 @@ class UserRestControllerTest extends WallabagApiTestCase | |||
61 | $this->assertArrayHasKey('username', $content); | 61 | $this->assertArrayHasKey('username', $content); |
62 | $this->assertArrayHasKey('created_at', $content); | 62 | $this->assertArrayHasKey('created_at', $content); |
63 | $this->assertArrayHasKey('updated_at', $content); | 63 | $this->assertArrayHasKey('updated_at', $content); |
64 | $this->assertArrayHasKey('default_client', $content); | ||
64 | 65 | ||
65 | $this->assertEquals('wallabag@google.com', $content['email']); | 66 | $this->assertEquals('wallabag@google.com', $content['email']); |
66 | $this->assertEquals('google', $content['username']); | 67 | $this->assertEquals('google', $content['username']); |
67 | 68 | ||
69 | $this->assertArrayHasKey('client_secret', $content['default_client']); | ||
70 | $this->assertArrayHasKey('client_id', $content['default_client']); | ||
71 | |||
72 | $this->assertEquals('Default client', $content['default_client']['name']); | ||
73 | |||
68 | $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); | 74 | $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); |
69 | 75 | ||
70 | $this->client->getContainer()->get('craue_config')->set('api_user_registration', 0); | 76 | $this->client->getContainer()->get('craue_config')->set('api_user_registration', 0); |
@@ -79,6 +85,7 @@ class UserRestControllerTest extends WallabagApiTestCase | |||
79 | 'username' => 'google', | 85 | 'username' => 'google', |
80 | 'password' => 'googlegoogle', | 86 | 'password' => 'googlegoogle', |
81 | 'email' => 'wallabag@google.com', | 87 | 'email' => 'wallabag@google.com', |
88 | 'client_name' => 'My client name !!', | ||
82 | ]); | 89 | ]); |
83 | 90 | ||
84 | $this->assertEquals(201, $client->getResponse()->getStatusCode()); | 91 | $this->assertEquals(201, $client->getResponse()->getStatusCode()); |
@@ -90,10 +97,16 @@ class UserRestControllerTest extends WallabagApiTestCase | |||
90 | $this->assertArrayHasKey('username', $content); | 97 | $this->assertArrayHasKey('username', $content); |
91 | $this->assertArrayHasKey('created_at', $content); | 98 | $this->assertArrayHasKey('created_at', $content); |
92 | $this->assertArrayHasKey('updated_at', $content); | 99 | $this->assertArrayHasKey('updated_at', $content); |
100 | $this->assertArrayHasKey('default_client', $content); | ||
93 | 101 | ||
94 | $this->assertEquals('wallabag@google.com', $content['email']); | 102 | $this->assertEquals('wallabag@google.com', $content['email']); |
95 | $this->assertEquals('google', $content['username']); | 103 | $this->assertEquals('google', $content['username']); |
96 | 104 | ||
105 | $this->assertArrayHasKey('client_secret', $content['default_client']); | ||
106 | $this->assertArrayHasKey('client_id', $content['default_client']); | ||
107 | |||
108 | $this->assertEquals('My client name !!', $content['default_client']['name']); | ||
109 | |||
97 | $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type')); | 110 | $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type')); |
98 | 111 | ||
99 | $client->getContainer()->get('craue_config')->set('api_user_registration', 0); | 112 | $client->getContainer()->get('craue_config')->set('api_user_registration', 0); |
diff --git a/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php b/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php index 3b928d1e..c0a4acfa 100644 --- a/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php +++ b/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php | |||
@@ -4,10 +4,8 @@ namespace Tests\Wallabag\CoreBundle\Command; | |||
4 | 4 | ||
5 | use Symfony\Bundle\FrameworkBundle\Console\Application; | 5 | use Symfony\Bundle\FrameworkBundle\Console\Application; |
6 | use Symfony\Component\Console\Tester\CommandTester; | 6 | use Symfony\Component\Console\Tester\CommandTester; |
7 | use Wallabag\CoreBundle\Command\CleanDuplicatesCommand; | ||
8 | use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; | 7 | use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; |
9 | use Wallabag\CoreBundle\Command\ShowUserCommand; | 8 | use Wallabag\CoreBundle\Command\ShowUserCommand; |
10 | use Wallabag\CoreBundle\Entity\Entry; | ||
11 | use Wallabag\UserBundle\Entity\User; | 9 | use Wallabag\UserBundle\Entity\User; |
12 | 10 | ||
13 | class ShowUserCommandTest extends WallabagCoreTestCase | 11 | class ShowUserCommandTest extends WallabagCoreTestCase |