mirror of
https://github.com/wallabag/wallabag.git
synced 2025-01-08 16:05:25 +00:00
Move API stuff in ApiBundle
This commit is contained in:
parent
e3c34bfc06
commit
769e19dc4a
25 changed files with 571 additions and 297 deletions
|
@ -23,7 +23,8 @@ class AppKernel extends Kernel
|
|||
new Nelmio\CorsBundle\NelmioCorsBundle(),
|
||||
new Liip\ThemeBundle\LiipThemeBundle(),
|
||||
new Wallabag\CoreBundle\WallabagCoreBundle(),
|
||||
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle()
|
||||
new Wallabag\ApiBundle\WallabagApiBundle(),
|
||||
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(),
|
||||
);
|
||||
|
||||
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
wallabag_api:
|
||||
resource: "@WallabagApiBundle/Resources/config/routing.yml"
|
||||
prefix: /
|
||||
|
||||
app:
|
||||
resource: @WallabagCoreBundle/Controller/
|
||||
type: annotation
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Rest_Wallabag:
|
||||
type : rest
|
||||
resource: "@WallabagCoreBundle/Resources/config/routing_rest.yml"
|
||||
resource: "@WallabagApiBundle/Resources/config/routing_rest.yml"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Controller;
|
||||
namespace Wallabag\ApiBundle\Controller;
|
||||
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
|
@ -62,6 +62,7 @@ class WallabagRestController extends Controller
|
|||
|
||||
return array($user->getSalt() ?: null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all entries. It could be filtered by many options.
|
||||
*
|
||||
|
@ -86,17 +87,13 @@ class WallabagRestController extends Controller
|
|||
$order = $request->query->get('order', 'desc');
|
||||
$page = (int) $request->query->get('page', 1);
|
||||
$perPage = (int) $request->query->get('perPage', 30);
|
||||
$tags = $request->query->get('tags', array());
|
||||
$tags = $request->query->get('tags', []);
|
||||
|
||||
$pager = $this
|
||||
->getDoctrine()
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order);
|
||||
|
||||
if (0 === $pager->getNbResults()) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$pager->setCurrentPage($page);
|
||||
$pager->setMaxPerPage($perPage);
|
||||
|
||||
|
@ -108,7 +105,7 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($paginatedCollection, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,13 +120,11 @@ class WallabagRestController extends Controller
|
|||
*/
|
||||
public function getEntryAction(Entry $entry)
|
||||
{
|
||||
if ($entry->getUser()->getId() != $this->getUser()->getId()) {
|
||||
throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId());
|
||||
}
|
||||
$this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId());
|
||||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,7 +160,7 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,9 +181,7 @@ class WallabagRestController extends Controller
|
|||
*/
|
||||
public function patchEntriesAction(Entry $entry, Request $request)
|
||||
{
|
||||
if ($entry->getUser()->getId() != $this->getUser()->getId()) {
|
||||
throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId());
|
||||
}
|
||||
$this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId());
|
||||
|
||||
$title = $request->request->get("title");
|
||||
$isArchived = $request->request->get("archive");
|
||||
|
@ -216,7 +209,7 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -231,9 +224,7 @@ class WallabagRestController extends Controller
|
|||
*/
|
||||
public function deleteEntriesAction(Entry $entry)
|
||||
{
|
||||
if ($entry->getUser()->getId() != $this->getUser()->getId()) {
|
||||
throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId());
|
||||
}
|
||||
$this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId());
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->remove($entry);
|
||||
|
@ -241,7 +232,7 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -255,13 +246,11 @@ class WallabagRestController extends Controller
|
|||
*/
|
||||
public function getEntriesTagsAction(Entry $entry)
|
||||
{
|
||||
if ($entry->getUser()->getId() != $this->getUser()->getId()) {
|
||||
throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId());
|
||||
}
|
||||
$this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId());
|
||||
|
||||
$json = $this->get('serializer')->serialize($entry->getTags(), 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -278,9 +267,7 @@ class WallabagRestController extends Controller
|
|||
*/
|
||||
public function postEntriesTagsAction(Request $request, Entry $entry)
|
||||
{
|
||||
if ($entry->getUser()->getId() != $this->getUser()->getId()) {
|
||||
throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId());
|
||||
}
|
||||
$this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId());
|
||||
|
||||
$tags = $request->request->get('tags', '');
|
||||
if (!empty($tags)) {
|
||||
|
@ -293,7 +280,7 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -301,16 +288,14 @@ class WallabagRestController extends Controller
|
|||
*
|
||||
* @ApiDoc(
|
||||
* requirements={
|
||||
* {"name"="tag", "dataType"="string", "requirement"="\w+", "description"="The tag"},
|
||||
* {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag ID"},
|
||||
* {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
public function deleteEntriesTagsAction(Entry $entry, Tag $tag)
|
||||
{
|
||||
if ($entry->getUser()->getId() != $this->getUser()->getId()) {
|
||||
throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId());
|
||||
}
|
||||
$this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId());
|
||||
|
||||
$entry->removeTag($tag);
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
@ -319,7 +304,7 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,7 +316,7 @@ class WallabagRestController extends Controller
|
|||
{
|
||||
$json = $this->get('serializer')->serialize($this->getUser()->getTags(), 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -339,15 +324,13 @@ class WallabagRestController extends Controller
|
|||
*
|
||||
* @ApiDoc(
|
||||
* requirements={
|
||||
* {"name"="tag", "dataType"="string", "requirement"="\w+", "description"="The tag"}
|
||||
* {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag"}
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
public function deleteTagAction(Tag $tag)
|
||||
{
|
||||
if ($tag->getUser()->getId() != $this->getUser()->getId()) {
|
||||
throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$tag->getUser()->getId().', logged user id: '.$this->getUser()->getId());
|
||||
}
|
||||
$this->validateUserAccess($tag->getUser()->getId(), $this->getUser()->getId());
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->remove($tag);
|
||||
|
@ -355,6 +338,33 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($tag, 'json');
|
||||
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the first id is equal to the second one.
|
||||
* If not, throw exception. It means a user try to access information from an other user
|
||||
*
|
||||
* @param integer $requestUserId User id from the requested source
|
||||
* @param integer $currentUserId User id from the retrieved source
|
||||
*/
|
||||
private function validateUserAccess($requestUserId, $currentUserId)
|
||||
{
|
||||
if ($requestUserId != $currentUserId) {
|
||||
throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$requestUserId.', logged user id: '.$currentUserId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a JSON Response.
|
||||
* We don't use the Symfony JsonRespone, because it takes an array as parameter instead of a JSON string
|
||||
*
|
||||
* @param string $json
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
private function renderJsonResponse($json)
|
||||
{
|
||||
return new Response($json, 200, array('application/json'));
|
||||
}
|
||||
}
|
29
src/Wallabag/ApiBundle/DependencyInjection/Configuration.php
Normal file
29
src/Wallabag/ApiBundle/DependencyInjection/Configuration.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\ApiBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* This is the class that validates and merges configuration from your app/config files
|
||||
*
|
||||
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
|
||||
*/
|
||||
class Configuration implements ConfigurationInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder();
|
||||
$rootNode = $treeBuilder->root('wallabag_api');
|
||||
|
||||
// Here you should define the parameters that are allowed to
|
||||
// configure your bundle. See the documentation linked above for
|
||||
// more information on that topic.
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\DependencyInjection\Security\Factory;
|
||||
namespace Wallabag\ApiBundle\DependencyInjection\Security\Factory;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\ApiBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\DependencyInjection\Loader;
|
||||
|
||||
class WallabagApiExtension extends Extension
|
||||
{
|
||||
public function load(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
$configuration = new Configuration();
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
$loader->load('services.yml');
|
||||
}
|
||||
|
||||
public function getAlias()
|
||||
{
|
||||
return 'wallabag_api';
|
||||
}
|
||||
}
|
0
src/Wallabag/ApiBundle/Resources/config/routing.yml
Normal file
0
src/Wallabag/ApiBundle/Resources/config/routing.yml
Normal file
4
src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
Normal file
4
src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
entries:
|
||||
type: rest
|
||||
resource: "WallabagApiBundle:WallabagRest"
|
||||
name_prefix: api_
|
12
src/Wallabag/ApiBundle/Resources/config/services.yml
Normal file
12
src/Wallabag/ApiBundle/Resources/config/services.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
services:
|
||||
wsse.security.authentication.provider:
|
||||
class: Wallabag\ApiBundle\Security\Authentication\Provider\WsseProvider
|
||||
public: false
|
||||
arguments: ['', '%kernel.cache_dir%/security/nonces']
|
||||
|
||||
wsse.security.authentication.listener:
|
||||
class: Wallabag\ApiBundle\Security\Firewall\WsseListener
|
||||
public: false
|
||||
tags:
|
||||
- { name: monolog.logger, channel: wsse }
|
||||
arguments: ['@security.context', '@security.authentication.manager', '@logger']
|
|
@ -1,12 +1,12 @@
|
|||
<?php
|
||||
namespace Wallabag\CoreBundle\Security\Authentication\Provider;
|
||||
namespace Wallabag\ApiBundle\Security\Authentication\Provider;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\NonceExpiredException;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Wallabag\CoreBundle\Security\Authentication\Token\WsseUserToken;
|
||||
use Wallabag\ApiBundle\Security\Authentication\Token\WsseUserToken;
|
||||
|
||||
class WsseProvider implements AuthenticationProviderInterface
|
||||
{
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
namespace Wallabag\CoreBundle\Security\Authentication\Token;
|
||||
namespace Wallabag\ApiBundle\Security\Authentication\Token;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Security\Firewall;
|
||||
namespace Wallabag\ApiBundle\Security\Firewall;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
|
@ -8,7 +8,7 @@ use Symfony\Component\Security\Http\Firewall\ListenerInterface;
|
|||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\SecurityContextInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Wallabag\CoreBundle\Security\Authentication\Token\WsseUserToken;
|
||||
use Wallabag\ApiBundle\Security\Authentication\Token\WsseUserToken;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class WsseListener implements ListenerInterface
|
|
@ -0,0 +1,410 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Tests\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
class WallabagRestControllerTest extends WebTestCase
|
||||
{
|
||||
protected static $salt;
|
||||
|
||||
/**
|
||||
* Grab the salt once and store it to be available for all tests
|
||||
*/
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
$client = self::createClient();
|
||||
|
||||
$user = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:User')
|
||||
->findOneByUsername('admin');
|
||||
|
||||
self::$salt = $user->getSalt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate HTTP headers for authenticate user on API
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function generateHeaders($username, $password)
|
||||
{
|
||||
$encryptedPassword = sha1($password.$username.self::$salt);
|
||||
$nonce = substr(md5(uniqid('nonce_', true)), 0, 16);
|
||||
|
||||
$now = new \DateTime('now', new \DateTimeZone('UTC'));
|
||||
$created = (string) $now->format('Y-m-d\TH:i:s\Z');
|
||||
$digest = base64_encode(sha1(base64_decode($nonce).$created.$encryptedPassword, true));
|
||||
|
||||
return array(
|
||||
'HTTP_AUTHORIZATION' => 'Authorization profile="UsernameToken"',
|
||||
'HTTP_x-wsse' => 'X-WSSE: UsernameToken Username="'.$username.'", PasswordDigest="'.$digest.'", Nonce="'.$nonce.'", Created="'.$created.'"',
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetSalt()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->request('GET', '/api/salts/admin.json');
|
||||
|
||||
$user = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:User')
|
||||
->findOneByUsername('admin');
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertArrayHasKey(0, $content);
|
||||
$this->assertEquals($user->getSalt(), $content[0]);
|
||||
|
||||
$client->request('GET', '/api/salts/notfound.json');
|
||||
$this->assertEquals(404, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function testWithBadHeaders()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneByIsArchived(false);
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$badHeaders = array(
|
||||
'HTTP_AUTHORIZATION' => 'Authorization profile="UsernameToken"',
|
||||
'HTTP_x-wsse' => 'X-WSSE: UsernameToken Username="admin", PasswordDigest="Wr0ngDig3st", Nonce="n0Nc3", Created="2015-01-01T13:37:00Z"',
|
||||
);
|
||||
|
||||
$client->request('GET', '/api/entries/'.$entry->getId().'.json', array(), array(), $badHeaders);
|
||||
$this->assertEquals(403, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGetOneEntry()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneBy(array('user' => 1, 'isArchived' => false));
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$client->request('GET', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertEquals($entry->getTitle(), $content['title']);
|
||||
$this->assertEquals($entry->getUrl(), $content['url']);
|
||||
$this->assertCount(count($entry->getTags()), $content['tags']);
|
||||
|
||||
$this->assertTrue(
|
||||
$client->getResponse()->headers->contains(
|
||||
'Content-Type',
|
||||
'application/json'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetOneEntryWrongUser()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneBy(array('user' => 2, 'isArchived' => false));
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$client->request('GET', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(403, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGetEntries()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$client->request('GET', '/api/entries', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertGreaterThanOrEqual(1, count($content));
|
||||
$this->assertNotEmpty($content['_embedded']['items']);
|
||||
$this->assertGreaterThanOrEqual(1, $content['total']);
|
||||
$this->assertEquals(1, $content['page']);
|
||||
$this->assertGreaterThanOrEqual(1, $content['pages']);
|
||||
|
||||
$this->assertTrue(
|
||||
$client->getResponse()->headers->contains(
|
||||
'Content-Type',
|
||||
'application/json'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetStarredEntries()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$client->request('GET', '/api/entries', array('archive' => 1), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertGreaterThanOrEqual(1, count($content));
|
||||
$this->assertEmpty($content['_embedded']['items']);
|
||||
$this->assertEquals(0, $content['total']);
|
||||
$this->assertEquals(1, $content['page']);
|
||||
$this->assertEquals(1, $content['pages']);
|
||||
|
||||
$this->assertTrue(
|
||||
$client->getResponse()->headers->contains(
|
||||
'Content-Type',
|
||||
'application/json'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testDeleteEntry()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneByUser(1);
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$client->request('DELETE', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertEquals($entry->getTitle(), $content['title']);
|
||||
$this->assertEquals($entry->getUrl(), $content['url']);
|
||||
|
||||
// We'll try to delete this entry again
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$client->request('DELETE', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(404, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function testPostEntry()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$client->request('POST', '/api/entries.json', array(
|
||||
'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html',
|
||||
'tags' => 'google',
|
||||
), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertGreaterThan(0, $content['id']);
|
||||
$this->assertEquals('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']);
|
||||
$this->assertEquals(false, $content['is_archived']);
|
||||
$this->assertEquals(false, $content['is_starred']);
|
||||
$this->assertCount(1, $content['tags']);
|
||||
}
|
||||
|
||||
public function testPatchEntry()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneByUser(1);
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
// hydrate the tags relations
|
||||
$nbTags = count($entry->getTags());
|
||||
|
||||
$client->request('PATCH', '/api/entries/'.$entry->getId().'.json', array(
|
||||
'title' => 'New awesome title',
|
||||
'tags' => 'new tag '.uniqid(),
|
||||
'star' => true,
|
||||
'archive' => false,
|
||||
), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertEquals($entry->getId(), $content['id']);
|
||||
$this->assertEquals($entry->getUrl(), $content['url']);
|
||||
$this->assertEquals('New awesome title', $content['title']);
|
||||
$this->assertGreaterThan($nbTags, count($content['tags']));
|
||||
}
|
||||
|
||||
public function testGetTagsEntry()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneWithTags(1);
|
||||
|
||||
$entry = $entry[0];
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$tags = array();
|
||||
foreach ($entry->getTags() as $tag) {
|
||||
$tags[] = array('id' => $tag->getId(), 'label' => $tag->getLabel());
|
||||
}
|
||||
|
||||
$client->request('GET', '/api/entries/'.$entry->getId().'/tags', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(json_encode($tags, JSON_HEX_QUOT), $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testPostTagsOnEntry()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneByUser(1);
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$nbTags = count($entry->getTags());
|
||||
|
||||
$newTags = 'tag1,tag2,tag3';
|
||||
|
||||
$client->request('POST', '/api/entries/'.$entry->getId().'/tags', array('tags' => $newTags), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertArrayHasKey('tags', $content);
|
||||
$this->assertEquals($nbTags+3, count($content['tags']));
|
||||
|
||||
$entryDB = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->find($entry->getId());
|
||||
|
||||
$tagsInDB = array();
|
||||
foreach ($entryDB->getTags()->toArray() as $tag) {
|
||||
$tagsInDB[$tag->getId()] = $tag->getLabel();
|
||||
}
|
||||
|
||||
foreach (explode(',', $newTags) as $tag) {
|
||||
$this->assertContains($tag, $tagsInDB);
|
||||
}
|
||||
}
|
||||
|
||||
public function testDeleteOneTagEntrie()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneByUser(1);
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
// hydrate the tags relations
|
||||
$nbTags = count($entry->getTags());
|
||||
$tag = $entry->getTags()[0];
|
||||
|
||||
$client->request('DELETE', '/api/entries/'.$entry->getId().'/tags/'.$tag->getId().'.json', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertArrayHasKey('tags', $content);
|
||||
$this->assertEquals($nbTags-1, count($content['tags']));
|
||||
}
|
||||
|
||||
public function testGetUserTags()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$client->request('GET', '/api/tags.json', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertGreaterThan(0, $content);
|
||||
$this->assertArrayHasKey('id', $content[0]);
|
||||
$this->assertArrayHasKey('label', $content[0]);
|
||||
|
||||
return end($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testGetUserTags
|
||||
*/
|
||||
public function testDeleteUserTag($tag)
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$headers = $this->generateHeaders('admin', 'mypassword');
|
||||
|
||||
$client->request('DELETE', '/api/tags/'.$tag['id'].'.json', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertArrayHasKey('label', $content);
|
||||
$this->assertEquals($tag['label'], $content['label']);
|
||||
}
|
||||
}
|
18
src/Wallabag/ApiBundle/WallabagApiBundle.php
Normal file
18
src/Wallabag/ApiBundle/WallabagApiBundle.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\ApiBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
use Wallabag\ApiBundle\DependencyInjection\Security\Factory\WsseFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
class WallabagApiBundle extends Bundle
|
||||
{
|
||||
public function build(ContainerBuilder $container)
|
||||
{
|
||||
parent::build($container);
|
||||
|
||||
$extension = $container->getExtension('security');
|
||||
$extension->addSecurityListenerFactory(new WsseFactory());
|
||||
}
|
||||
}
|
|
@ -3,15 +3,15 @@
|
|||
namespace Wallabag\CoreBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\DependencyInjection\Loader;
|
||||
|
||||
class WallabagCoreExtension extends Extension
|
||||
{
|
||||
public function load(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
$loader->load('services.yml');
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
entries:
|
||||
type: rest
|
||||
resource: "WallabagCoreBundle:WallabagRest"
|
||||
name_prefix: api_
|
|
@ -4,18 +4,6 @@ services:
|
|||
tags:
|
||||
- { name: twig.extension }
|
||||
|
||||
wsse.security.authentication.provider:
|
||||
class: Wallabag\CoreBundle\Security\Authentication\Provider\WsseProvider
|
||||
public: false
|
||||
arguments: ['', '%kernel.cache_dir%/security/nonces']
|
||||
|
||||
wsse.security.authentication.listener:
|
||||
class: Wallabag\CoreBundle\Security\Firewall\WsseListener
|
||||
public: false
|
||||
tags:
|
||||
- { name: monolog.logger, channel: wsse }
|
||||
arguments: ['@security.context', '@security.authentication.manager', '@logger']
|
||||
|
||||
wallabag_core.helper.detect_active_theme:
|
||||
class: Wallabag\CoreBundle\Helper\DetectActiveTheme
|
||||
arguments:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Wallabag\CoreBundle\Tests\Command;
|
||||
|
||||
use Wallabag\CoreBundle\Tests\WallabagTestCase;
|
||||
use Wallabag\CoreBundle\Tests\WallabagCoreTestCase;
|
||||
use Wallabag\CoreBundle\Command\InstallCommand;
|
||||
use Wallabag\CoreBundle\Tests\Mock\InstallCommandMock;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
|
@ -12,7 +12,7 @@ use Symfony\Component\Console\Output\NullOutput;
|
|||
use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand;
|
||||
use Doctrine\Bundle\DoctrineBundle\Command\CreateDatabaseDoctrineCommand;
|
||||
|
||||
class InstallCommandTest extends WallabagTestCase
|
||||
class InstallCommandTest extends WallabagCoreTestCase
|
||||
{
|
||||
public static function tearDownAfterClass()
|
||||
{
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
namespace Wallabag\CoreBundle\Tests\Controller;
|
||||
|
||||
use Wallabag\CoreBundle\Tests\WallabagTestCase;
|
||||
use Wallabag\CoreBundle\Tests\WallabagCoreTestCase;
|
||||
|
||||
class ConfigControllerTest extends WallabagTestCase
|
||||
class ConfigControllerTest extends WallabagCoreTestCase
|
||||
{
|
||||
public function testLogin()
|
||||
{
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
namespace Wallabag\CoreBundle\Tests\Controller;
|
||||
|
||||
use Wallabag\CoreBundle\Tests\WallabagTestCase;
|
||||
use Wallabag\CoreBundle\Tests\WallabagCoreTestCase;
|
||||
use Doctrine\ORM\AbstractQuery;
|
||||
|
||||
class EntryControllerTest extends WallabagTestCase
|
||||
class EntryControllerTest extends WallabagCoreTestCase
|
||||
{
|
||||
public function testLogin()
|
||||
{
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
namespace Wallabag\CoreBundle\Tests\Controller;
|
||||
|
||||
use Wallabag\CoreBundle\Tests\WallabagTestCase;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Wallabag\CoreBundle\Tests\WallabagCoreTestCase;
|
||||
|
||||
class SecurityControllerTest extends WallabagTestCase
|
||||
class SecurityControllerTest extends WallabagCoreTestCase
|
||||
{
|
||||
public function testLogin()
|
||||
{
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Tests\Controller;
|
||||
|
||||
use Wallabag\CoreBundle\Tests\WallabagTestCase;
|
||||
|
||||
class WallabagRestControllerTest extends WallabagTestCase
|
||||
{
|
||||
/**
|
||||
* Generate HTTP headers for authenticate user on API
|
||||
*
|
||||
* @param $username
|
||||
* @param $password
|
||||
* @param $salt
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function generateHeaders($username, $password, $salt)
|
||||
{
|
||||
$encryptedPassword = sha1($password.$username.$salt);
|
||||
$nonce = substr(md5(uniqid('nonce_', true)), 0, 16);
|
||||
|
||||
$now = new \DateTime('now', new \DateTimeZone('UTC'));
|
||||
$created = (string) $now->format('Y-m-d\TH:i:s\Z');
|
||||
$digest = base64_encode(sha1(base64_decode($nonce).$created.$encryptedPassword, true));
|
||||
|
||||
return array(
|
||||
'HTTP_AUTHORIZATION' => 'Authorization profile="UsernameToken"',
|
||||
'HTTP_x-wsse' => 'X-WSSE: UsernameToken Username="'.$username.'", PasswordDigest="'.$digest.'", Nonce="'.$nonce.'", Created="'.$created.'"',
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetSalt()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->request('GET', '/api/salts/admin.json');
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
$this->assertNotEmpty(json_decode($client->getResponse()->getContent()));
|
||||
|
||||
$client->request('GET', '/api/salts/notfound.json');
|
||||
$this->assertEquals(404, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function testWithBadHeaders()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneByIsArchived(false);
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$badHeaders = array(
|
||||
'HTTP_AUTHORIZATION' => 'Authorization profile="UsernameToken"',
|
||||
'HTTP_x-wsse' => 'X-WSSE: UsernameToken Username="admin", PasswordDigest="Wr0ngDig3st", Nonce="n0Nc3", Created="2015-01-01T13:37:00Z"',
|
||||
);
|
||||
|
||||
$client->request('GET', '/api/entries/'.$entry->getId().'.json', array(), array(), $badHeaders);
|
||||
$this->assertEquals(403, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGetOneEntry()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->request('GET', '/api/salts/admin.json');
|
||||
$salt = json_decode($client->getResponse()->getContent());
|
||||
|
||||
$headers = $this->generateHeaders('admin', 'mypassword', $salt[0]);
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneByIsArchived(false);
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$client->request('GET', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers);
|
||||
$this->assertContains($entry->getTitle(), $client->getResponse()->getContent());
|
||||
|
||||
$this->assertTrue(
|
||||
$client->getResponse()->headers->contains(
|
||||
'Content-Type',
|
||||
'application/json'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetEntries()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->request('GET', '/api/salts/admin.json');
|
||||
$salt = json_decode($client->getResponse()->getContent());
|
||||
|
||||
$headers = $this->generateHeaders('admin', 'mypassword', $salt[0]);
|
||||
|
||||
$client->request('GET', '/api/entries', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$this->assertGreaterThanOrEqual(1, count(json_decode($client->getResponse()->getContent())));
|
||||
|
||||
$this->assertContains('Google', $client->getResponse()->getContent());
|
||||
|
||||
$this->assertTrue(
|
||||
$client->getResponse()->headers->contains(
|
||||
'Content-Type',
|
||||
'application/json'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testDeleteEntry()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->request('GET', '/api/salts/admin.json');
|
||||
$salt = json_decode($client->getResponse()->getContent());
|
||||
|
||||
$headers = $this->generateHeaders('admin', 'mypassword', $salt[0]);
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneByUser(1);
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$client->request('DELETE', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
// We'll try to delete this entry again
|
||||
$client->request('GET', '/api/salts/admin.json');
|
||||
$salt = json_decode($client->getResponse()->getContent());
|
||||
|
||||
$headers = $this->generateHeaders('admin', 'mypassword', $salt[0]);
|
||||
|
||||
$client->request('DELETE', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(404, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGetTagsEntry()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->request('GET', '/api/salts/admin.json');
|
||||
$salt = json_decode($client->getResponse()->getContent());
|
||||
$headers = $this->generateHeaders('admin', 'mypassword', $salt[0]);
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneWithTags(1);
|
||||
|
||||
$entry = $entry[0];
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$tags = array();
|
||||
foreach ($entry->getTags() as $tag) {
|
||||
$tags[] = array('id' => $tag->getId(), 'label' => $tag->getLabel());
|
||||
}
|
||||
|
||||
$client->request('GET', '/api/entries/'.$entry->getId().'/tags', array(), array(), $headers);
|
||||
|
||||
$this->assertEquals(json_encode($tags, JSON_HEX_QUOT), $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testPostTagsOnEntry()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->request('GET', '/api/salts/admin.json');
|
||||
$salt = json_decode($client->getResponse()->getContent());
|
||||
$headers = $this->generateHeaders('admin', 'mypassword', $salt[0]);
|
||||
|
||||
$entry = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneByUser(1);
|
||||
|
||||
if (!$entry) {
|
||||
$this->markTestSkipped('No content found in db.');
|
||||
}
|
||||
|
||||
$newTags = 'tag1,tag2,tag3';
|
||||
|
||||
$client->request('POST', '/api/entries/'.$entry->getId().'/tags', array('tags' => $newTags), array(), $headers);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$entryDB = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->find($entry->getId());
|
||||
|
||||
$tagsInDB = array();
|
||||
foreach ($entryDB->getTags()->toArray() as $tag) {
|
||||
$tagsInDB[$tag->getId()] = $tag->getLabel();
|
||||
}
|
||||
|
||||
foreach (explode(',', $newTags) as $tag) {
|
||||
$this->assertContains($tag, $tagsInDB);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ namespace Wallabag\CoreBundle\Tests;
|
|||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
abstract class WallabagTestCase extends WebTestCase
|
||||
abstract class WallabagCoreTestCase extends WebTestCase
|
||||
{
|
||||
private $client = null;
|
||||
|
|
@ -3,16 +3,7 @@
|
|||
namespace Wallabag\CoreBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
use Wallabag\CoreBundle\DependencyInjection\Security\Factory\WsseFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
class WallabagCoreBundle extends Bundle
|
||||
{
|
||||
public function build(ContainerBuilder $container)
|
||||
{
|
||||
parent::build($container);
|
||||
|
||||
$extension = $container->getExtension('security');
|
||||
$extension->addSecurityListenerFactory(new WsseFactory());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue