aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBertrand Dunogier <bertrand.dunogier@gmail.com>2016-09-29 10:14:43 +0200
committerNicolas LÅ“uillet <nicolas@loeuillet.org>2016-11-22 14:01:46 +0100
commit7aab0ecf2f78ce58f28b53c1fa19bfd824cc3cd7 (patch)
treeb3e4f7875944f79e6f4fcf16fd5d1230a1467621
parentbb28368f6953e07dbe6747d7c1eacf1abe35817e (diff)
downloadwallabag-7aab0ecf2f78ce58f28b53c1fa19bfd824cc3cd7.tar.gz
wallabag-7aab0ecf2f78ce58f28b53c1fa19bfd824cc3cd7.tar.zst
wallabag-7aab0ecf2f78ce58f28b53c1fa19bfd824cc3cd7.zip
Added authentication for restricted access articles
Fix #438. Thank you so much @bdunogier
-rw-r--r--app/AppKernel.php1
-rw-r--r--app/config/parameters.yml.dist3
-rw-r--r--composer.json3
-rw-r--r--src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php68
-rw-r--r--src/Wallabag/CoreBundle/Helper/HttpClientFactory.php44
-rw-r--r--src/Wallabag/CoreBundle/Resources/config/services.yml32
-rw-r--r--tests/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilderTest.php85
7 files changed, 235 insertions, 1 deletions
diff --git a/app/AppKernel.php b/app/AppKernel.php
index 81b83ef9..c8382d5f 100644
--- a/app/AppKernel.php
+++ b/app/AppKernel.php
@@ -31,6 +31,7 @@ class AppKernel extends Kernel
31 new Craue\ConfigBundle\CraueConfigBundle(), 31 new Craue\ConfigBundle\CraueConfigBundle(),
32 new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(), 32 new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
33 new FOS\JsRoutingBundle\FOSJsRoutingBundle(), 33 new FOS\JsRoutingBundle\FOSJsRoutingBundle(),
34 new BD\GuzzleSiteAuthenticatorBundle\BDGuzzleSiteAuthenticatorBundle(),
34 35
35 // wallabag bundles 36 // wallabag bundles
36 new Wallabag\CoreBundle\WallabagCoreBundle(), 37 new Wallabag\CoreBundle\WallabagCoreBundle(),
diff --git a/app/config/parameters.yml.dist b/app/config/parameters.yml.dist
index f821f2a8..a4dc0bde 100644
--- a/app/config/parameters.yml.dist
+++ b/app/config/parameters.yml.dist
@@ -56,3 +56,6 @@ parameters:
56 redis_port: 6379 56 redis_port: 6379
57 redis_path: null 57 redis_path: null
58 redis_password: null 58 redis_password: null
59
60 # sites credentials
61 sites_credentials: {}
diff --git a/composer.json b/composer.json
index 1548d6ec..e2aeb424 100644
--- a/composer.json
+++ b/composer.json
@@ -83,7 +83,8 @@
83 "predis/predis": "^1.0", 83 "predis/predis": "^1.0",
84 "javibravo/simpleue": "^1.0", 84 "javibravo/simpleue": "^1.0",
85 "symfony/dom-crawler": "^3.1", 85 "symfony/dom-crawler": "^3.1",
86 "friendsofsymfony/jsrouting-bundle": "^1.6" 86 "friendsofsymfony/jsrouting-bundle": "^1.6",
87 "bdunogier/guzzle-site-authenticator": "^1.0@beta"
87 }, 88 },
88 "require-dev": { 89 "require-dev": {
89 "doctrine/doctrine-fixtures-bundle": "~2.2", 90 "doctrine/doctrine-fixtures-bundle": "~2.2",
diff --git a/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php b/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php
new file mode 100644
index 00000000..6d4129e8
--- /dev/null
+++ b/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php
@@ -0,0 +1,68 @@
1<?php
2
3namespace Wallabag\CoreBundle\GuzzleSiteAuthenticator;
4
5use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfig;
6use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfigBuilder;
7use Graby\SiteConfig\ConfigBuilder;
8use OutOfRangeException;
9
10class GrabySiteConfigBuilder implements SiteConfigBuilder
11{
12 /**
13 * @var \Graby\SiteConfig\ConfigBuilder
14 */
15 private $grabyConfigBuilder;
16 /**
17 * @var array
18 */
19 private $credentials;
20
21 /**
22 * GrabySiteConfigBuilder constructor.
23 *
24 * @param \Graby\SiteConfig\ConfigBuilder $grabyConfigBuilder
25 * @param array $credentials
26 */
27 public function __construct(ConfigBuilder $grabyConfigBuilder, array $credentials = [])
28 {
29 $this->grabyConfigBuilder = $grabyConfigBuilder;
30 $this->credentials = $credentials;
31 }
32
33 /**
34 * Builds the SiteConfig for a host.
35 *
36 * @param string $host The "www." prefix is ignored
37 *
38 * @return SiteConfig
39 *
40 * @throws OutOfRangeException If there is no config for $host
41 */
42 public function buildForHost($host)
43 {
44 // required by credentials below
45 $host = strtolower($host);
46 if (substr($host, 0, 4) == 'www.') {
47 $host = substr($host, 4);
48 }
49
50 $config = $this->grabyConfigBuilder->buildForHost($host);
51 $parameters = [
52 'host' => $host,
53 'requiresLogin' => $config->requires_login ?: false,
54 'loginUri' => $config->login_uri ?: null,
55 'usernameField' => $config->login_username_field ?: null,
56 'passwordField' => $config->login_password_field ?: null,
57 'extraFields' => is_array($config->login_extra_fields) ? $config->login_extra_fields : [],
58 'notLoggedInXpath' => $config->not_logged_in_xpath ?: null,
59 ];
60
61 if (isset($this->credentials[$host])) {
62 $parameters['username'] = $this->credentials[$host]['username'];
63 $parameters['password'] = $this->credentials[$host]['password'];
64 }
65
66 return new SiteConfig($parameters);
67 }
68}
diff --git a/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php
new file mode 100644
index 00000000..3e1d1ed5
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php
@@ -0,0 +1,44 @@
1<?php
2
3namespace Wallabag\CoreBundle\Helper;
4
5use Graby\Ring\Client\SafeCurlHandler;
6use GuzzleHttp\Client;
7use GuzzleHttp\Cookie\CookieJar;
8use GuzzleHttp\Event\SubscriberInterface;
9
10/**
11 * Builds and configures the Guzzle HTTP client.
12 */
13class HttpClientFactory
14{
15 /** @var \GuzzleHttp\Event\SubscriberInterface */
16 private $authenticatorSubscriber;
17
18 /** @var \GuzzleHttp\Cookie\CookieJar */
19 private $cookieJar;
20
21 /**
22 * HttpClientFactory constructor.
23 *
24 * @param \GuzzleHttp\Event\SubscriberInterface $authenticatorSubscriber
25 * @param \GuzzleHttp\Cookie\CookieJar $cookieJar
26 */
27 public function __construct(SubscriberInterface $authenticatorSubscriber, CookieJar $cookieJar)
28 {
29 $this->authenticatorSubscriber = $authenticatorSubscriber;
30 $this->cookieJar = $cookieJar;
31 }
32
33 /**
34 * @return \GuzzleHttp\Client
35 */
36 public function buildHttpClient()
37 {
38 // need to set the (shared) cookie jar
39 $client = new Client(['handler' => new SafeCurlHandler(), 'defaults' => ['cookies' => $this->cookieJar]]);
40 $client->getEmitter()->attach($this->authenticatorSubscriber);
41
42 return $client;
43 }
44}
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml
index 0280bc18..1b7f39fc 100644
--- a/src/Wallabag/CoreBundle/Resources/config/services.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/services.yml
@@ -41,11 +41,43 @@ services:
41 arguments: 41 arguments:
42 - 42 -
43 error_message: '%wallabag_core.fetching_error_message%' 43 error_message: '%wallabag_core.fetching_error_message%'
44 - "@wallabag_core.guzzle.http_client"
45 - "@wallabag_core.graby.config_builder"
44 calls: 46 calls:
45 - [ setLogger, [ "@logger" ] ] 47 - [ setLogger, [ "@logger" ] ]
46 tags: 48 tags:
47 - { name: monolog.logger, channel: graby } 49 - { name: monolog.logger, channel: graby }
48 50
51 wallabag_core.graby.config_builder:
52 class: Graby\SiteConfig\ConfigBuilder
53 arguments:
54 - {}
55 - "@logger"
56
57 wallabag_core.guzzle.http_client:
58 class: GuzzleHttp\ClientInterface
59 factory: ["@wallabag_core.guzzle.http_client_factory", buildHttpClient]
60
61 wallabag_core.guzzle_authenticator.config_builder:
62 class: Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder
63 arguments:
64 - "@wallabag_core.graby.config_builder"
65 - "%sites_credentials%"
66
67 # service alias override
68 bd_guzzle_site_authenticator.site_config_builder:
69 alias: wallabag_core.guzzle_authenticator.config_builder
70
71 wallabag_core.guzzle.http_client_factory:
72 class: Wallabag\CoreBundle\Helper\HttpClientFactory
73 arguments:
74 - "@bd_guzzle_site_authenticator.authenticator_subscriber"
75 - "@wallabag_core.guzzle.cookie_jar"
76
77 wallabag_core.guzzle.cookie_jar:
78 class: GuzzleHttp\Cookie\FileCookieJar
79 arguments: ["%kernel.cache_dir%/cookiejar.json"]
80
49 wallabag_core.content_proxy: 81 wallabag_core.content_proxy:
50 class: Wallabag\CoreBundle\Helper\ContentProxy 82 class: Wallabag\CoreBundle\Helper\ContentProxy
51 arguments: 83 arguments:
diff --git a/tests/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilderTest.php b/tests/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilderTest.php
new file mode 100644
index 00000000..aee67259
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilderTest.php
@@ -0,0 +1,85 @@
1<?php
2
3namespace Tests\Wallabag\CoreBundle\GuzzleSiteAuthenticator;
4
5use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfig;
6use Graby\SiteConfig\SiteConfig as GrabySiteConfig;
7use PHPUnit_Framework_TestCase;
8use Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder;
9
10class GrabySiteConfigBuilderTest extends PHPUnit_Framework_TestCase
11{
12 /** @var \Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder */
13 protected $builder;
14
15 public function testBuildConfigExists()
16 {
17 /* @var \Graby\SiteConfig\ConfigBuilder|\PHPUnit_Framework_MockObject_MockObject */
18 $grabyConfigBuilderMock = $this->getMockBuilder('\Graby\SiteConfig\ConfigBuilder')
19 ->disableOriginalConstructor()
20 ->getMock();
21
22 $grabySiteConfig = new GrabySiteConfig();
23 $grabySiteConfig->requires_login = true;
24 $grabySiteConfig->login_uri = 'http://example.com/login';
25 $grabySiteConfig->login_username_field = 'login';
26 $grabySiteConfig->login_password_field = 'password';
27 $grabySiteConfig->login_extra_fields = ['field' => 'value'];
28 $grabySiteConfig->not_logged_in_xpath = '//div[@class="need-login"]';
29
30 $grabyConfigBuilderMock
31 ->method('buildForHost')
32 ->with('example.com')
33 ->will($this->returnValue($grabySiteConfig));
34
35 $this->builder = new GrabySiteConfigBuilder(
36 $grabyConfigBuilderMock,
37 ['example.com' => ['username' => 'foo', 'password' => 'bar']]
38 );
39
40 $config = $this->builder->buildForHost('example.com');
41
42 self::assertEquals(
43 new SiteConfig([
44 'host' => 'example.com',
45 'requiresLogin' => true,
46 'loginUri' => 'http://example.com/login',
47 'usernameField' => 'login',
48 'passwordField' => 'password',
49 'extraFields' => ['field' => 'value'],
50 'notLoggedInXpath' => '//div[@class="need-login"]',
51 'username' => 'foo',
52 'password' => 'bar',
53 ]),
54 $config
55 );
56 }
57
58 public function testBuildConfigDoesntExist()
59 {
60 /* @var \Graby\SiteConfig\ConfigBuilder|\PHPUnit_Framework_MockObject_MockObject */
61 $grabyConfigBuilderMock = $this->getMockBuilder('\Graby\SiteConfig\ConfigBuilder')
62 ->disableOriginalConstructor()
63 ->getMock();
64
65 $grabyConfigBuilderMock
66 ->method('buildForHost')
67 ->with('unknown.com')
68 ->will($this->returnValue(new GrabySiteConfig()));
69
70 $this->builder = new GrabySiteConfigBuilder($grabyConfigBuilderMock, []);
71
72 $config = $this->builder->buildForHost('unknown.com');
73
74 self::assertEquals(
75 new SiteConfig([
76 'host' => 'unknown.com',
77 'requiresLogin' => false,
78 'username' => null,
79 'password' => null,
80 'extraFields' => [],
81 ]),
82 $config
83 );
84 }
85}