diff options
author | Thomas Citharel <tcit@tcit.fr> | 2017-04-30 09:16:55 +0200 |
---|---|---|
committer | Thomas Citharel <tcit@tcit.fr> | 2017-06-14 17:53:52 +0200 |
commit | 0f8268c93e6210d368f9dcd1900274871a9eacdf (patch) | |
tree | 251024ae114d2a14a67399ba28d02ddb6d031bad /src/Wallabag/ApiBundle | |
parent | f93a3109a5f0999dbbd69131c9e5041c390120c9 (diff) | |
download | wallabag-0f8268c93e6210d368f9dcd1900274871a9eacdf.tar.gz wallabag-0f8268c93e6210d368f9dcd1900274871a9eacdf.tar.zst wallabag-0f8268c93e6210d368f9dcd1900274871a9eacdf.zip |
Add client_credentials as grant_typeoauth-changes
Therefore, username and password are no longer needed
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
Allow to have global clients, auth through direct token or auth code and bring scopes
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
fix review
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
remove redirect uri requirement on specific clients
add back password and depreciate it
enforce state
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
Allow apps to register themselves
A handful of changes
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
change timeout values
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
set access_token lifetime to 1 year and double for refresh_token
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
Diffstat (limited to 'src/Wallabag/ApiBundle')
10 files changed, 324 insertions, 146 deletions
diff --git a/src/Wallabag/ApiBundle/Controller/AnnotationRestController.php b/src/Wallabag/ApiBundle/Controller/AnnotationRestController.php index 2dd26c07..c524a24c 100644 --- a/src/Wallabag/ApiBundle/Controller/AnnotationRestController.php +++ b/src/Wallabag/ApiBundle/Controller/AnnotationRestController.php | |||
@@ -4,6 +4,7 @@ namespace Wallabag\ApiBundle\Controller; | |||
4 | 4 | ||
5 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | 5 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; |
6 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | 6 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; |
7 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; | ||
7 | use Symfony\Component\HttpFoundation\Request; | 8 | use Symfony\Component\HttpFoundation\Request; |
8 | use Symfony\Component\HttpFoundation\JsonResponse; | 9 | use Symfony\Component\HttpFoundation\JsonResponse; |
9 | use Wallabag\CoreBundle\Entity\Entry; | 10 | use Wallabag\CoreBundle\Entity\Entry; |
@@ -21,7 +22,7 @@ class AnnotationRestController extends WallabagRestController | |||
21 | * ) | 22 | * ) |
22 | * | 23 | * |
23 | * @param Entry $entry | 24 | * @param Entry $entry |
24 | * | 25 | * @Security("has_role('ROLE_READ')") |
25 | * @return JsonResponse | 26 | * @return JsonResponse |
26 | */ | 27 | */ |
27 | public function getAnnotationsAction(Entry $entry) | 28 | public function getAnnotationsAction(Entry $entry) |
@@ -46,7 +47,7 @@ class AnnotationRestController extends WallabagRestController | |||
46 | * | 47 | * |
47 | * @param Request $request | 48 | * @param Request $request |
48 | * @param Entry $entry | 49 | * @param Entry $entry |
49 | * | 50 | * @Security("has_role('ROLE_WRITE')") |
50 | * @return JsonResponse | 51 | * @return JsonResponse |
51 | */ | 52 | */ |
52 | public function postAnnotationAction(Request $request, Entry $entry) | 53 | public function postAnnotationAction(Request $request, Entry $entry) |
@@ -72,7 +73,7 @@ class AnnotationRestController extends WallabagRestController | |||
72 | * | 73 | * |
73 | * @param Annotation $annotation | 74 | * @param Annotation $annotation |
74 | * @param Request $request | 75 | * @param Request $request |
75 | * | 76 | * @Security("has_role('ROLE_WRITE')") |
76 | * @return JsonResponse | 77 | * @return JsonResponse |
77 | */ | 78 | */ |
78 | public function putAnnotationAction(Annotation $annotation, Request $request) | 79 | public function putAnnotationAction(Annotation $annotation, Request $request) |
@@ -97,7 +98,7 @@ class AnnotationRestController extends WallabagRestController | |||
97 | * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation") | 98 | * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation") |
98 | * | 99 | * |
99 | * @param Annotation $annotation | 100 | * @param Annotation $annotation |
100 | * | 101 | * @Security("has_role('ROLE_WRITE')") |
101 | * @return JsonResponse | 102 | * @return JsonResponse |
102 | */ | 103 | */ |
103 | public function deleteAnnotationAction(Annotation $annotation) | 104 | public function deleteAnnotationAction(Annotation $annotation) |
diff --git a/src/Wallabag/ApiBundle/Controller/AppsController.php b/src/Wallabag/ApiBundle/Controller/AppsController.php new file mode 100644 index 00000000..6ef77667 --- /dev/null +++ b/src/Wallabag/ApiBundle/Controller/AppsController.php | |||
@@ -0,0 +1,189 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\ApiBundle\Controller; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; | ||
6 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
7 | use Symfony\Component\Finder\Exception\AccessDeniedException; | ||
8 | use Symfony\Component\HttpFoundation\JsonResponse; | ||
9 | use Symfony\Component\HttpFoundation\Request; | ||
10 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
11 | use Wallabag\ApiBundle\Entity\AccessToken; | ||
12 | use Wallabag\ApiBundle\Entity\Client; | ||
13 | use Wallabag\ApiBundle\Form\Type\ClientType; | ||
14 | |||
15 | class AppsController extends Controller | ||
16 | { | ||
17 | /** | ||
18 | * List all clients and link to create a new one. | ||
19 | * | ||
20 | * @Route("/apps", name="apps") | ||
21 | * | ||
22 | * @return \Symfony\Component\HttpFoundation\Response | ||
23 | */ | ||
24 | public function indexAction() | ||
25 | { | ||
26 | $clients = $this->getDoctrine()->getRepository('WallabagApiBundle:Client')->findByUser($this->getUser()->getId()); | ||
27 | |||
28 | $apps = $this->getDoctrine()->getRepository('WallabagApiBundle:AccessToken')->findAppsByUser($this->getUser()->getId()); | ||
29 | |||
30 | return $this->render('@WallabagCore/themes/common/Developer/index.html.twig', [ | ||
31 | 'clients' => $clients, | ||
32 | 'apps' => $apps, | ||
33 | ]); | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * Create a an app | ||
38 | * | ||
39 | * @param Request $request | ||
40 | * | ||
41 | * @Route("/api/apps", name="apps_create") | ||
42 | * @Method("POST") | ||
43 | * | ||
44 | * @return \Symfony\Component\HttpFoundation\Response | ||
45 | */ | ||
46 | public function createAppAction(Request $request) | ||
47 | { | ||
48 | $em = $this->getDoctrine()->getManager(); | ||
49 | |||
50 | $clientName = $request->request->get('client_name'); | ||
51 | $redirectURIs = $request->request->get('redirect_uris'); | ||
52 | $logoURI = $request->request->get('logo_uri'); | ||
53 | $description = $request->request->get('description'); | ||
54 | $appURI = $request->request->get('app_uri'); | ||
55 | $nextRedirect = $request->request->get('uri_redirect_after_creation'); | ||
56 | |||
57 | if (!$clientName) { | ||
58 | return new JsonResponse([ | ||
59 | 'error' => 'invalid_client_name', | ||
60 | 'error_description' => 'The client name cannot be empty', | ||
61 | ], 400); | ||
62 | } | ||
63 | |||
64 | if (!$redirectURIs) { | ||
65 | return new JsonResponse([ | ||
66 | 'error' => 'invalid_redirect_uri', | ||
67 | 'error_description' => 'One or more redirect_uri values are invalid', | ||
68 | ], 400); | ||
69 | } | ||
70 | |||
71 | $redirectURIs = (array) $redirectURIs; | ||
72 | |||
73 | $client = new Client(); | ||
74 | |||
75 | $client->setName($clientName); | ||
76 | |||
77 | $client->setDescription($description); | ||
78 | |||
79 | $client->setRedirectUris($redirectURIs); | ||
80 | |||
81 | $client->setImage($logoURI); | ||
82 | $client->setAppUrl($appURI); | ||
83 | |||
84 | $client->setAllowedGrantTypes(['token', 'refresh_token', 'authorization_code']); | ||
85 | $em->persist($client); | ||
86 | $em->flush(); | ||
87 | |||
88 | return new JsonResponse([ | ||
89 | 'client_id' => $client->getPublicId(), | ||
90 | 'client_secret' => $client->getSecret(), | ||
91 | 'client_name' => $client->getName(), | ||
92 | 'redirect_uri' => $client->getRedirectUris(), | ||
93 | 'description' => $client->getDescription(), | ||
94 | 'logo_uri' => $client->getImage(), | ||
95 | 'app_uri' => $client->getAppUrl(), | ||
96 | ], 201); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * Create a client (an app). | ||
101 | * | ||
102 | * @param Request $request | ||
103 | * | ||
104 | * @Route("/apps/client/create", name="apps_create_client") | ||
105 | * | ||
106 | * @return \Symfony\Component\HttpFoundation\Response | ||
107 | */ | ||
108 | public function createClientAction(Request $request) | ||
109 | { | ||
110 | $em = $this->getDoctrine()->getManager(); | ||
111 | $client = new Client($this->getUser()); | ||
112 | $clientForm = $this->createForm(ClientType::class, $client); | ||
113 | $clientForm->handleRequest($request); | ||
114 | |||
115 | if ($clientForm->isSubmitted() && $clientForm->isValid()) { | ||
116 | $client->setAllowedGrantTypes(['password', 'token', 'refresh_token', 'client_credentials']); // Password is depreciated | ||
117 | $em->persist($client); | ||
118 | $em->flush(); | ||
119 | |||
120 | $this->get('session')->getFlashBag()->add( | ||
121 | 'notice', | ||
122 | $this->get('translator')->trans('flashes.developer.notice.client_created', ['%name%' => $client->getName()]) | ||
123 | ); | ||
124 | |||
125 | return $this->render('@WallabagCore/themes/common/Developer/client_parameters.html.twig', [ | ||
126 | 'client_id' => $client->getPublicId(), | ||
127 | 'client_secret' => $client->getSecret(), | ||
128 | 'client_name' => $client->getName(), | ||
129 | ]); | ||
130 | } | ||
131 | |||
132 | return $this->render('@WallabagCore/themes/common/Developer/client.html.twig', [ | ||
133 | 'form' => $clientForm->createView(), | ||
134 | ]); | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * Revoke an access token | ||
139 | * @param $token | ||
140 | * @Route("/api/revoke/{token}", name="apps_revoke_access_token") | ||
141 | * @return JsonResponse | ||
142 | */ | ||
143 | public function removeAccessTokenAction($token) | ||
144 | { | ||
145 | if (false === $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { | ||
146 | throw new AccessDeniedException(); | ||
147 | } | ||
148 | |||
149 | $em = $this->getDoctrine()->getManager(); | ||
150 | $accessToken = $em->getRepository('WallabagApiBundle:AccessToken')->findOneBy([ | ||
151 | 'user' => $this->getUser()->getId(), | ||
152 | 'token' => $token | ||
153 | ]); | ||
154 | if ($accessToken) { | ||
155 | $em->remove($accessToken); | ||
156 | $em->flush(); | ||
157 | |||
158 | return new JsonResponse([], 204); | ||
159 | } | ||
160 | return new JsonResponse([], 404); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * Remove a client. | ||
165 | * | ||
166 | * @param Client $client | ||
167 | * | ||
168 | * @Route("/apps/client/delete/{id}", requirements={"id" = "\d+"}, name="apps_delete_client") | ||
169 | * | ||
170 | * @return \Symfony\Component\HttpFoundation\RedirectResponse | ||
171 | */ | ||
172 | public function deleteClientAction(Client $client) | ||
173 | { | ||
174 | if (null === $this->getUser() || $client->getUser()->getId() != $this->getUser()->getId()) { | ||
175 | throw $this->createAccessDeniedException('You can not access this client.'); | ||
176 | } | ||
177 | |||
178 | $em = $this->getDoctrine()->getManager(); | ||
179 | $em->remove($client); | ||
180 | $em->flush(); | ||
181 | |||
182 | $this->get('session')->getFlashBag()->add( | ||
183 | 'notice', | ||
184 | $this->get('translator')->trans('flashes.developer.notice.client_deleted', ['%name%' => $client->getName()]) | ||
185 | ); | ||
186 | |||
187 | return $this->redirect($this->generateUrl('apps')); | ||
188 | } | ||
189 | } | ||
diff --git a/src/Wallabag/ApiBundle/Controller/DeveloperController.php b/src/Wallabag/ApiBundle/Controller/DeveloperController.php deleted file mode 100644 index 9cb1b626..00000000 --- a/src/Wallabag/ApiBundle/Controller/DeveloperController.php +++ /dev/null | |||
@@ -1,105 +0,0 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\ApiBundle\Controller; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Component\HttpFoundation\Request; | ||
7 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
8 | use Wallabag\ApiBundle\Entity\Client; | ||
9 | use Wallabag\ApiBundle\Form\Type\ClientType; | ||
10 | |||
11 | class DeveloperController extends Controller | ||
12 | { | ||
13 | /** | ||
14 | * List all clients and link to create a new one. | ||
15 | * | ||
16 | * @Route("/developer", name="developer") | ||
17 | * | ||
18 | * @return \Symfony\Component\HttpFoundation\Response | ||
19 | */ | ||
20 | public function indexAction() | ||
21 | { | ||
22 | $clients = $this->getDoctrine()->getRepository('WallabagApiBundle:Client')->findByUser($this->getUser()->getId()); | ||
23 | |||
24 | return $this->render('@WallabagCore/themes/common/Developer/index.html.twig', [ | ||
25 | 'clients' => $clients, | ||
26 | ]); | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * Create a client (an app). | ||
31 | * | ||
32 | * @param Request $request | ||
33 | * | ||
34 | * @Route("/developer/client/create", name="developer_create_client") | ||
35 | * | ||
36 | * @return \Symfony\Component\HttpFoundation\Response | ||
37 | */ | ||
38 | public function createClientAction(Request $request) | ||
39 | { | ||
40 | $em = $this->getDoctrine()->getManager(); | ||
41 | $client = new Client($this->getUser()); | ||
42 | $clientForm = $this->createForm(ClientType::class, $client); | ||
43 | $clientForm->handleRequest($request); | ||
44 | |||
45 | if ($clientForm->isSubmitted() && $clientForm->isValid()) { | ||
46 | $client->setAllowedGrantTypes(['token', 'authorization_code', 'password', 'refresh_token']); | ||
47 | $em->persist($client); | ||
48 | $em->flush(); | ||
49 | |||
50 | $this->get('session')->getFlashBag()->add( | ||
51 | 'notice', | ||
52 | $this->get('translator')->trans('flashes.developer.notice.client_created', ['%name%' => $client->getName()]) | ||
53 | ); | ||
54 | |||
55 | return $this->render('@WallabagCore/themes/common/Developer/client_parameters.html.twig', [ | ||
56 | 'client_id' => $client->getPublicId(), | ||
57 | 'client_secret' => $client->getSecret(), | ||
58 | 'client_name' => $client->getName(), | ||
59 | ]); | ||
60 | } | ||
61 | |||
62 | return $this->render('@WallabagCore/themes/common/Developer/client.html.twig', [ | ||
63 | 'form' => $clientForm->createView(), | ||
64 | ]); | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * Remove a client. | ||
69 | * | ||
70 | * @param Client $client | ||
71 | * | ||
72 | * @Route("/developer/client/delete/{id}", requirements={"id" = "\d+"}, name="developer_delete_client") | ||
73 | * | ||
74 | * @return \Symfony\Component\HttpFoundation\RedirectResponse | ||
75 | */ | ||
76 | public function deleteClientAction(Client $client) | ||
77 | { | ||
78 | if (null === $this->getUser() || $client->getUser()->getId() != $this->getUser()->getId()) { | ||
79 | throw $this->createAccessDeniedException('You can not access this client.'); | ||
80 | } | ||
81 | |||
82 | $em = $this->getDoctrine()->getManager(); | ||
83 | $em->remove($client); | ||
84 | $em->flush(); | ||
85 | |||
86 | $this->get('session')->getFlashBag()->add( | ||
87 | 'notice', | ||
88 | $this->get('translator')->trans('flashes.developer.notice.client_deleted', ['%name%' => $client->getName()]) | ||
89 | ); | ||
90 | |||
91 | return $this->redirect($this->generateUrl('developer')); | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * Display developer how to use an existing app. | ||
96 | * | ||
97 | * @Route("/developer/howto/first-app", name="developer_howto_firstapp") | ||
98 | * | ||
99 | * @return \Symfony\Component\HttpFoundation\Response | ||
100 | */ | ||
101 | public function howtoFirstAppAction() | ||
102 | { | ||
103 | return $this->render('@WallabagCore/themes/common/Developer/howto_app.html.twig'); | ||
104 | } | ||
105 | } | ||
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php index 768c4fdc..93f1f461 100644 --- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php +++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php | |||
@@ -5,6 +5,7 @@ namespace Wallabag\ApiBundle\Controller; | |||
5 | use Hateoas\Configuration\Route; | 5 | use Hateoas\Configuration\Route; |
6 | use Hateoas\Representation\Factory\PagerfantaFactory; | 6 | use Hateoas\Representation\Factory\PagerfantaFactory; |
7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | 7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; |
8 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; | ||
8 | use Symfony\Component\HttpKernel\Exception\HttpException; | 9 | use Symfony\Component\HttpKernel\Exception\HttpException; |
9 | use Symfony\Component\HttpFoundation\Request; | 10 | use Symfony\Component\HttpFoundation\Request; |
10 | use Symfony\Component\HttpFoundation\JsonResponse; | 11 | use Symfony\Component\HttpFoundation\JsonResponse; |
@@ -25,7 +26,7 @@ class EntryRestController extends WallabagRestController | |||
25 | * {"name"="urls", "dataType"="string", "required"=false, "format"="An array of urls (?urls[]=http...&urls[]=http...)", "description"="Urls (as an array) to check if it exists"} | 26 | * {"name"="urls", "dataType"="string", "required"=false, "format"="An array of urls (?urls[]=http...&urls[]=http...)", "description"="Urls (as an array) to check if it exists"} |
26 | * } | 27 | * } |
27 | * ) | 28 | * ) |
28 | * | 29 | * @Security("has_role('ROLE_READ')") |
29 | * @return JsonResponse | 30 | * @return JsonResponse |
30 | */ | 31 | */ |
31 | public function getEntriesExistsAction(Request $request) | 32 | public function getEntriesExistsAction(Request $request) |
@@ -80,7 +81,7 @@ class EntryRestController extends WallabagRestController | |||
80 | * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by entries with a public link"}, | 81 | * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by entries with a public link"}, |
81 | * } | 82 | * } |
82 | * ) | 83 | * ) |
83 | * | 84 | * @Security("has_role('ROLE_READ')") |
84 | * @return JsonResponse | 85 | * @return JsonResponse |
85 | */ | 86 | */ |
86 | public function getEntriesAction(Request $request) | 87 | public function getEntriesAction(Request $request) |
@@ -143,7 +144,7 @@ class EntryRestController extends WallabagRestController | |||
143 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | 144 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} |
144 | * } | 145 | * } |
145 | * ) | 146 | * ) |
146 | * | 147 | * @Security("has_role('ROLE_READ')") |
147 | * @return JsonResponse | 148 | * @return JsonResponse |
148 | */ | 149 | */ |
149 | public function getEntryAction(Entry $entry) | 150 | public function getEntryAction(Entry $entry) |
@@ -162,7 +163,7 @@ class EntryRestController extends WallabagRestController | |||
162 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | 163 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} |
163 | * } | 164 | * } |
164 | * ) | 165 | * ) |
165 | * | 166 | * @Security("has_role('ROLE_READ')") |
166 | * @return Response | 167 | * @return Response |
167 | */ | 168 | */ |
168 | public function getEntryExportAction(Entry $entry, Request $request) | 169 | public function getEntryExportAction(Entry $entry, Request $request) |
@@ -302,7 +303,7 @@ class EntryRestController extends WallabagRestController | |||
302 | * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="will generate a public link for the entry"}, | 303 | * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="will generate a public link for the entry"}, |
303 | * } | 304 | * } |
304 | * ) | 305 | * ) |
305 | * | 306 | * @Security("has_role('ROLE_WRITE')") |
306 | * @return JsonResponse | 307 | * @return JsonResponse |
307 | */ | 308 | */ |
308 | public function postEntriesAction(Request $request) | 309 | public function postEntriesAction(Request $request) |
@@ -346,7 +347,7 @@ class EntryRestController extends WallabagRestController | |||
346 | * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="will generate a public link for the entry"}, | 347 | * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="will generate a public link for the entry"}, |
347 | * } | 348 | * } |
348 | * ) | 349 | * ) |
349 | * | 350 | * @Security("has_role('ROLE_WRITE')") |
350 | * @return JsonResponse | 351 | * @return JsonResponse |
351 | */ | 352 | */ |
352 | public function patchEntriesAction(Entry $entry, Request $request) | 353 | public function patchEntriesAction(Entry $entry, Request $request) |
@@ -368,7 +369,7 @@ class EntryRestController extends WallabagRestController | |||
368 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | 369 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} |
369 | * } | 370 | * } |
370 | * ) | 371 | * ) |
371 | * | 372 | * @Security("has_role('ROLE_WRITE')") |
372 | * @return JsonResponse | 373 | * @return JsonResponse |
373 | */ | 374 | */ |
374 | public function patchEntriesReloadAction(Entry $entry) | 375 | public function patchEntriesReloadAction(Entry $entry) |
@@ -410,7 +411,7 @@ class EntryRestController extends WallabagRestController | |||
410 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | 411 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} |
411 | * } | 412 | * } |
412 | * ) | 413 | * ) |
413 | * | 414 | * @Security("has_role('ROLE_WRITE')") |
414 | * @return JsonResponse | 415 | * @return JsonResponse |
415 | */ | 416 | */ |
416 | public function deleteEntriesAction(Entry $entry) | 417 | public function deleteEntriesAction(Entry $entry) |
@@ -436,7 +437,7 @@ class EntryRestController extends WallabagRestController | |||
436 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | 437 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} |
437 | * } | 438 | * } |
438 | * ) | 439 | * ) |
439 | * | 440 | * @Security("has_role('ROLE_READ')") |
440 | * @return JsonResponse | 441 | * @return JsonResponse |
441 | */ | 442 | */ |
442 | public function getEntriesTagsAction(Entry $entry) | 443 | public function getEntriesTagsAction(Entry $entry) |
@@ -458,7 +459,7 @@ class EntryRestController extends WallabagRestController | |||
458 | * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."}, | 459 | * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."}, |
459 | * } | 460 | * } |
460 | * ) | 461 | * ) |
461 | * | 462 | * @Security("has_role('ROLE_WRITE')") |
462 | * @return JsonResponse | 463 | * @return JsonResponse |
463 | */ | 464 | */ |
464 | public function postEntriesTagsAction(Request $request, Entry $entry) | 465 | public function postEntriesTagsAction(Request $request, Entry $entry) |
@@ -487,7 +488,7 @@ class EntryRestController extends WallabagRestController | |||
487 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | 488 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} |
488 | * } | 489 | * } |
489 | * ) | 490 | * ) |
490 | * | 491 | * @Security("has_role('ROLE_WRITE')") |
491 | * @return JsonResponse | 492 | * @return JsonResponse |
492 | */ | 493 | */ |
493 | public function deleteEntriesTagsAction(Entry $entry, Tag $tag) | 494 | public function deleteEntriesTagsAction(Entry $entry, Tag $tag) |
diff --git a/src/Wallabag/ApiBundle/Controller/TagRestController.php b/src/Wallabag/ApiBundle/Controller/TagRestController.php index 354187a0..6f460a2d 100644 --- a/src/Wallabag/ApiBundle/Controller/TagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/TagRestController.php | |||
@@ -3,6 +3,7 @@ | |||
3 | namespace Wallabag\ApiBundle\Controller; | 3 | namespace Wallabag\ApiBundle\Controller; |
4 | 4 | ||
5 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | 5 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; |
6 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; | ||
6 | use Symfony\Component\HttpFoundation\Request; | 7 | use Symfony\Component\HttpFoundation\Request; |
7 | use Symfony\Component\HttpFoundation\JsonResponse; | 8 | use Symfony\Component\HttpFoundation\JsonResponse; |
8 | use Wallabag\CoreBundle\Entity\Entry; | 9 | use Wallabag\CoreBundle\Entity\Entry; |
@@ -14,7 +15,7 @@ class TagRestController extends WallabagRestController | |||
14 | * Retrieve all tags. | 15 | * Retrieve all tags. |
15 | * | 16 | * |
16 | * @ApiDoc() | 17 | * @ApiDoc() |
17 | * | 18 | * @Security("has_role('ROLE_READ')") |
18 | * @return JsonResponse | 19 | * @return JsonResponse |
19 | */ | 20 | */ |
20 | public function getTagsAction() | 21 | public function getTagsAction() |
@@ -38,7 +39,7 @@ class TagRestController extends WallabagRestController | |||
38 | * {"name"="tag", "dataType"="string", "required"=true, "requirement"="\w+", "description"="Tag as a string"} | 39 | * {"name"="tag", "dataType"="string", "required"=true, "requirement"="\w+", "description"="Tag as a string"} |
39 | * } | 40 | * } |
40 | * ) | 41 | * ) |
41 | * | 42 | * @Security("has_role('ROLE_WRITE')") |
42 | * @return JsonResponse | 43 | * @return JsonResponse |
43 | */ | 44 | */ |
44 | public function deleteTagLabelAction(Request $request) | 45 | public function deleteTagLabelAction(Request $request) |
@@ -71,7 +72,7 @@ class TagRestController extends WallabagRestController | |||
71 | * {"name"="tags", "dataType"="string", "required"=true, "format"="tag1,tag2", "description"="Tags as strings (comma splitted)"} | 72 | * {"name"="tags", "dataType"="string", "required"=true, "format"="tag1,tag2", "description"="Tags as strings (comma splitted)"} |
72 | * } | 73 | * } |
73 | * ) | 74 | * ) |
74 | * | 75 | * @Security("has_role('ROLE_WRITE')") |
75 | * @return JsonResponse | 76 | * @return JsonResponse |
76 | */ | 77 | */ |
77 | public function deleteTagsLabelAction(Request $request) | 78 | public function deleteTagsLabelAction(Request $request) |
@@ -113,7 +114,7 @@ class TagRestController extends WallabagRestController | |||
113 | * {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag"} | 114 | * {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag"} |
114 | * } | 115 | * } |
115 | * ) | 116 | * ) |
116 | * | 117 | * @Security("has_role('ROLE_WRITE')") |
117 | * @return JsonResponse | 118 | * @return JsonResponse |
118 | */ | 119 | */ |
119 | public function deleteTagAction(Tag $tag) | 120 | public function deleteTagAction(Tag $tag) |
@@ -133,7 +134,7 @@ class TagRestController extends WallabagRestController | |||
133 | 134 | ||
134 | /** | 135 | /** |
135 | * Remove orphan tag in case no entries are associated to it. | 136 | * Remove orphan tag in case no entries are associated to it. |
136 | * | 137 | * @Security("has_role('ROLE_WRITE')") |
137 | * @param Tag|array $tags | 138 | * @param Tag|array $tags |
138 | */ | 139 | */ |
139 | private function cleanOrphanTag($tags) | 140 | private function cleanOrphanTag($tags) |
diff --git a/src/Wallabag/ApiBundle/Entity/AccessToken.php b/src/Wallabag/ApiBundle/Entity/AccessToken.php index c09a0c80..a8b46742 100644 --- a/src/Wallabag/ApiBundle/Entity/AccessToken.php +++ b/src/Wallabag/ApiBundle/Entity/AccessToken.php | |||
@@ -7,7 +7,7 @@ use FOS\OAuthServerBundle\Entity\AccessToken as BaseAccessToken; | |||
7 | 7 | ||
8 | /** | 8 | /** |
9 | * @ORM\Table("oauth2_access_tokens") | 9 | * @ORM\Table("oauth2_access_tokens") |
10 | * @ORM\Entity | 10 | * @ORM\Entity(repositoryClass="Wallabag\ApiBundle\Repository\AccessTokenRepository") |
11 | */ | 11 | */ |
12 | class AccessToken extends BaseAccessToken | 12 | class AccessToken extends BaseAccessToken |
13 | { | 13 | { |
diff --git a/src/Wallabag/ApiBundle/Entity/Client.php b/src/Wallabag/ApiBundle/Entity/Client.php index c15fd3fa..24444c9f 100644 --- a/src/Wallabag/ApiBundle/Entity/Client.php +++ b/src/Wallabag/ApiBundle/Entity/Client.php | |||
@@ -8,6 +8,7 @@ use Wallabag\UserBundle\Entity\User; | |||
8 | use JMS\Serializer\Annotation\Groups; | 8 | use JMS\Serializer\Annotation\Groups; |
9 | use JMS\Serializer\Annotation\SerializedName; | 9 | use JMS\Serializer\Annotation\SerializedName; |
10 | use JMS\Serializer\Annotation\VirtualProperty; | 10 | use JMS\Serializer\Annotation\VirtualProperty; |
11 | use Symfony\Component\Validator\Constraints as Assert; | ||
11 | 12 | ||
12 | /** | 13 | /** |
13 | * @ORM\Table("oauth2_clients") | 14 | * @ORM\Table("oauth2_clients") |
@@ -51,13 +52,39 @@ class Client extends BaseClient | |||
51 | 52 | ||
52 | /** | 53 | /** |
53 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="clients") | 54 | * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="clients") |
55 | * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true) | ||
54 | */ | 56 | */ |
55 | private $user; | 57 | private $user; |
56 | 58 | ||
57 | public function __construct(User $user) | 59 | /** |
60 | * @ORM\Column(type="string", nullable=true) | ||
61 | */ | ||
62 | private $image; | ||
63 | |||
64 | /** | ||
65 | * @ORM\Column(type="string", nullable=true) | ||
66 | */ | ||
67 | private $description; | ||
68 | |||
69 | /** | ||
70 | * @ORM\Column(type="string", nullable=true) | ||
71 | */ | ||
72 | private $appUrl; | ||
73 | |||
74 | /** | ||
75 | * @ORM\Column(type="datetime", nullable=true) | ||
76 | */ | ||
77 | private $createdAt; | ||
78 | |||
79 | /** | ||
80 | * Client constructor. | ||
81 | * @param User|null $user | ||
82 | */ | ||
83 | public function __construct(User $user = null) | ||
58 | { | 84 | { |
59 | parent::__construct(); | 85 | parent::__construct(); |
60 | $this->user = $user; | 86 | $this->user = $user; |
87 | $this->createdAt = new \DateTime(); | ||
61 | } | 88 | } |
62 | 89 | ||
63 | /** | 90 | /** |
@@ -99,6 +126,62 @@ class Client extends BaseClient | |||
99 | */ | 126 | */ |
100 | public function getClientId() | 127 | public function getClientId() |
101 | { | 128 | { |
102 | return $this->getId().'_'.$this->getRandomId(); | 129 | return $this->getId() . '_' . $this->getRandomId(); |
130 | } | ||
131 | |||
132 | /** | ||
133 | * @return string | ||
134 | */ | ||
135 | public function getImage() | ||
136 | { | ||
137 | return $this->image; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * @param string $image | ||
142 | */ | ||
143 | public function setImage($image) | ||
144 | { | ||
145 | $this->image = $image; | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * @return string | ||
150 | */ | ||
151 | public function getDescription() | ||
152 | { | ||
153 | return $this->description; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * @param string $description | ||
158 | */ | ||
159 | public function setDescription($description) | ||
160 | { | ||
161 | $this->description = $description; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * @return string | ||
166 | */ | ||
167 | public function getAppUrl() | ||
168 | { | ||
169 | return $this->appUrl; | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * @param string $appUrl | ||
174 | */ | ||
175 | public function setAppUrl($appUrl) | ||
176 | { | ||
177 | $this->appUrl = $appUrl; | ||
178 | } | ||
179 | |||
180 | /** | ||
181 | * @return \DateTime | ||
182 | */ | ||
183 | public function getCreatedAt() | ||
184 | { | ||
185 | return $this->createdAt; | ||
103 | } | 186 | } |
104 | } | 187 | } |
diff --git a/src/Wallabag/ApiBundle/Form/Type/ClientType.php b/src/Wallabag/ApiBundle/Form/Type/ClientType.php index eaea4feb..58602d22 100644 --- a/src/Wallabag/ApiBundle/Form/Type/ClientType.php +++ b/src/Wallabag/ApiBundle/Form/Type/ClientType.php | |||
@@ -15,24 +15,8 @@ class ClientType extends AbstractType | |||
15 | public function buildForm(FormBuilderInterface $builder, array $options) | 15 | public function buildForm(FormBuilderInterface $builder, array $options) |
16 | { | 16 | { |
17 | $builder | 17 | $builder |
18 | ->add('name', TextType::class, ['label' => 'developer.client.form.name_label']) | 18 | ->add('name', TextType::class, ['label' => 'apps.old_client.form.name_label']) |
19 | ->add('redirect_uris', UrlType::class, [ | 19 | ->add('save', SubmitType::class, ['label' => 'apps.old_client.form.save_label']) |
20 | 'required' => false, | ||
21 | 'label' => 'developer.client.form.redirect_uris_label', | ||
22 | 'property_path' => 'redirectUris', | ||
23 | ]) | ||
24 | ->add('save', SubmitType::class, ['label' => 'developer.client.form.save_label']) | ||
25 | ; | ||
26 | |||
27 | $builder->get('redirect_uris') | ||
28 | ->addModelTransformer(new CallbackTransformer( | ||
29 | function ($originalUri) { | ||
30 | return $originalUri; | ||
31 | }, | ||
32 | function ($submittedUri) { | ||
33 | return [$submittedUri]; | ||
34 | } | ||
35 | )) | ||
36 | ; | 20 | ; |
37 | } | 21 | } |
38 | 22 | ||
diff --git a/src/Wallabag/ApiBundle/Repository/AccessTokenRepository.php b/src/Wallabag/ApiBundle/Repository/AccessTokenRepository.php new file mode 100644 index 00000000..2b8d24df --- /dev/null +++ b/src/Wallabag/ApiBundle/Repository/AccessTokenRepository.php | |||
@@ -0,0 +1,18 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\ApiBundle\Repository; | ||
4 | |||
5 | use Doctrine\ORM\EntityRepository; | ||
6 | |||
7 | |||
8 | class AccessTokenRepository extends EntityRepository | ||
9 | { | ||
10 | public function findAppsByUser($userId) | ||
11 | { | ||
12 | $qb = $this->createQueryBuilder('a') | ||
13 | ->innerJoin('a.client', 'c') | ||
14 | ->addSelect('c') | ||
15 | ->where('a.user =:userId')->setParameter('userId', $userId); | ||
16 | return $qb->getQuery()->getResult(); | ||
17 | } | ||
18 | } | ||
diff --git a/src/Wallabag/ApiBundle/Resources/config/services.yml b/src/Wallabag/ApiBundle/Resources/config/services.yml new file mode 100644 index 00000000..1275107d --- /dev/null +++ b/src/Wallabag/ApiBundle/Resources/config/services.yml | |||
@@ -0,0 +1,6 @@ | |||
1 | services: | ||
2 | wallabag_api.accesstoken_repository: | ||
3 | class: Wallabag\ApiBundle\Repository\AccessTokenRepository | ||
4 | factory: [ "@doctrine.orm.default_entity_manager", getRepository ] | ||
5 | arguments: | ||
6 | - WallabagApiBundle:AccessToken | ||