aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag/ApiBundle
diff options
context:
space:
mode:
authorThomas Citharel <tcit@tcit.fr>2017-04-30 09:16:55 +0200
committerThomas Citharel <tcit@tcit.fr>2017-06-14 17:53:52 +0200
commit0f8268c93e6210d368f9dcd1900274871a9eacdf (patch)
tree251024ae114d2a14a67399ba28d02ddb6d031bad /src/Wallabag/ApiBundle
parentf93a3109a5f0999dbbd69131c9e5041c390120c9 (diff)
downloadwallabag-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')
-rw-r--r--src/Wallabag/ApiBundle/Controller/AnnotationRestController.php9
-rw-r--r--src/Wallabag/ApiBundle/Controller/AppsController.php189
-rw-r--r--src/Wallabag/ApiBundle/Controller/DeveloperController.php105
-rw-r--r--src/Wallabag/ApiBundle/Controller/EntryRestController.php23
-rw-r--r--src/Wallabag/ApiBundle/Controller/TagRestController.php11
-rw-r--r--src/Wallabag/ApiBundle/Entity/AccessToken.php2
-rw-r--r--src/Wallabag/ApiBundle/Entity/Client.php87
-rw-r--r--src/Wallabag/ApiBundle/Form/Type/ClientType.php20
-rw-r--r--src/Wallabag/ApiBundle/Repository/AccessTokenRepository.php18
-rw-r--r--src/Wallabag/ApiBundle/Resources/config/services.yml6
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
5use Nelmio\ApiDocBundle\Annotation\ApiDoc; 5use Nelmio\ApiDocBundle\Annotation\ApiDoc;
6use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; 6use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
7use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
7use Symfony\Component\HttpFoundation\Request; 8use Symfony\Component\HttpFoundation\Request;
8use Symfony\Component\HttpFoundation\JsonResponse; 9use Symfony\Component\HttpFoundation\JsonResponse;
9use Wallabag\CoreBundle\Entity\Entry; 10use 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
3namespace Wallabag\ApiBundle\Controller;
4
5use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
6use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
7use Symfony\Component\Finder\Exception\AccessDeniedException;
8use Symfony\Component\HttpFoundation\JsonResponse;
9use Symfony\Component\HttpFoundation\Request;
10use Symfony\Bundle\FrameworkBundle\Controller\Controller;
11use Wallabag\ApiBundle\Entity\AccessToken;
12use Wallabag\ApiBundle\Entity\Client;
13use Wallabag\ApiBundle\Form\Type\ClientType;
14
15class 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
3namespace Wallabag\ApiBundle\Controller;
4
5use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
6use Symfony\Component\HttpFoundation\Request;
7use Symfony\Bundle\FrameworkBundle\Controller\Controller;
8use Wallabag\ApiBundle\Entity\Client;
9use Wallabag\ApiBundle\Form\Type\ClientType;
10
11class 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;
5use Hateoas\Configuration\Route; 5use Hateoas\Configuration\Route;
6use Hateoas\Representation\Factory\PagerfantaFactory; 6use Hateoas\Representation\Factory\PagerfantaFactory;
7use Nelmio\ApiDocBundle\Annotation\ApiDoc; 7use Nelmio\ApiDocBundle\Annotation\ApiDoc;
8use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
8use Symfony\Component\HttpKernel\Exception\HttpException; 9use Symfony\Component\HttpKernel\Exception\HttpException;
9use Symfony\Component\HttpFoundation\Request; 10use Symfony\Component\HttpFoundation\Request;
10use Symfony\Component\HttpFoundation\JsonResponse; 11use 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 @@
3namespace Wallabag\ApiBundle\Controller; 3namespace Wallabag\ApiBundle\Controller;
4 4
5use Nelmio\ApiDocBundle\Annotation\ApiDoc; 5use Nelmio\ApiDocBundle\Annotation\ApiDoc;
6use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
6use Symfony\Component\HttpFoundation\Request; 7use Symfony\Component\HttpFoundation\Request;
7use Symfony\Component\HttpFoundation\JsonResponse; 8use Symfony\Component\HttpFoundation\JsonResponse;
8use Wallabag\CoreBundle\Entity\Entry; 9use 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 */
12class AccessToken extends BaseAccessToken 12class 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;
8use JMS\Serializer\Annotation\Groups; 8use JMS\Serializer\Annotation\Groups;
9use JMS\Serializer\Annotation\SerializedName; 9use JMS\Serializer\Annotation\SerializedName;
10use JMS\Serializer\Annotation\VirtualProperty; 10use JMS\Serializer\Annotation\VirtualProperty;
11use 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
3namespace Wallabag\ApiBundle\Repository;
4
5use Doctrine\ORM\EntityRepository;
6
7
8class 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 @@
1services:
2 wallabag_api.accesstoken_repository:
3 class: Wallabag\ApiBundle\Repository\AccessTokenRepository
4 factory: [ "@doctrine.orm.default_entity_manager", getRepository ]
5 arguments:
6 - WallabagApiBundle:AccessToken