Move API stuff in ApiBundle

This commit is contained in:
Jeremy
2015-03-29 10:53:10 +02:00
parent e3c34bfc06
commit 769e19dc4a
25 changed files with 571 additions and 297 deletions

View File

@ -1,360 +0,0 @@
<?php
namespace Wallabag\CoreBundle\Controller;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Entity\Tag;
use Wallabag\CoreBundle\Service\Extractor;
use Hateoas\Configuration\Route;
use Hateoas\Representation\Factory\PagerfantaFactory;
class WallabagRestController extends Controller
{
/**
* @param Entry $entry
* @param string $tags
*/
private function assignTagsToEntry(Entry $entry, $tags)
{
foreach (explode(',', $tags) as $label) {
$label = trim($label);
$tagEntity = $this
->getDoctrine()
->getRepository('WallabagCoreBundle:Tag')
->findOneByLabel($label);
if (is_null($tagEntity)) {
$tagEntity = new Tag($this->getUser());
$tagEntity->setLabel($label);
}
// only add the tag on the entry if the relation doesn't exist
if (!$entry->getTags()->contains($tagEntity)) {
$entry->addTag($tagEntity);
}
}
}
/**
* Retrieve salt for a giver user.
*
* @ApiDoc(
* parameters={
* {"name"="username", "dataType"="string", "required"=true, "description"="username"}
* }
* )
* @return array
*/
public function getSaltAction($username)
{
$user = $this
->getDoctrine()
->getRepository('WallabagCoreBundle:User')
->findOneByUsername($username);
if (is_null($user)) {
throw $this->createNotFoundException();
}
return array($user->getSalt() ?: null);
}
/**
* Retrieve all entries. It could be filtered by many options.
*
* @ApiDoc(
* parameters={
* {"name"="archive", "dataType"="boolean", "required"=false, "format"="true or false, all entries by default", "description"="filter by archived status."},
* {"name"="star", "dataType"="boolean", "required"=false, "format"="true or false, all entries by default", "description"="filter by starred status."},
* {"name"="sort", "dataType"="string", "required"=false, "format"="'created' or 'updated', default 'created'", "description"="sort entries by date."},
* {"name"="order", "dataType"="string", "required"=false, "format"="'asc' or 'desc', default 'desc'", "description"="order of sort."},
* {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."},
* {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."},
* {"name"="tags", "dataType"="string", "required"=false, "format"="api%2Crest", "description"="a list of tags url encoded. Will returns entries that matches ALL tags."},
* }
* )
* @return Entry
*/
public function getEntriesAction(Request $request)
{
$isArchived = $request->query->get('archive');
$isStarred = $request->query->get('star');
$sort = $request->query->get('sort', 'created');
$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());
$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);
$pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
$paginatedCollection = $pagerfantaFactory->createRepresentation(
$pager,
new Route('api_get_entries', [], $absolute = true)
);
$json = $this->get('serializer')->serialize($paginatedCollection, 'json');
return new Response($json, 200, array('application/json'));
}
/**
* Retrieve a single entry
*
* @ApiDoc(
* requirements={
* {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
* }
* )
* @return Entry
*/
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());
}
$json = $this->get('serializer')->serialize($entry, 'json');
return new Response($json, 200, array('application/json'));
}
/**
* Create an entry
*
* @ApiDoc(
* parameters={
* {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."},
* {"name"="title", "dataType"="string", "required"=false, "description"="Optional, we'll get the title from the page."},
* {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
* }
* )
* @return Entry
*/
public function postEntriesAction(Request $request)
{
$url = $request->request->get('url');
$content = Extractor::extract($url);
$entry = new Entry($this->getUser());
$entry->setUrl($url);
$entry->setTitle($request->request->get('title') ?: $content->getTitle());
$entry->setContent($content->getBody());
$tags = $request->request->get('tags', '');
if (!empty($tags)) {
$this->assignTagsToEntry($entry, $tags);
}
$em = $this->getDoctrine()->getManager();
$em->persist($entry);
$em->flush();
$json = $this->get('serializer')->serialize($entry, 'json');
return new Response($json, 200, array('application/json'));
}
/**
* Change several properties of an entry
*
* @ApiDoc(
* requirements={
* {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
* },
* parameters={
* {"name"="title", "dataType"="string", "required"=false},
* {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
* {"name"="archive", "dataType"="boolean", "required"=false, "format"="true or false", "description"="archived the entry."},
* {"name"="star", "dataType"="boolean", "required"=false, "format"="true or false", "description"="starred the entry."},
* }
* )
* @return Entry
*/
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());
}
$title = $request->request->get("title");
$isArchived = $request->request->get("archive");
$isStarred = $request->request->get("star");
if (!is_null($title)) {
$entry->setTitle($title);
}
if (!is_null($isArchived)) {
$entry->setArchived($isArchived);
}
if (!is_null($isStarred)) {
$entry->setStarred($isStarred);
}
$tags = $request->request->get('tags', '');
if (!empty($tags)) {
$this->assignTagsToEntry($entry, $tags);
}
$em = $this->getDoctrine()->getManager();
$em->flush();
$json = $this->get('serializer')->serialize($entry, 'json');
return new Response($json, 200, array('application/json'));
}
/**
* Delete **permanently** an entry
*
* @ApiDoc(
* requirements={
* {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
* }
* )
* @return Entry
*/
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());
}
$em = $this->getDoctrine()->getManager();
$em->remove($entry);
$em->flush();
$json = $this->get('serializer')->serialize($entry, 'json');
return new Response($json, 200, array('application/json'));
}
/**
* Retrieve all tags for an entry
*
* @ApiDoc(
* requirements={
* {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
* }
* )
*/
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());
}
$json = $this->get('serializer')->serialize($entry->getTags(), 'json');
return new Response($json, 200, array('application/json'));
}
/**
* Add one or more tags to an entry
*
* @ApiDoc(
* requirements={
* {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
* },
* parameters={
* {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
* }
* )
*/
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());
}
$tags = $request->request->get('tags', '');
if (!empty($tags)) {
$this->assignTagsToEntry($entry, $tags);
}
$em = $this->getDoctrine()->getManager();
$em->persist($entry);
$em->flush();
$json = $this->get('serializer')->serialize($entry, 'json');
return new Response($json, 200, array('application/json'));
}
/**
* Permanently remove one tag for an entry
*
* @ApiDoc(
* requirements={
* {"name"="tag", "dataType"="string", "requirement"="\w+", "description"="The tag"},
* {"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());
}
$entry->removeTag($tag);
$em = $this->getDoctrine()->getManager();
$em->persist($entry);
$em->flush();
$json = $this->get('serializer')->serialize($entry, 'json');
return new Response($json, 200, array('application/json'));
}
/**
* Retrieve all tags
*
* @ApiDoc()
*/
public function getTagsAction()
{
$json = $this->get('serializer')->serialize($this->getUser()->getTags(), 'json');
return new Response($json, 200, array('application/json'));
}
/**
* Permanently remove one tag from **every** entry
*
* @ApiDoc(
* requirements={
* {"name"="tag", "dataType"="string", "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());
}
$em = $this->getDoctrine()->getManager();
$em->remove($tag);
$em->flush();
$json = $this->get('serializer')->serialize($tag, 'json');
return new Response($json, 200, array('application/json'));
}
}

View File

@ -1,40 +0,0 @@
<?php
namespace Wallabag\CoreBundle\DependencyInjection\Security\Factory;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface;
class WsseFactory implements SecurityFactoryInterface
{
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
{
$providerId = 'security.authentication.provider.wsse.'.$id;
$container
->setDefinition($providerId, new DefinitionDecorator('wsse.security.authentication.provider'))
->replaceArgument(0, new Reference($userProvider))
;
$listenerId = 'security.authentication.listener.wsse.'.$id;
$listener = $container->setDefinition($listenerId, new DefinitionDecorator('wsse.security.authentication.listener'));
return array($providerId, $listenerId, $defaultEntryPoint);
}
public function getPosition()
{
return 'pre_auth';
}
public function getKey()
{
return 'wsse';
}
public function addConfiguration(NodeDefinition $node)
{
}
}

View File

@ -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');
}

View File

@ -1,4 +0,0 @@
entries:
type: rest
resource: "WallabagCoreBundle:WallabagRest"
name_prefix: api_

View File

@ -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:

View File

@ -1,78 +0,0 @@
<?php
namespace Wallabag\CoreBundle\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;
class WsseProvider implements AuthenticationProviderInterface
{
private $userProvider;
private $cacheDir;
public function __construct(UserProviderInterface $userProvider, $cacheDir)
{
$this->userProvider = $userProvider;
$this->cacheDir = $cacheDir;
// If cache directory does not exist we create it
if (!is_dir($this->cacheDir)) {
mkdir($this->cacheDir, 0777, true);
}
}
public function authenticate(TokenInterface $token)
{
$user = $this->userProvider->loadUserByUsername($token->getUsername());
if (!$user) {
throw new AuthenticationException("Bad credentials. Did you forgot your username?");
}
if ($user && $this->validateDigest($token->digest, $token->nonce, $token->created, $user->getPassword())) {
$authenticatedToken = new WsseUserToken($user->getRoles());
$authenticatedToken->setUser($user);
return $authenticatedToken;
}
throw new AuthenticationException('The WSSE authentication failed.');
}
protected function validateDigest($digest, $nonce, $created, $secret)
{
// Check created time is not in the future
if (strtotime($created) > time()) {
throw new AuthenticationException("Back to the future...");
}
// Expire timestamp after 5 minutes
if (time() - strtotime($created) > 300) {
throw new AuthenticationException("Too late for this timestamp... Watch your watch.");
}
// Validate nonce is unique within 5 minutes
if (file_exists($this->cacheDir.'/'.$nonce) && file_get_contents($this->cacheDir.'/'.$nonce) + 300 > time()) {
throw new NonceExpiredException('Previously used nonce detected');
}
file_put_contents($this->cacheDir.'/'.$nonce, time());
// Validate Secret
$expected = base64_encode(sha1(base64_decode($nonce).$created.$secret, true));
if ($digest !== $expected) {
throw new AuthenticationException("Bad credentials ! Digest is not as expected.");
}
return $digest === $expected;
}
public function supports(TokenInterface $token)
{
return $token instanceof WsseUserToken;
}
}

View File

@ -1,23 +0,0 @@
<?php
namespace Wallabag\CoreBundle\Security\Authentication\Token;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
class WsseUserToken extends AbstractToken
{
public $created;
public $digest;
public $nonce;
public function __construct(array $roles = array())
{
parent::__construct($roles);
$this->setAuthenticated(count($roles) > 0);
}
public function getCredentials()
{
return '';
}
}

View File

@ -1,62 +0,0 @@
<?php
namespace Wallabag\CoreBundle\Security\Firewall;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
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 Psr\Log\LoggerInterface;
class WsseListener implements ListenerInterface
{
protected $securityContext;
protected $authenticationManager;
protected $logger;
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger)
{
$this->securityContext = $securityContext;
$this->authenticationManager = $authenticationManager;
$this->logger = $logger;
}
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
$wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"/';
if (!$request->headers->has('x-wsse') || 1 !== preg_match($wsseRegex, $request->headers->get('x-wsse'), $matches)) {
return;
}
$token = new WsseUserToken();
$token->setUser($matches[1]);
$token->digest = $matches[2];
$token->nonce = $matches[3];
$token->created = $matches[4];
try {
$authToken = $this->authenticationManager->authenticate($token);
$this->securityContext->setToken($authToken);
return;
} catch (AuthenticationException $failed) {
$failedMessage = 'WSSE Login failed for '.$token->getUsername().'. Why ? '.$failed->getMessage();
$this->logger->err($failedMessage);
// Deny authentication with a '403 Forbidden' HTTP response
$response = new Response();
$response->setStatusCode(403);
$response->setContent($failedMessage);
$event->setResponse($response);
return;
}
}
}

View File

@ -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()
{

View File

@ -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()
{

View File

@ -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()
{

View File

@ -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()
{

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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());
}
}