mirror of
https://github.com/wallabag/wallabag.git
synced 2025-01-11 09:25:25 +00:00
Merge pull request #1167 from wallabag/v2-api-bundle
Move API stuff in ApiBundle
This commit is contained in:
commit
2878416f8b
56 changed files with 1141 additions and 788 deletions
18
.travis.yml
18
.travis.yml
|
@ -30,16 +30,16 @@ install:
|
|||
- composer self-update
|
||||
|
||||
# build coverage only on one build, to speed up results feedbacks
|
||||
before_script:
|
||||
- if [[ "$TRAVIS_PHP_VERSION" = "5.6" ]]; then PHPUNIT_FLAGS="--coverage-clover=coverage.clover"; else PHPUNIT_FLAGS=""; fi;
|
||||
# before_script:
|
||||
# - if [[ "$TRAVIS_PHP_VERSION" = "5.6" ]]; then PHPUNIT_FLAGS="--coverage-clover=coverage.clover"; else PHPUNIT_FLAGS=""; fi;
|
||||
|
||||
script:
|
||||
- ant prepare
|
||||
- phpunit --exclude-group command-doctrine $PHPUNIT_FLAGS
|
||||
- bin/phpunit --exclude-group command-doctrine --debug $PHPUNIT_FLAGS
|
||||
|
||||
after_script:
|
||||
- |
|
||||
if [ $TRAVIS_PHP_VERSION = '5.6' ]; then
|
||||
wget https://scrutinizer-ci.com/ocular.phar
|
||||
php ocular.phar code-coverage:upload --format=php-clover coverage.clover
|
||||
fi
|
||||
# after_script:
|
||||
# - |
|
||||
# if [ $TRAVIS_PHP_VERSION = '5.6' ]; then
|
||||
# wget https://scrutinizer-ci.com/ocular.phar
|
||||
# php ocular.phar code-coverage:upload --format=php-clover coverage.clover
|
||||
# fi
|
||||
|
|
|
@ -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'))) {
|
||||
|
|
|
@ -77,7 +77,7 @@ class Requirement
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the help text for resolving the problem
|
||||
* Returns the help text for resolving the problem.
|
||||
*
|
||||
* @return string The help text
|
||||
*/
|
||||
|
@ -119,10 +119,10 @@ class PhpIniRequirement extends Requirement
|
|||
*
|
||||
* @param string $cfgName The configuration name used for ini_get()
|
||||
* @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false,
|
||||
or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
|
||||
* or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
|
||||
* @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
|
||||
This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
|
||||
Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
|
||||
* This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
|
||||
* Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
|
||||
* @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived)
|
||||
* @param string|null $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived)
|
||||
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
|
||||
|
@ -221,10 +221,10 @@ class RequirementCollection implements IteratorAggregate
|
|||
*
|
||||
* @param string $cfgName The configuration name used for ini_get()
|
||||
* @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false,
|
||||
or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
|
||||
* or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
|
||||
* @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
|
||||
This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
|
||||
Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
|
||||
* This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
|
||||
* Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
|
||||
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived)
|
||||
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived)
|
||||
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
|
||||
|
@ -239,10 +239,10 @@ class RequirementCollection implements IteratorAggregate
|
|||
*
|
||||
* @param string $cfgName The configuration name used for ini_get()
|
||||
* @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false,
|
||||
or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
|
||||
* or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
|
||||
* @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
|
||||
This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
|
||||
Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
|
||||
* This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
|
||||
* Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
|
||||
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived)
|
||||
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived)
|
||||
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
|
||||
|
@ -542,11 +542,22 @@ class SymfonyRequirements extends RequirementCollection
|
|||
|
||||
/* optional recommendations follow */
|
||||
|
||||
$this->addRecommendation(
|
||||
file_get_contents(__FILE__) === file_get_contents(__DIR__.'/../vendor/sensio/distribution-bundle/Sensio/Bundle/DistributionBundle/Resources/skeleton/app/SymfonyRequirements.php'),
|
||||
'Requirements file should be up-to-date',
|
||||
'Your requirements file is outdated. Run composer install and re-check your configuration.'
|
||||
);
|
||||
if (file_exists(__DIR__.'/../vendor/composer')) {
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
try {
|
||||
$r = new \ReflectionClass('Sensio\Bundle\DistributionBundle\SensioDistributionBundle');
|
||||
|
||||
$contents = file_get_contents(dirname($r->getFileName()).'/Resources/skeleton/app/SymfonyRequirements.php');
|
||||
} catch (\ReflectionException $e) {
|
||||
$contents = '';
|
||||
}
|
||||
$this->addRecommendation(
|
||||
file_get_contents(__FILE__) === $contents,
|
||||
'Requirements file should be up-to-date',
|
||||
'Your requirements file is outdated. Run composer install and re-check your configuration.'
|
||||
);
|
||||
}
|
||||
|
||||
$this->addRecommendation(
|
||||
version_compare($installedPhpVersion, '5.3.4', '>='),
|
||||
|
|
|
@ -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"
|
||||
|
|
628
composer.lock
generated
628
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Controller;
|
||||
namespace Wallabag\ApiBundle\Controller;
|
||||
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
|
@ -47,6 +47,7 @@ class WallabagRestController extends Controller
|
|||
* {"name"="username", "dataType"="string", "required"=true, "description"="username"}
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSaltAction($username)
|
||||
|
@ -62,6 +63,7 @@ class WallabagRestController extends Controller
|
|||
|
||||
return array($user->getSalt() ?: null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all entries. It could be filtered by many options.
|
||||
*
|
||||
|
@ -76,6 +78,7 @@ class WallabagRestController extends Controller
|
|||
* {"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)
|
||||
|
@ -86,17 +89,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,32 +107,31 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($paginatedCollection, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a single entry
|
||||
* 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());
|
||||
}
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an entry
|
||||
* Create an entry.
|
||||
*
|
||||
* @ApiDoc(
|
||||
* parameters={
|
||||
|
@ -142,6 +140,7 @@ class WallabagRestController extends Controller
|
|||
* {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @return Entry
|
||||
*/
|
||||
public function postEntriesAction(Request $request)
|
||||
|
@ -165,11 +164,11 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change several properties of an entry
|
||||
* Change several properties of an entry.
|
||||
*
|
||||
* @ApiDoc(
|
||||
* requirements={
|
||||
|
@ -182,17 +181,16 @@ class WallabagRestController extends Controller
|
|||
* {"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());
|
||||
}
|
||||
$this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId());
|
||||
|
||||
$title = $request->request->get("title");
|
||||
$isArchived = $request->request->get("archive");
|
||||
$isStarred = $request->request->get("star");
|
||||
$title = $request->request->get('title');
|
||||
$isArchived = $request->request->get('archive');
|
||||
$isStarred = $request->request->get('star');
|
||||
|
||||
if (!is_null($title)) {
|
||||
$entry->setTitle($title);
|
||||
|
@ -216,24 +214,23 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete **permanently** an entry
|
||||
* 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());
|
||||
}
|
||||
$this->validateUserAccess($entry->getUser()->getId(), $this->getUser()->getId());
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->remove($entry);
|
||||
|
@ -241,11 +238,11 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all tags for an entry
|
||||
* Retrieve all tags for an entry.
|
||||
*
|
||||
* @ApiDoc(
|
||||
* requirements={
|
||||
|
@ -255,17 +252,15 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one or more tags to an entry
|
||||
* Add one or more tags to an entry.
|
||||
*
|
||||
* @ApiDoc(
|
||||
* requirements={
|
||||
|
@ -278,9 +273,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,24 +286,22 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permanently remove one tag for an entry
|
||||
* Permanently remove one tag for an entry.
|
||||
*
|
||||
* @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,11 +310,11 @@ class WallabagRestController extends Controller
|
|||
|
||||
$json = $this->get('serializer')->serialize($entry, 'json');
|
||||
|
||||
return new Response($json, 200, array('application/json'));
|
||||
return $this->renderJsonResponse($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all tags
|
||||
* Retrieve all tags.
|
||||
*
|
||||
* @ApiDoc()
|
||||
*/
|
||||
|
@ -331,23 +322,21 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permanently remove one tag from **every** entry
|
||||
* Permanently remove one tag from **every** entry.
|
||||
*
|
||||
* @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 +344,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 int $requestUserId User id from the requested source
|
||||
* @param int $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,13 @@
|
|||
<?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
|
||||
{
|
||||
|
@ -29,7 +30,7 @@ class WsseProvider implements AuthenticationProviderInterface
|
|||
$user = $this->userProvider->loadUserByUsername($token->getUsername());
|
||||
|
||||
if (!$user) {
|
||||
throw new AuthenticationException("Bad credentials. Did you forgot your username?");
|
||||
throw new AuthenticationException('Bad credentials. Did you forgot your username?');
|
||||
}
|
||||
|
||||
if ($user && $this->validateDigest($token->digest, $token->nonce, $token->created, $user->getPassword())) {
|
||||
|
@ -46,12 +47,12 @@ class WsseProvider implements AuthenticationProviderInterface
|
|||
{
|
||||
// Check created time is not in the future
|
||||
if (strtotime($created) > time()) {
|
||||
throw new AuthenticationException("Back to the future...");
|
||||
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.");
|
||||
throw new AuthenticationException('Too late for this timestamp... Watch your watch.');
|
||||
}
|
||||
|
||||
// Validate nonce is unique within 5 minutes
|
||||
|
@ -65,7 +66,7 @@ class WsseProvider implements AuthenticationProviderInterface
|
|||
$expected = base64_encode(sha1(base64_decode($nonce).$created.$secret, true));
|
||||
|
||||
if ($digest !== $expected) {
|
||||
throw new AuthenticationException("Bad credentials ! Digest is not as expected.");
|
||||
throw new AuthenticationException('Bad credentials ! Digest is not as expected.');
|
||||
}
|
||||
|
||||
return $digest === $expected;
|
|
@ -1,5 +1,6 @@
|
|||
<?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\ApiBundle\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->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 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());
|
||||
}
|
||||
}
|
|
@ -225,7 +225,7 @@ class InstallCommand extends ContainerAwareCommand
|
|||
}
|
||||
|
||||
/**
|
||||
* Run a command
|
||||
* Run a command.
|
||||
*
|
||||
* @param string $command
|
||||
* @param array $parameters Parameters to this command (usually 'force' => true)
|
||||
|
@ -266,9 +266,9 @@ class InstallCommand extends ContainerAwareCommand
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if the database already exists
|
||||
* Check if the database already exists.
|
||||
*
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
private function isDatabasePresent()
|
||||
{
|
||||
|
@ -300,9 +300,9 @@ class InstallCommand extends ContainerAwareCommand
|
|||
|
||||
/**
|
||||
* Check if the schema is already created.
|
||||
* If we found at least oen table, it means the schema exists
|
||||
* If we found at least oen table, it means the schema exists.
|
||||
*
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
private function isSchemaPresent()
|
||||
{
|
||||
|
|
|
@ -133,7 +133,7 @@ class ConfigController extends Controller
|
|||
'rss' => array(
|
||||
'username' => $user->getUsername(),
|
||||
'token' => $config->getRssToken(),
|
||||
)
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ class EntryController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Shows unread entries for current user
|
||||
* Shows unread entries for current user.
|
||||
*
|
||||
* @Route("/unread", name="unread")
|
||||
*
|
||||
|
@ -70,7 +70,7 @@ class EntryController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Shows read entries for current user
|
||||
* Shows read entries for current user.
|
||||
*
|
||||
* @Route("/archive", name="archive")
|
||||
*
|
||||
|
@ -90,7 +90,7 @@ class EntryController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Shows starred entries for current user
|
||||
* Shows starred entries for current user.
|
||||
*
|
||||
* @Route("/starred", name="starred")
|
||||
*
|
||||
|
@ -110,7 +110,7 @@ class EntryController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Shows entry content
|
||||
* Shows entry content.
|
||||
*
|
||||
* @param Entry $entry
|
||||
*
|
||||
|
@ -129,7 +129,7 @@ class EntryController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Changes read status for an entry
|
||||
* Changes read status for an entry.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Entry $entry
|
||||
|
@ -154,7 +154,7 @@ class EntryController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Changes favorite status for an entry
|
||||
* Changes favorite status for an entry.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Entry $entry
|
||||
|
@ -179,7 +179,7 @@ class EntryController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Deletes entry
|
||||
* Deletes entry.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Entry $entry
|
||||
|
@ -205,7 +205,7 @@ class EntryController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if the logged user can manage the given entry
|
||||
* Check if the logged user can manage the given entry.
|
||||
*
|
||||
* @param Entry $entry
|
||||
*/
|
||||
|
|
|
@ -11,7 +11,7 @@ use Wallabag\CoreBundle\Entity\Entry;
|
|||
class RssController extends Controller
|
||||
{
|
||||
/**
|
||||
* Shows unread entries for current user
|
||||
* Shows unread entries for current user.
|
||||
*
|
||||
* @Route("/{username}/{token}/unread.xml", name="unread_rss", defaults={"_format"="xml"})
|
||||
* @ParamConverter("user", class="WallabagCoreBundle:User", converter="username_rsstoken_converter")
|
||||
|
@ -35,7 +35,7 @@ class RssController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Shows read entries for current user
|
||||
* Shows read entries for current user.
|
||||
*
|
||||
* @Route("/{username}/{token}/archive.xml", name="archive_rss")
|
||||
* @ParamConverter("user", class="WallabagCoreBundle:User", converter="username_rsstoken_converter")
|
||||
|
@ -59,7 +59,7 @@ class RssController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Shows starred entries for current user
|
||||
* Shows starred entries for current user.
|
||||
*
|
||||
* @Route("/{username}/{token}/starred.xml", name="starred_rss")
|
||||
* @ParamConverter("user", class="WallabagCoreBundle:User", converter="username_rsstoken_converter")
|
||||
|
|
|
@ -30,9 +30,10 @@ class SecurityController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Request forgot password: show form
|
||||
* Request forgot password: show form.
|
||||
*
|
||||
* @Route("/forgot-password", name="forgot_password")
|
||||
*
|
||||
* @Method({"GET", "POST"})
|
||||
*/
|
||||
public function forgotPasswordAction(Request $request)
|
||||
|
@ -73,9 +74,10 @@ class SecurityController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Tell the user to check his email provider
|
||||
* Tell the user to check his email provider.
|
||||
*
|
||||
* @Route("/forgot-password/check-email", name="forgot_password_check_email")
|
||||
*
|
||||
* @Method({"GET"})
|
||||
*/
|
||||
public function checkEmailAction(Request $request)
|
||||
|
@ -93,9 +95,10 @@ class SecurityController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Reset user password
|
||||
* Reset user password.
|
||||
*
|
||||
* @Route("/forgot-password/{token}", name="forgot_password_reset")
|
||||
*
|
||||
* @Method({"GET", "POST"})
|
||||
*/
|
||||
public function resetAction(Request $request, $token)
|
||||
|
|
|
@ -39,9 +39,9 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface
|
|||
$entry3->setContent('This is my content /o/');
|
||||
|
||||
$tag1 = new Tag($this->getReference('bob-user'));
|
||||
$tag1->setLabel("foo");
|
||||
$tag1->setLabel('foo');
|
||||
$tag2 = new Tag($this->getReference('bob-user'));
|
||||
$tag2->setLabel("bar");
|
||||
$tag2->setLabel('bar');
|
||||
|
||||
$entry3->addTag($tag1);
|
||||
$entry3->addTag($tag2);
|
||||
|
@ -56,9 +56,9 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface
|
|||
$entry4->setContent('This is my content /o/');
|
||||
|
||||
$tag1 = new Tag($this->getReference('admin-user'));
|
||||
$tag1->setLabel("foo");
|
||||
$tag1->setLabel('foo');
|
||||
$tag2 = new Tag($this->getReference('admin-user'));
|
||||
$tag2->setLabel("bar");
|
||||
$tag2->setLabel('bar');
|
||||
|
||||
$entry4->addTag($tag1);
|
||||
$entry4->addTag($tag2);
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class PrefixedNamingStrategy implements NamingStrategy
|
|||
*/
|
||||
public function classToTableName($className)
|
||||
{
|
||||
return strtolower($this->prefix . substr($className, strrpos($className, '\\') + 1));
|
||||
return strtolower($this->prefix.substr($className, strrpos($className, '\\') + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,7 +49,7 @@ class PrefixedNamingStrategy implements NamingStrategy
|
|||
*/
|
||||
public function joinColumnName($propertyName)
|
||||
{
|
||||
return $propertyName . '_' . $this->referenceColumnName();
|
||||
return $propertyName.'_'.$this->referenceColumnName();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,7 +62,7 @@ class PrefixedNamingStrategy implements NamingStrategy
|
|||
// ie: not "wallabag_entry_wallabag_tag" but "wallabag_entry_tag"
|
||||
$target = substr($targetEntity, strrpos($targetEntity, '\\') + 1);
|
||||
|
||||
return strtolower($this->classToTableName($sourceEntity) . '_' .$target);
|
||||
return strtolower($this->classToTableName($sourceEntity).'_'.$target);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,6 +70,14 @@ class PrefixedNamingStrategy implements NamingStrategy
|
|||
*/
|
||||
public function joinKeyColumnName($entityName, $referencedColumnName = null)
|
||||
{
|
||||
return strtolower($this->classToTableName($entityName) . '_' .($referencedColumnName ?: $this->referenceColumnName()));
|
||||
return strtolower($this->classToTableName($entityName).'_'.($referencedColumnName ?: $this->referenceColumnName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null)
|
||||
{
|
||||
return $propertyName.'_'.$embeddedColumnName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* Config
|
||||
* Config.
|
||||
*
|
||||
* @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\ConfigRepository")
|
||||
* @ORM\Table
|
||||
|
@ -15,7 +15,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
class Config
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
|
@ -32,7 +32,7 @@ class Config
|
|||
private $theme;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
* @var int
|
||||
*
|
||||
* @Assert\NotBlank()
|
||||
* @Assert\Range(
|
||||
|
@ -60,7 +60,7 @@ class Config
|
|||
private $rssToken;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="rss_limit", type="integer", nullable=true)
|
||||
* @Assert\Range(
|
||||
|
@ -85,9 +85,9 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Get id
|
||||
* Get id.
|
||||
*
|
||||
* @return integer
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
|
@ -95,9 +95,10 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Set theme
|
||||
* Set theme.
|
||||
*
|
||||
* @param string $theme
|
||||
*
|
||||
* @param string $theme
|
||||
* @return Config
|
||||
*/
|
||||
public function setTheme($theme)
|
||||
|
@ -108,7 +109,7 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Get theme
|
||||
* Get theme.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -118,9 +119,10 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Set itemsPerPage
|
||||
* Set itemsPerPage.
|
||||
*
|
||||
* @param int $itemsPerPage
|
||||
*
|
||||
* @param integer $itemsPerPage
|
||||
* @return Config
|
||||
*/
|
||||
public function setItemsPerPage($itemsPerPage)
|
||||
|
@ -131,9 +133,9 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Get itemsPerPage
|
||||
* Get itemsPerPage.
|
||||
*
|
||||
* @return integer
|
||||
* @return int
|
||||
*/
|
||||
public function getItemsPerPage()
|
||||
{
|
||||
|
@ -141,9 +143,10 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Set language
|
||||
* Set language.
|
||||
*
|
||||
* @param string $language
|
||||
*
|
||||
* @param string $language
|
||||
* @return Config
|
||||
*/
|
||||
public function setLanguage($language)
|
||||
|
@ -154,7 +157,7 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Get language
|
||||
* Get language.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -164,9 +167,10 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Set user
|
||||
* Set user.
|
||||
*
|
||||
* @param \Wallabag\CoreBundle\Entity\User $user
|
||||
*
|
||||
* @param \Wallabag\CoreBundle\Entity\User $user
|
||||
* @return Config
|
||||
*/
|
||||
public function setUser(\Wallabag\CoreBundle\Entity\User $user = null)
|
||||
|
@ -177,7 +181,7 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Get user
|
||||
* Get user.
|
||||
*
|
||||
* @return \Wallabag\CoreBundle\Entity\User
|
||||
*/
|
||||
|
@ -187,9 +191,10 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Set rssToken
|
||||
* Set rssToken.
|
||||
*
|
||||
* @param string $rssToken
|
||||
*
|
||||
* @param string $rssToken
|
||||
* @return Config
|
||||
*/
|
||||
public function setRssToken($rssToken)
|
||||
|
@ -200,7 +205,7 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Get rssToken
|
||||
* Get rssToken.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -210,9 +215,10 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Set rssLimit
|
||||
* Set rssLimit.
|
||||
*
|
||||
* @param string $rssLimit
|
||||
*
|
||||
* @param string $rssLimit
|
||||
* @return Config
|
||||
*/
|
||||
public function setRssLimit($rssLimit)
|
||||
|
@ -223,7 +229,7 @@ class Config
|
|||
}
|
||||
|
||||
/**
|
||||
* Get rssLimit
|
||||
* Get rssLimit.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
|
|
@ -9,7 +9,7 @@ use Hateoas\Configuration\Annotation as Hateoas;
|
|||
use JMS\Serializer\Annotation\XmlRoot;
|
||||
|
||||
/**
|
||||
* Entry
|
||||
* Entry.
|
||||
*
|
||||
* @XmlRoot("entry")
|
||||
* @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\EntryRepository")
|
||||
|
@ -21,7 +21,7 @@ class Entry
|
|||
{
|
||||
/** @Serializer\XmlAttribute */
|
||||
/**
|
||||
* @var integer
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
|
@ -45,14 +45,14 @@ class Entry
|
|||
private $url;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* @var bool
|
||||
*
|
||||
* @ORM\Column(name="is_archived", type="boolean")
|
||||
*/
|
||||
private $isArchived = false;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* @var bool
|
||||
*
|
||||
* @ORM\Column(name="is_starred", type="boolean")
|
||||
*/
|
||||
|
@ -94,7 +94,7 @@ class Entry
|
|||
private $mimetype;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="reading_type", type="integer", nullable=true)
|
||||
*/
|
||||
|
@ -108,7 +108,7 @@ class Entry
|
|||
private $domainName;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* @var bool
|
||||
*
|
||||
* @ORM\Column(name="is_public", type="boolean", nullable=true, options={"default" = false})
|
||||
*/
|
||||
|
@ -135,9 +135,9 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Get id
|
||||
* Get id.
|
||||
*
|
||||
* @return integer
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
|
@ -145,9 +145,10 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Set title
|
||||
* Set title.
|
||||
*
|
||||
* @param string $title
|
||||
*
|
||||
* @param string $title
|
||||
* @return Entry
|
||||
*/
|
||||
public function setTitle($title)
|
||||
|
@ -158,7 +159,7 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Get title
|
||||
* Get title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -168,9 +169,10 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Set url
|
||||
* Set url.
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @param string $url
|
||||
* @return Entry
|
||||
*/
|
||||
public function setUrl($url)
|
||||
|
@ -181,7 +183,7 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Get url
|
||||
* Get url.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -191,9 +193,10 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Set isArchived
|
||||
* Set isArchived.
|
||||
*
|
||||
* @param string $isArchived
|
||||
*
|
||||
* @param string $isArchived
|
||||
* @return Entry
|
||||
*/
|
||||
public function setArchived($isArchived)
|
||||
|
@ -204,7 +207,7 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Get isArchived
|
||||
* Get isArchived.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -221,9 +224,10 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Set isStarred
|
||||
* Set isStarred.
|
||||
*
|
||||
* @param string $isStarred
|
||||
*
|
||||
* @param string $isStarred
|
||||
* @return Entry
|
||||
*/
|
||||
public function setStarred($isStarred)
|
||||
|
@ -234,7 +238,7 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Get isStarred
|
||||
* Get isStarred.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -251,9 +255,10 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Set content
|
||||
* Set content.
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
* @param string $content
|
||||
* @return Entry
|
||||
*/
|
||||
public function setContent($content)
|
||||
|
@ -264,7 +269,7 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* Get content
|
||||
* Get content.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -375,7 +380,7 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
public function isPublic()
|
||||
{
|
||||
|
@ -383,7 +388,7 @@ class Entry
|
|||
}
|
||||
|
||||
/**
|
||||
* @param boolean $isPublic
|
||||
* @param bool $isPublic
|
||||
*/
|
||||
public function setPublic($isPublic)
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ use JMS\Serializer\Annotation\Expose;
|
|||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
/**
|
||||
* Tag
|
||||
* Tag.
|
||||
*
|
||||
* @XmlRoot("tag")
|
||||
* @ORM\Table
|
||||
|
@ -19,7 +19,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
|||
class Tag
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
* @var int
|
||||
*
|
||||
* @Expose
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
|
@ -52,9 +52,9 @@ class Tag
|
|||
$this->entries = new ArrayCollection();
|
||||
}
|
||||
/**
|
||||
* Get id
|
||||
* Get id.
|
||||
*
|
||||
* @return integer
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
|
@ -62,9 +62,10 @@ class Tag
|
|||
}
|
||||
|
||||
/**
|
||||
* Set label
|
||||
* Set label.
|
||||
*
|
||||
* @param string $label
|
||||
*
|
||||
* @param string $label
|
||||
* @return Tag
|
||||
*/
|
||||
public function setLabel($label)
|
||||
|
@ -75,7 +76,7 @@ class Tag
|
|||
}
|
||||
|
||||
/**
|
||||
* Get label
|
||||
* Get label.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
|
|
@ -12,7 +12,7 @@ use JMS\Serializer\Annotation\ExclusionPolicy;
|
|||
use JMS\Serializer\Annotation\Expose;
|
||||
|
||||
/**
|
||||
* User
|
||||
* User.
|
||||
*
|
||||
* @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\UserRepository")
|
||||
* @ORM\Table
|
||||
|
@ -25,7 +25,7 @@ use JMS\Serializer\Annotation\Expose;
|
|||
class User implements AdvancedUserInterface, \Serializable
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
* @var int
|
||||
*
|
||||
* @Expose
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
|
@ -142,9 +142,9 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Get id
|
||||
* Get id.
|
||||
*
|
||||
* @return integer
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
|
@ -152,9 +152,10 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Set username
|
||||
* Set username.
|
||||
*
|
||||
* @param string $username
|
||||
*
|
||||
* @param string $username
|
||||
* @return User
|
||||
*/
|
||||
public function setUsername($username)
|
||||
|
@ -165,7 +166,7 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Get username
|
||||
* Get username.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -191,9 +192,10 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Set password
|
||||
* Set password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $password
|
||||
* @return User
|
||||
*/
|
||||
public function setPassword($password)
|
||||
|
@ -208,7 +210,7 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Get password
|
||||
* Get password.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -218,9 +220,10 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Set name
|
||||
* Set name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @param string $name
|
||||
* @return User
|
||||
*/
|
||||
public function setName($name)
|
||||
|
@ -231,7 +234,7 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Get name
|
||||
* Get name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -241,9 +244,10 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Set email
|
||||
* Set email.
|
||||
*
|
||||
* @param string $email
|
||||
*
|
||||
* @param string $email
|
||||
* @return User
|
||||
*/
|
||||
public function setEmail($email)
|
||||
|
@ -254,7 +258,7 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Get email
|
||||
* Get email.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -341,8 +345,7 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
public function unserialize($serialized)
|
||||
{
|
||||
list(
|
||||
$this->id,
|
||||
) = unserialize($serialized);
|
||||
$this->id) = unserialize($serialized);
|
||||
}
|
||||
|
||||
public function isEqualTo(UserInterface $user)
|
||||
|
@ -370,9 +373,10 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
return $this->isActive;
|
||||
}
|
||||
/**
|
||||
* Set config
|
||||
* Set config.
|
||||
*
|
||||
* @param \Wallabag\CoreBundle\Entity\Config $config
|
||||
*
|
||||
* @param \Wallabag\CoreBundle\Entity\Config $config
|
||||
* @return User
|
||||
*/
|
||||
public function setConfig(\Wallabag\CoreBundle\Entity\Config $config = null)
|
||||
|
@ -383,7 +387,7 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Get config
|
||||
* Get config.
|
||||
*
|
||||
* @return \Wallabag\CoreBundle\Entity\Config
|
||||
*/
|
||||
|
@ -393,9 +397,10 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Set confirmationToken
|
||||
* Set confirmationToken.
|
||||
*
|
||||
* @param string $confirmationToken
|
||||
*
|
||||
* @param string $confirmationToken
|
||||
* @return User
|
||||
*/
|
||||
public function setConfirmationToken($confirmationToken)
|
||||
|
@ -406,7 +411,7 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Get confirmationToken
|
||||
* Get confirmationToken.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -416,9 +421,10 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Set passwordRequestedAt
|
||||
* Set passwordRequestedAt.
|
||||
*
|
||||
* @param \DateTime $passwordRequestedAt
|
||||
*
|
||||
* @param \DateTime $passwordRequestedAt
|
||||
* @return User
|
||||
*/
|
||||
public function setPasswordRequestedAt($passwordRequestedAt)
|
||||
|
@ -429,7 +435,7 @@ class User implements AdvancedUserInterface, \Serializable
|
|||
}
|
||||
|
||||
/**
|
||||
* Get passwordRequestedAt
|
||||
* Get passwordRequestedAt.
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
|
|
|
@ -5,15 +5,16 @@ namespace Wallabag\CoreBundle\Helper;
|
|||
final class Tools
|
||||
{
|
||||
/**
|
||||
* Download a file (typically, for downloading pictures on web server)
|
||||
* Download a file (typically, for downloading pictures on web server).
|
||||
*
|
||||
* @param $url
|
||||
*
|
||||
* @return bool|mixed|string
|
||||
*/
|
||||
public static function getFile($url)
|
||||
{
|
||||
$timeout = 15;
|
||||
$useragent = "Mozilla/5.0 (Windows NT 5.1; rv:18.0) Gecko/20100101 Firefox/18.0";
|
||||
$useragent = 'Mozilla/5.0 (Windows NT 5.1; rv:18.0) Gecko/20100101 Firefox/18.0';
|
||||
|
||||
if (in_array('curl', get_loaded_extensions())) {
|
||||
# Fetch feed from URL
|
||||
|
@ -32,7 +33,7 @@ final class Tools
|
|||
|
||||
# FeedBurner requires a proper USER-AGENT...
|
||||
curl_setopt($curl, CURL_HTTP_VERSION_1_1, true);
|
||||
curl_setopt($curl, CURLOPT_ENCODING, "gzip, deflate");
|
||||
curl_setopt($curl, CURLOPT_ENCODING, 'gzip, deflate');
|
||||
curl_setopt($curl, CURLOPT_USERAGENT, $useragent);
|
||||
|
||||
$data = curl_exec($curl);
|
||||
|
@ -45,7 +46,7 @@ final class Tools
|
|||
array(
|
||||
'http' => array(
|
||||
'timeout' => $timeout,
|
||||
'header' => "User-Agent: ".$useragent,
|
||||
'header' => 'User-Agent: '.$useragent,
|
||||
'follow_location' => true,
|
||||
),
|
||||
'ssl' => array(
|
||||
|
@ -91,9 +92,10 @@ final class Tools
|
|||
}
|
||||
|
||||
/**
|
||||
* Encode a URL by using a salt
|
||||
* Encode a URL by using a salt.
|
||||
*
|
||||
* @param $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function encodeString($string)
|
||||
|
|
|
@ -10,7 +10,7 @@ use Pagerfanta\Pagerfanta;
|
|||
class EntryRepository extends EntityRepository
|
||||
{
|
||||
/**
|
||||
* Retrieves unread entries for a user
|
||||
* Retrieves unread entries for a user.
|
||||
*
|
||||
* @param int $userId
|
||||
* @param int $firstResult
|
||||
|
@ -35,7 +35,7 @@ class EntryRepository extends EntityRepository
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieves read entries for a user
|
||||
* Retrieves read entries for a user.
|
||||
*
|
||||
* @param int $userId
|
||||
* @param int $firstResult
|
||||
|
@ -61,7 +61,7 @@ class EntryRepository extends EntityRepository
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieves starred entries for a user
|
||||
* Retrieves starred entries for a user.
|
||||
*
|
||||
* @param int $userId
|
||||
* @param int $firstResult
|
||||
|
@ -87,7 +87,7 @@ class EntryRepository extends EntityRepository
|
|||
}
|
||||
|
||||
/**
|
||||
* Find Entries
|
||||
* Find Entries.
|
||||
*
|
||||
* @param int $userId
|
||||
* @param bool $isArchived
|
||||
|
|
|
@ -7,7 +7,7 @@ use Doctrine\ORM\EntityRepository;
|
|||
class UserRepository extends EntityRepository
|
||||
{
|
||||
/**
|
||||
* Find a user by its username and rss roken
|
||||
* Find a user by its username and rss roken.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $rssToken
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -7,8 +7,7 @@ use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
|||
|
||||
/**
|
||||
* This override just add en extra variable (username) to be able to salt the password
|
||||
* the way Wallabag v1 does. It will avoid to break compatibility with Wallabag v1
|
||||
*
|
||||
* the way Wallabag v1 does. It will avoid to break compatibility with Wallabag v1.
|
||||
*/
|
||||
class WallabagPasswordEncoder extends BasePasswordEncoder
|
||||
{
|
||||
|
|
|
@ -45,7 +45,7 @@ class WallabagAuthenticationProvider extends UserAuthenticationProvider
|
|||
throw new BadCredentialsException('The credentials were changed from another session.');
|
||||
}
|
||||
} else {
|
||||
if ("" === ($presentedPassword = $token->getCredentials())) {
|
||||
if ('' === ($presentedPassword = $token->getCredentials())) {
|
||||
throw new BadCredentialsException('The presented password cannot be empty.');
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ final class Extractor
|
|||
{
|
||||
public static function extract($url)
|
||||
{
|
||||
$pageContent = Extractor::getPageContent(new Url(base64_encode($url)));
|
||||
$pageContent = self::getPageContent(new Url(base64_encode($url)));
|
||||
$title = $pageContent['rss']['channel']['item']['title'] ?: 'Untitled';
|
||||
$body = $pageContent['rss']['channel']['item']['description'];
|
||||
|
||||
|
@ -21,9 +21,10 @@ final class Extractor
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the content for a given URL (by a call to FullTextFeed)
|
||||
* Get the content for a given URL (by a call to FullTextFeed).
|
||||
*
|
||||
* @param Url $url
|
||||
*
|
||||
* @param Url $url
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getPageContent(Url $url)
|
||||
|
@ -49,12 +50,12 @@ final class Extractor
|
|||
$scope = function () {
|
||||
extract(func_get_arg(1));
|
||||
$_GET = $_REQUEST = array(
|
||||
"url" => $url->getUrl(),
|
||||
"max" => 5,
|
||||
"links" => "preserve",
|
||||
"exc" => "",
|
||||
"format" => "json",
|
||||
"submit" => "Create Feed",
|
||||
'url' => $url->getUrl(),
|
||||
'max' => 5,
|
||||
'links' => 'preserve',
|
||||
'exc' => '',
|
||||
'format' => 'json',
|
||||
'submit' => 'Create Feed',
|
||||
);
|
||||
ob_start();
|
||||
require func_get_arg(0);
|
||||
|
@ -67,11 +68,11 @@ final class Extractor
|
|||
// Silence $scope function to avoid
|
||||
// issues with FTRSS when error_reporting is to high
|
||||
// FTRSS generates PHP warnings which break output
|
||||
$json = @$scope(__DIR__."/../../../../vendor/wallabag/Fivefilters_Libraries/makefulltextfeed.php", array("url" => $url));
|
||||
$json = @$scope(__DIR__.'/../../../../vendor/wallabag/Fivefilters_Libraries/makefulltextfeed.php', array('url' => $url));
|
||||
|
||||
// Clearing and restoring context
|
||||
foreach ($GLOBALS as $key => $value) {
|
||||
if ($key != "GLOBALS" && $key != "_SESSION") {
|
||||
if ($key != 'GLOBALS' && $key != '_SESSION') {
|
||||
unset($GLOBALS[$key]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
@ -397,7 +397,7 @@ class ConfigControllerTest extends WallabagTestCase
|
|||
);
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
$content = json_decode($client->getResponse()->getContent(), true);;
|
||||
$content = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertArrayHasKey('token', $content);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,9 +2,9 @@
|
|||
|
||||
namespace Wallabag\CoreBundle\Tests\Controller;
|
||||
|
||||
use Wallabag\CoreBundle\Tests\WallabagTestCase;
|
||||
use Wallabag\CoreBundle\Tests\WallabagCoreTestCase;
|
||||
|
||||
class RssControllerTest extends WallabagTestCase
|
||||
class RssControllerTest extends WallabagCoreTestCase
|
||||
{
|
||||
public function validateDom($xml, $nb = null)
|
||||
{
|
||||
|
@ -36,13 +36,13 @@ class RssControllerTest extends WallabagTestCase
|
|||
{
|
||||
return array(
|
||||
array(
|
||||
'/admin/YZIOAUZIAO/unread.xml'
|
||||
'/admin/YZIOAUZIAO/unread.xml',
|
||||
),
|
||||
array(
|
||||
'/wallace/YZIOAUZIAO/starred.xml'
|
||||
'/wallace/YZIOAUZIAO/starred.xml',
|
||||
),
|
||||
array(
|
||||
'/wallace/YZIOAUZIAO/archives.xml'
|
||||
'/wallace/YZIOAUZIAO/archives.xml',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
@ -5,7 +5,7 @@ namespace Wallabag\CoreBundle\Tools;
|
|||
class Utils
|
||||
{
|
||||
/**
|
||||
* Generate a token used for RSS
|
||||
* Generate a token used for RSS.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -22,6 +22,7 @@ class Utils
|
|||
$token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
|
||||
}
|
||||
|
||||
return str_replace('+', '', $token);
|
||||
// remove character which can broken the url
|
||||
return str_replace(array('+', '/'), '', $token);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,10 @@ class WallabagExtension extends \Twig_Extension
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the domain name for a URL
|
||||
* Returns the domain name for a URL.
|
||||
*
|
||||
* @param $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getDomainName($url)
|
||||
|
@ -24,9 +25,10 @@ class WallabagExtension extends \Twig_Extension
|
|||
}
|
||||
|
||||
/**
|
||||
* For a given text, we calculate reading time for an article
|
||||
* For a given text, we calculate reading time for an article.
|
||||
*
|
||||
* @param $text
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function getReadingTime($text)
|
||||
|
|
|
@ -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