diff options
author | Jeremy Benoist <j0k3r@users.noreply.github.com> | 2016-11-22 19:12:53 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-22 19:12:53 +0100 |
commit | 176e0ea3caee9f4eccc1ddda5f84b14da2cca034 (patch) | |
tree | 543ff69ee6b56c6383f3f9758221fc64154dee5c | |
parent | 1d5dd2c2410d7866752bca5d65886afc6a7650ef (diff) | |
parent | d51093a7d964ca720793d0cfcf4af601f2de448a (diff) | |
download | wallabag-176e0ea3caee9f4eccc1ddda5f84b14da2cca034.tar.gz wallabag-176e0ea3caee9f4eccc1ddda5f84b14da2cca034.tar.zst wallabag-176e0ea3caee9f4eccc1ddda5f84b14da2cca034.zip |
Merge pull request #2317 from wallabag/restricted-access
Added authentication for restricted access articles
28 files changed, 484 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/DoctrineMigrations/Version20161122144743.php b/app/DoctrineMigrations/Version20161122144743.php new file mode 100644 index 00000000..ec80c48e --- /dev/null +++ b/app/DoctrineMigrations/Version20161122144743.php | |||
@@ -0,0 +1,45 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Application\Migrations; | ||
4 | |||
5 | use Doctrine\DBAL\Migrations\AbstractMigration; | ||
6 | use Doctrine\DBAL\Schema\Schema; | ||
7 | use Symfony\Component\DependencyInjection\ContainerAwareInterface; | ||
8 | use Symfony\Component\DependencyInjection\ContainerInterface; | ||
9 | |||
10 | /** | ||
11 | * Add the restricted_access internal setting for articles with paywall | ||
12 | */ | ||
13 | class Version20161122144743 extends AbstractMigration implements ContainerAwareInterface | ||
14 | { | ||
15 | /** | ||
16 | * @var ContainerInterface | ||
17 | */ | ||
18 | private $container; | ||
19 | |||
20 | public function setContainer(ContainerInterface $container = null) | ||
21 | { | ||
22 | $this->container = $container; | ||
23 | } | ||
24 | |||
25 | private function getTable($tableName) | ||
26 | { | ||
27 | return $this->container->getParameter('database_table_prefix') . $tableName; | ||
28 | } | ||
29 | |||
30 | /** | ||
31 | * @param Schema $schema | ||
32 | */ | ||
33 | public function up(Schema $schema) | ||
34 | { | ||
35 | $this->addSql("INSERT INTO ".$this->getTable('craue_config_setting')." (name, value, section) VALUES ('restricted_access', 0, 'entry')"); | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * @param Schema $schema | ||
40 | */ | ||
41 | public function down(Schema $schema) | ||
42 | { | ||
43 | $this->addSql("DELETE FROM ".$this->getTable('craue_config_setting')." WHERE name = 'restricted_access';"); | ||
44 | } | ||
45 | } | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml index fac3b4f8..c65463db 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml | |||
@@ -32,3 +32,4 @@ demo_mode_enabled: "Aktiver demo-indstilling? (anvendes kun til wallabags offent | |||
32 | demo_mode_username: "Demobruger" | 32 | demo_mode_username: "Demobruger" |
33 | # share_public: Allow public url for entries | 33 | # share_public: Allow public url for entries |
34 | # download_images_enabled: Download images locally | 34 | # download_images_enabled: Download images locally |
35 | # restricted_access: Enable authentication for websites with paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml index d382733c..bc378147 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml | |||
@@ -32,3 +32,4 @@ demo_mode_enabled: "Test-Modus aktivieren? (nur für die öffentliche wallabag-D | |||
32 | demo_mode_username: "Test-Benutzer" | 32 | demo_mode_username: "Test-Benutzer" |
33 | share_public: Erlaube eine öffentliche URL für Einträge | 33 | share_public: Erlaube eine öffentliche URL für Einträge |
34 | # download_images_enabled: Download images locally | 34 | # download_images_enabled: Download images locally |
35 | # restricted_access: Enable authentication for websites with paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml index 23de7a43..52cb8e20 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml | |||
@@ -32,3 +32,4 @@ demo_mode_enabled: "Enable demo mode ? (only used for the wallabag public demo)" | |||
32 | demo_mode_username: "Demo user" | 32 | demo_mode_username: "Demo user" |
33 | share_public: Allow public url for entries | 33 | share_public: Allow public url for entries |
34 | download_images_enabled: Download images locally | 34 | download_images_enabled: Download images locally |
35 | restricted_access: Enable authentication for websites with paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml index ff1dd04f..dbec0e81 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml | |||
@@ -32,3 +32,4 @@ demo_mode_enabled: "Activar modo demo (sólo usado para la demo de wallabag)" | |||
32 | demo_mode_username: "Nombre de usuario demo" | 32 | demo_mode_username: "Nombre de usuario demo" |
33 | # share_public: Allow public url for entries | 33 | # share_public: Allow public url for entries |
34 | # download_images_enabled: Download images locally | 34 | # download_images_enabled: Download images locally |
35 | # restricted_access: Enable authentication for websites with paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml index 4e712fdd..7a341e0b 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml | |||
@@ -32,3 +32,4 @@ modify_settings: "اعمال" | |||
32 | # demo_mode_username: "Demo user" | 32 | # demo_mode_username: "Demo user" |
33 | # share_public: Allow public url for entries | 33 | # share_public: Allow public url for entries |
34 | # download_images_enabled: Download images locally | 34 | # download_images_enabled: Download images locally |
35 | # restricted_access: Enable authentication for websites with paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml index cae4c662..f5c886d6 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml | |||
@@ -32,3 +32,4 @@ demo_mode_enabled: "Activer le mode démo ? (utiliser uniquement pour la démo p | |||
32 | demo_mode_username: "Utilisateur de la démo" | 32 | demo_mode_username: "Utilisateur de la démo" |
33 | share_public: Autoriser une URL publique pour les articles | 33 | share_public: Autoriser une URL publique pour les articles |
34 | download_images_enabled: Télécharger les images en local | 34 | download_images_enabled: Télécharger les images en local |
35 | restricted_access: Activer l'authentification pour les articles derrière un paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml index f94f834f..88a1b4f6 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml | |||
@@ -32,3 +32,4 @@ demo_mode_enabled: "Abilita modalità demo ? (usato solo per la demo pubblica di | |||
32 | demo_mode_username: "Utente Demo" | 32 | demo_mode_username: "Utente Demo" |
33 | # share_public: Allow public url for entries | 33 | # share_public: Allow public url for entries |
34 | # download_images_enabled: Download images locally | 34 | # download_images_enabled: Download images locally |
35 | # restricted_access: Enable authentication for websites with paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml index de60a194..00deeade 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml | |||
@@ -32,3 +32,4 @@ demo_mode_enabled: "Activar lo mode demostracion ? (utilizar solament per la dem | |||
32 | demo_mode_username: "Utilizaire de la demostracion" | 32 | demo_mode_username: "Utilizaire de la demostracion" |
33 | # share_public: Allow public url for entries | 33 | # share_public: Allow public url for entries |
34 | # download_images_enabled: Download images locally | 34 | # download_images_enabled: Download images locally |
35 | # restricted_access: Enable authentication for websites with paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml index 11579745..744031e8 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml | |||
@@ -32,3 +32,4 @@ demo_mode_enabled: "Włacz tryb demo? (używany wyłącznie dla publicznej demon | |||
32 | demo_mode_username: "Użytkownik Demonstracyjny" | 32 | demo_mode_username: "Użytkownik Demonstracyjny" |
33 | share_public: Zezwalaj na publiczny adres url dla wpisow | 33 | share_public: Zezwalaj na publiczny adres url dla wpisow |
34 | # download_images_enabled: Download images locally | 34 | # download_images_enabled: Download images locally |
35 | # restricted_access: Enable authentication for websites with paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml index 74ae5a44..1edde87a 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml | |||
@@ -32,3 +32,4 @@ demo_mode_enabled: "Habilitar modo demo? (somente usado para o demo público do | |||
32 | demo_mode_username: "Usuário demo" | 32 | demo_mode_username: "Usuário demo" |
33 | # share_public: Allow public url for entries | 33 | # share_public: Allow public url for entries |
34 | # download_images_enabled: Download images locally | 34 | # download_images_enabled: Download images locally |
35 | # restricted_access: Enable authentication for websites with paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml index 5095dfa0..f0c935d3 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml | |||
@@ -32,3 +32,4 @@ modify_settings: "aplică" | |||
32 | # demo_mode_username: "Demo user" | 32 | # demo_mode_username: "Demo user" |
33 | # share_public: Allow public url for entries | 33 | # share_public: Allow public url for entries |
34 | # download_images_enabled: Download images locally | 34 | # download_images_enabled: Download images locally |
35 | # restricted_access: Enable authentication for websites with paywall | ||
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml index cd42e595..eb40fc5e 100644 --- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml +++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml | |||
@@ -32,3 +32,4 @@ | |||
32 | # demo_mode_username: "Demo user" | 32 | # demo_mode_username: "Demo user" |
33 | # share_public: Allow public url for entries | 33 | # share_public: Allow public url for entries |
34 | # download_images_enabled: Download images locally | 34 | # download_images_enabled: Download images locally |
35 | # restricted_access: Enable authentication for websites with paywall | ||
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/docs/de/developer/paywall.rst b/docs/de/developer/paywall.rst new file mode 100644 index 00000000..365027b4 --- /dev/null +++ b/docs/de/developer/paywall.rst | |||
@@ -0,0 +1,56 @@ | |||
1 | Articles behind a paywall | ||
2 | ========================= | ||
3 | |||
4 | wallabag can fetch articles from websites which use a paywall system. | ||
5 | |||
6 | Enable paywall authentication | ||
7 | ----------------------------- | ||
8 | |||
9 | In internal settings, in the **Article** section, enable authentication for websites with paywall (with the value 1). | ||
10 | |||
11 | Configure credentials in wallabag | ||
12 | --------------------------------- | ||
13 | |||
14 | Edit your ``app/config/parameters.yml`` file to edit credentials for each website with paywall. Here is an example for some french websites: | ||
15 | |||
16 | .. code:: yaml | ||
17 | |||
18 | sites_credentials: | ||
19 | mediapart.fr: {username: "myMediapartLogin", password: "mypassword"} | ||
20 | arretsurimages.net: {username: "myASILogin", password: "mypassword"} | ||
21 | |||
22 | .. note:: | ||
23 | |||
24 | These credentials will be shared between each user of your wallabag instance. | ||
25 | |||
26 | Parsing configuration files | ||
27 | --------------------------- | ||
28 | |||
29 | .. note:: | ||
30 | |||
31 | Read `this part of the documentation <http://doc.wallabag.org/en/master/user/errors_during_fetching.html>`_ to understand the configuration files. | ||
32 | |||
33 | Each parsing configuration file needs to be improved by adding ``requires_login``, ``login_uri``, | ||
34 | ``login_username_field``, ``login_password_field`` and ``not_logged_in_xpath``. | ||
35 | |||
36 | Be careful, the login form must be in the page content when wallabag loads it. It's impossible for wallabag to be authenticated | ||
37 | on a website where the login form is loaded after the page (by ajax for example). | ||
38 | |||
39 | ``login_uri`` is the action URL of the form (``action`` attribute in the form). | ||
40 | ``login_username_field`` is the ``name`` attribute of the login field. | ||
41 | ``login_password_field`` is the ``name`` attribute of the password field. | ||
42 | |||
43 | For example: | ||
44 | |||
45 | .. code:: | ||
46 | |||
47 | title://div[@id="titrage-contenu"]/h1[@class="title"] | ||
48 | body: //div[@class="contenu-html"]/div[@class="page-pane"] | ||
49 | |||
50 | requires_login: yes | ||
51 | |||
52 | login_uri: http://www.arretsurimages.net/forum/login.php | ||
53 | login_username_field: username | ||
54 | login_password_field: password | ||
55 | |||
56 | not_logged_in_xpath: //body[@class="not-logged-in"] | ||
diff --git a/docs/de/index.rst b/docs/de/index.rst index c1ce7d4b..1c3e4873 100644 --- a/docs/de/index.rst +++ b/docs/de/index.rst | |||
@@ -46,6 +46,7 @@ Die Dokumentation ist in anderen Sprachen verfügbar : | |||
46 | 46 | ||
47 | developer/api | 47 | developer/api |
48 | developer/docker | 48 | developer/docker |
49 | developer/paywall | ||
49 | developer/documentation | 50 | developer/documentation |
50 | developer/translate | 51 | developer/translate |
51 | developer/asynchronous | 52 | developer/asynchronous |
diff --git a/docs/en/developer/paywall.rst b/docs/en/developer/paywall.rst new file mode 100644 index 00000000..365027b4 --- /dev/null +++ b/docs/en/developer/paywall.rst | |||
@@ -0,0 +1,56 @@ | |||
1 | Articles behind a paywall | ||
2 | ========================= | ||
3 | |||
4 | wallabag can fetch articles from websites which use a paywall system. | ||
5 | |||
6 | Enable paywall authentication | ||
7 | ----------------------------- | ||
8 | |||
9 | In internal settings, in the **Article** section, enable authentication for websites with paywall (with the value 1). | ||
10 | |||
11 | Configure credentials in wallabag | ||
12 | --------------------------------- | ||
13 | |||
14 | Edit your ``app/config/parameters.yml`` file to edit credentials for each website with paywall. Here is an example for some french websites: | ||
15 | |||
16 | .. code:: yaml | ||
17 | |||
18 | sites_credentials: | ||
19 | mediapart.fr: {username: "myMediapartLogin", password: "mypassword"} | ||
20 | arretsurimages.net: {username: "myASILogin", password: "mypassword"} | ||
21 | |||
22 | .. note:: | ||
23 | |||
24 | These credentials will be shared between each user of your wallabag instance. | ||
25 | |||
26 | Parsing configuration files | ||
27 | --------------------------- | ||
28 | |||
29 | .. note:: | ||
30 | |||
31 | Read `this part of the documentation <http://doc.wallabag.org/en/master/user/errors_during_fetching.html>`_ to understand the configuration files. | ||
32 | |||
33 | Each parsing configuration file needs to be improved by adding ``requires_login``, ``login_uri``, | ||
34 | ``login_username_field``, ``login_password_field`` and ``not_logged_in_xpath``. | ||
35 | |||
36 | Be careful, the login form must be in the page content when wallabag loads it. It's impossible for wallabag to be authenticated | ||
37 | on a website where the login form is loaded after the page (by ajax for example). | ||
38 | |||
39 | ``login_uri`` is the action URL of the form (``action`` attribute in the form). | ||
40 | ``login_username_field`` is the ``name`` attribute of the login field. | ||
41 | ``login_password_field`` is the ``name`` attribute of the password field. | ||
42 | |||
43 | For example: | ||
44 | |||
45 | .. code:: | ||
46 | |||
47 | title://div[@id="titrage-contenu"]/h1[@class="title"] | ||
48 | body: //div[@class="contenu-html"]/div[@class="page-pane"] | ||
49 | |||
50 | requires_login: yes | ||
51 | |||
52 | login_uri: http://www.arretsurimages.net/forum/login.php | ||
53 | login_username_field: username | ||
54 | login_password_field: password | ||
55 | |||
56 | not_logged_in_xpath: //body[@class="not-logged-in"] | ||
diff --git a/docs/en/index.rst b/docs/en/index.rst index 54a1eef8..2e20aee6 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst | |||
@@ -46,6 +46,7 @@ The documentation is available in other languages: | |||
46 | 46 | ||
47 | developer/api | 47 | developer/api |
48 | developer/docker | 48 | developer/docker |
49 | developer/paywall | ||
49 | developer/documentation | 50 | developer/documentation |
50 | developer/translate | 51 | developer/translate |
51 | developer/asynchronous | 52 | developer/asynchronous |
diff --git a/docs/fr/developer/paywall.rst b/docs/fr/developer/paywall.rst new file mode 100644 index 00000000..c1c410b1 --- /dev/null +++ b/docs/fr/developer/paywall.rst | |||
@@ -0,0 +1,56 @@ | |||
1 | Articles derrière un paywall | ||
2 | ============================ | ||
3 | |||
4 | wallabag peut récupérer le contenu des articles des sites qui utilisent un système de paiement. | ||
5 | |||
6 | Activer l'authentification pour les paywall | ||
7 | ------------------------------------------- | ||
8 | |||
9 | Dans les paramètres internes, section **Article**, activez l'authentification pour les articles derrière un paywall (avec la valeur 1). | ||
10 | |||
11 | Configurer les accès dans wallabag | ||
12 | ---------------------------------- | ||
13 | |||
14 | Éditez le fichier ``app/config/parameters.yml`` pour modifier les accès aux sites avec paywall. Voici un exemple pour certains sites : | ||
15 | |||
16 | .. code:: yaml | ||
17 | |||
18 | sites_credentials: | ||
19 | mediapart.fr: {username: "myMediapartLogin", password: "mypassword"} | ||
20 | arretsurimages.net: {username: "myASILogin", password: "mypassword"} | ||
21 | |||
22 | .. note:: | ||
23 | |||
24 | Ces accès seront partagés entre chaque utilisateur de votre instance wallabag. | ||
25 | |||
26 | Fichiers de configuration pour parser les articles | ||
27 | -------------------------------------------------- | ||
28 | |||
29 | .. note:: | ||
30 | |||
31 | Lisez `cette documentation <http://doc.wallabag.org/fr/master/user/errors_during_fetching.html>`_ pour en savoir plus sur ces fichiers de configuration. | ||
32 | |||
33 | Chaque fichier de configuration doit être enrichi en ajoutant ``requires_login``, ``login_uri``, | ||
34 | ``login_username_field``, ``login_password_field`` et ``not_logged_in_xpath``. | ||
35 | |||
36 | Attention, le formulaire de connexion doit se trouver dans le contenu de la page lors du chargement de celle-ci. | ||
37 | Il sera impossible pour wallabag de se connecter à un site dont le formulaire de connexion est chargé après coup (en ajax par exemple). | ||
38 | |||
39 | ``login_uri`` correspond à l'URL à laquelle le formulaire est soumis (attribut ``action`` du formulaire). | ||
40 | ``login_username_field`` correspond à l'attribut ``name`` du champ de l'identifiant. | ||
41 | ``login_password_field`` correspond à l'attribut ``name`` du champ du mot de passe. | ||
42 | |||
43 | Par exemple : | ||
44 | |||
45 | .. code:: | ||
46 | |||
47 | title://div[@id="titrage-contenu"]/h1[@class="title"] | ||
48 | body: //div[@class="contenu-html"]/div[@class="page-pane"] | ||
49 | |||
50 | requires_login: yes | ||
51 | |||
52 | login_uri: http://www.arretsurimages.net/forum/login.php | ||
53 | login_username_field: username | ||
54 | login_password_field: password | ||
55 | |||
56 | not_logged_in_xpath: //body[@class="not-logged-in"] | ||
diff --git a/docs/fr/index.rst b/docs/fr/index.rst index 8a4c600a..e3f14b04 100644 --- a/docs/fr/index.rst +++ b/docs/fr/index.rst | |||
@@ -47,6 +47,7 @@ La documentation est disponible dans d'autres langues : | |||
47 | 47 | ||
48 | developer/api | 48 | developer/api |
49 | developer/docker | 49 | developer/docker |
50 | developer/paywall | ||
50 | developer/documentation | 51 | developer/documentation |
51 | developer/translate | 52 | developer/translate |
52 | developer/asynchronous | 53 | developer/asynchronous |
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php index e95c3a7b..f0738b91 100644 --- a/src/Wallabag/CoreBundle/Command/InstallCommand.php +++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php | |||
@@ -432,6 +432,11 @@ class InstallCommand extends ContainerAwareCommand | |||
432 | 'value' => '0', | 432 | 'value' => '0', |
433 | 'section' => 'misc', | 433 | 'section' => 'misc', |
434 | ], | 434 | ], |
435 | [ | ||
436 | 'name' => 'restricted_access', | ||
437 | 'value' => '0', | ||
438 | 'section' => 'entry', | ||
439 | ], | ||
435 | ]; | 440 | ]; |
436 | 441 | ||
437 | foreach ($settings as $setting) { | 442 | foreach ($settings as $setting) { |
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php index 1f74891a..a723656e 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php | |||
@@ -155,6 +155,11 @@ class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface | |||
155 | 'value' => '0', | 155 | 'value' => '0', |
156 | 'section' => 'misc', | 156 | 'section' => 'misc', |
157 | ], | 157 | ], |
158 | [ | ||
159 | 'name' => 'restricted_access', | ||
160 | 'value' => '0', | ||
161 | 'section' => 'entry', | ||
162 | ], | ||
158 | ]; | 163 | ]; |
159 | 164 | ||
160 | foreach ($settings as $setting) { | 165 | foreach ($settings as $setting) { |
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 | |||
3 | namespace Wallabag\CoreBundle\GuzzleSiteAuthenticator; | ||
4 | |||
5 | use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfig; | ||
6 | use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfigBuilder; | ||
7 | use Graby\SiteConfig\ConfigBuilder; | ||
8 | use OutOfRangeException; | ||
9 | |||
10 | class 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..8891887b --- /dev/null +++ b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php | |||
@@ -0,0 +1,54 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Helper; | ||
4 | |||
5 | use Graby\Ring\Client\SafeCurlHandler; | ||
6 | use GuzzleHttp\Client; | ||
7 | use GuzzleHttp\Cookie\CookieJar; | ||
8 | use GuzzleHttp\Event\SubscriberInterface; | ||
9 | |||
10 | /** | ||
11 | * Builds and configures the Guzzle HTTP client. | ||
12 | */ | ||
13 | class HttpClientFactory | ||
14 | { | ||
15 | /** @var \GuzzleHttp\Event\SubscriberInterface */ | ||
16 | private $authenticatorSubscriber; | ||
17 | |||
18 | /** @var \GuzzleHttp\Cookie\CookieJar */ | ||
19 | private $cookieJar; | ||
20 | |||
21 | private $restrictedAccess; | ||
22 | |||
23 | /** | ||
24 | * HttpClientFactory constructor. | ||
25 | * | ||
26 | * @param \GuzzleHttp\Event\SubscriberInterface $authenticatorSubscriber | ||
27 | * @param \GuzzleHttp\Cookie\CookieJar $cookieJar | ||
28 | * @param string $restrictedAccess this param is a kind of boolean. Values: 0 or 1 | ||
29 | */ | ||
30 | public function __construct(SubscriberInterface $authenticatorSubscriber, CookieJar $cookieJar, $restrictedAccess) | ||
31 | { | ||
32 | $this->authenticatorSubscriber = $authenticatorSubscriber; | ||
33 | $this->cookieJar = $cookieJar; | ||
34 | $this->restrictedAccess = $restrictedAccess; | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * @return \GuzzleHttp\Client|null | ||
39 | */ | ||
40 | public function buildHttpClient() | ||
41 | { | ||
42 | if (0 === (int) $this->restrictedAccess) { | ||
43 | return null; | ||
44 | } | ||
45 | |||
46 | // we clear the cookie to avoid websites who use cookies for analytics | ||
47 | $this->cookieJar->clear(); | ||
48 | // need to set the (shared) cookie jar | ||
49 | $client = new Client(['handler' => new SafeCurlHandler(), 'defaults' => ['cookies' => $this->cookieJar]]); | ||
50 | $client->getEmitter()->attach($this->authenticatorSubscriber); | ||
51 | |||
52 | return $client; | ||
53 | } | ||
54 | } | ||
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index 0280bc18..bcf0c9ca 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml | |||
@@ -41,11 +41,44 @@ 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 | - '@=service(''craue_config'').get(''restricted_access'')' | ||
77 | |||
78 | wallabag_core.guzzle.cookie_jar: | ||
79 | class: GuzzleHttp\Cookie\FileCookieJar | ||
80 | arguments: ["%kernel.cache_dir%/cookiejar.json"] | ||
81 | |||
49 | wallabag_core.content_proxy: | 82 | wallabag_core.content_proxy: |
50 | class: Wallabag\CoreBundle\Helper\ContentProxy | 83 | class: Wallabag\CoreBundle\Helper\ContentProxy |
51 | arguments: | 84 | 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 | |||
3 | namespace Tests\Wallabag\CoreBundle\GuzzleSiteAuthenticator; | ||
4 | |||
5 | use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfig; | ||
6 | use Graby\SiteConfig\SiteConfig as GrabySiteConfig; | ||
7 | use PHPUnit_Framework_TestCase; | ||
8 | use Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder; | ||
9 | |||
10 | class 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 | } | ||