aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE.md2
-rw-r--r--app/DoctrineMigrations/Version20170602075214.php52
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml1
-rw-r--r--app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml1
-rw-r--r--app/config/config.yml37
-rw-r--r--app/config/security.yml1
-rw-r--r--app/config/wallabag.yml164
-rw-r--r--src/Wallabag/ApiBundle/Controller/EntryRestController.php150
-rw-r--r--src/Wallabag/ApiBundle/Controller/UserRestController.php23
-rw-r--r--src/Wallabag/CoreBundle/Command/InstallCommand.php160
-rw-r--r--src/Wallabag/CoreBundle/Command/ShowUserCommand.php77
-rw-r--r--src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php174
-rw-r--r--src/Wallabag/CoreBundle/DependencyInjection/Configuration.php11
-rw-r--r--src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php1
-rw-r--r--src/Wallabag/CoreBundle/Helper/ContentProxy.php2
-rw-r--r--src/Wallabag/CoreBundle/Helper/DownloadImages.php50
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.it.yml76
-rw-r--r--tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php11
-rw-r--r--tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php98
-rw-r--r--tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php10
-rw-r--r--tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php95
-rw-r--r--tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php25
-rw-r--r--tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpgbin0 -> 354067 bytes
33 files changed, 726 insertions, 505 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 38bf2df8..96854460 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,4 +1,4 @@
1:warning: If your issue is about an error during fetching a link, please read: http://doc.wallabag.org/en/master/user/errors_during_fetching.html#how-can-i-help-to-fix-that 1:warning: If your issue is about an error during fetching a link, please read: http://doc.wallabag.org/en/user/errors_during_fetching.html#how-can-i-help-to-fix-that
2 2
3### Issue details 3### Issue details
4 4
diff --git a/app/DoctrineMigrations/Version20170602075214.php b/app/DoctrineMigrations/Version20170602075214.php
new file mode 100644
index 00000000..451d16ba
--- /dev/null
+++ b/app/DoctrineMigrations/Version20170602075214.php
@@ -0,0 +1,52 @@
1<?php
2
3namespace Application\Migrations;
4
5use Doctrine\DBAL\Migrations\AbstractMigration;
6use Doctrine\DBAL\Schema\Schema;
7use Symfony\Component\DependencyInjection\ContainerAwareInterface;
8use Symfony\Component\DependencyInjection\ContainerInterface;
9
10/**
11 * Add api_user_registration in craue_config_setting.
12 */
13class Version20170602075214 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 $apiUserRegistration = $this->container
36 ->get('doctrine.orm.default_entity_manager')
37 ->getConnection()
38 ->fetchArray('SELECT * FROM '.$this->getTable('craue_config_setting')." WHERE name = 'api_user_registration'");
39
40 $this->skipIf(false !== $apiUserRegistration, 'It seems that you already played this migration.');
41
42 $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('api_user_registration', '0', 'api')");
43 }
44
45 /**
46 * @param Schema $schema
47 */
48 public function down(Schema $schema)
49 {
50 $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'api_user_registration';");
51 }
52}
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml
index d1f7e3b5..20e938f5 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml
@@ -34,3 +34,4 @@ demo_mode_username: "Demobruger"
34# share_public: Allow public url for entries 34# share_public: Allow public url for entries
35# download_images_enabled: Download images locally 35# download_images_enabled: Download images locally
36# restricted_access: Enable authentication for websites with paywall 36# restricted_access: Enable authentication for websites with paywall
37# api_user_registration: Enable user to be registered using the API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml
index 1105675b..526d41bc 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml
@@ -34,3 +34,4 @@ demo_mode_username: "Test-Benutzer"
34share_public: Erlaube eine öffentliche URL für Einträge 34share_public: Erlaube eine öffentliche URL für Einträge
35# download_images_enabled: Download images locally 35# download_images_enabled: Download images locally
36# restricted_access: Enable authentication for websites with paywall 36# restricted_access: Enable authentication for websites with paywall
37# api_user_registration: Enable user to be registered using the API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml
index 802599b3..3c0037f3 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml
@@ -34,3 +34,4 @@ demo_mode_username: "Demo user"
34share_public: Allow public url for entries 34share_public: Allow public url for entries
35download_images_enabled: Download images locally 35download_images_enabled: Download images locally
36restricted_access: Enable authentication for websites with paywall 36restricted_access: Enable authentication for websites with paywall
37api_user_registration: Enable user to be registered using the API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml
index b3ac18ed..99869669 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml
@@ -34,3 +34,4 @@ demo_mode_username: "Nombre de usuario demo"
34share_public: Permitir URL pública para los artículos 34share_public: Permitir URL pública para los artículos
35download_images_enabled: Descargar imágenes localmente 35download_images_enabled: Descargar imágenes localmente
36restricted_access: Activar autenticación para websites con paywall 36restricted_access: Activar autenticación para websites con paywall
37# api_user_registration: Enable user to be registered using the API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml
index c73d63e2..2e1307e5 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml
@@ -34,3 +34,4 @@ modify_settings: "اعمال"
34# share_public: Allow public url for entries 34# share_public: Allow public url for entries
35# download_images_enabled: Download images locally 35# download_images_enabled: Download images locally
36# restricted_access: Enable authentication for websites with paywall 36# restricted_access: Enable authentication for websites with paywall
37# api_user_registration: Enable user to be registered using the API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml
index a53174ae..454053ad 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml
@@ -34,3 +34,4 @@ demo_mode_username: "Utilisateur de la démo"
34share_public: Autoriser une URL publique pour les articles 34share_public: Autoriser une URL publique pour les articles
35download_images_enabled: Télécharger les images en local 35download_images_enabled: Télécharger les images en local
36restricted_access: Activer l'authentification pour les articles derrière un paywall 36restricted_access: Activer l'authentification pour les articles derrière un paywall
37api_user_registration: Activer la création de compte depuis l'API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml
index 3d53fc8d..4dbd2ff8 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml
@@ -34,3 +34,4 @@ demo_mode_username: "Utente Demo"
34# share_public: Allow public url for entries 34# share_public: Allow public url for entries
35# download_images_enabled: Download images locally 35# download_images_enabled: Download images locally
36# restricted_access: Enable authentication for websites with paywall 36# restricted_access: Enable authentication for websites with paywall
37api_user_registration: Abilita la registrazione dell'utente attraverso l'API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml
index 79f75245..00c06638 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml
@@ -34,3 +34,4 @@ demo_mode_username: "Utilizaire de la demostracion"
34share_public: Autorizar una URL publica pels articles 34share_public: Autorizar una URL publica pels articles
35download_images_enabled: Telecargar los imatges en local 35download_images_enabled: Telecargar los imatges en local
36restricted_access: Activar l'autenticacion pels sites amb peatge 36restricted_access: Activar l'autenticacion pels sites amb peatge
37# api_user_registration: Enable user to be registered using the API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml
index 02fe98e3..ada11b3a 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml
@@ -34,3 +34,4 @@ demo_mode_username: "Użytkownik Demonstracyjny"
34share_public: Zezwalaj na publiczny adres url dla wpisow 34share_public: Zezwalaj na publiczny adres url dla wpisow
35download_images_enabled: Pobierz obrazy lokalnie 35download_images_enabled: Pobierz obrazy lokalnie
36restricted_access: Włącz autoryzację dla stron z paywallem 36restricted_access: Włącz autoryzację dla stron z paywallem
37api_user_registration: Włącz rejestrację użytkownika przy użyciu API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml
index 4a061bce..59af9610 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml
@@ -34,3 +34,4 @@ demo_mode_username: "Usuário demo"
34# share_public: Allow public url for entries 34# share_public: Allow public url for entries
35# download_images_enabled: Download images locally 35# download_images_enabled: Download images locally
36# restricted_access: Enable authentication for websites with paywall 36# restricted_access: Enable authentication for websites with paywall
37# api_user_registration: Enable user to be registered using the API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml
index 5ee48074..104e37c6 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml
@@ -34,3 +34,4 @@ modify_settings: "aplică"
34# share_public: Allow public url for entries 34# share_public: Allow public url for entries
35# download_images_enabled: Download images locally 35# download_images_enabled: Download images locally
36# restricted_access: Enable authentication for websites with paywall 36# restricted_access: Enable authentication for websites with paywall
37# api_user_registration: Enable user to be registered using the API
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml
index d83a4b7b..1579366d 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml
@@ -34,3 +34,4 @@
34# share_public: Allow public url for entries 34# share_public: Allow public url for entries
35# download_images_enabled: Download images locally 35# download_images_enabled: Download images locally
36# restricted_access: Enable authentication for websites with paywall 36# restricted_access: Enable authentication for websites with paywall
37# api_user_registration: Enable user to be registered using the API
diff --git a/app/config/config.yml b/app/config/config.yml
index 04f8547d..2bc5e3b3 100644
--- a/app/config/config.yml
+++ b/app/config/config.yml
@@ -2,6 +2,7 @@ imports:
2 - { resource: parameters.yml } 2 - { resource: parameters.yml }
3 - { resource: security.yml } 3 - { resource: security.yml }
4 - { resource: services.yml } 4 - { resource: services.yml }
5 - { resource: wallabag.yml }
5 6
6parameters: 7parameters:
7 # Allows to use the live reload feature for changes in assets 8 # Allows to use the live reload feature for changes in assets
@@ -34,42 +35,6 @@ framework:
34 http_method_override: true 35 http_method_override: true
35 assets: ~ 36 assets: ~
36 37
37wallabag_core:
38 version: 2.2.3
39 paypal_url: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9UBA65LG3FX9Y&lc=gb"
40 languages:
41 en: 'English'
42 fr: 'Français'
43 de: 'Deutsch'
44 tr: 'Türkçe'
45 fa: 'فارسی'
46 ro: 'Română'
47 pl: 'Polish'
48 da: 'Dansk'
49 es: 'Español'
50 oc: 'Occitan'
51 it: 'Italiano'
52 pt: 'Português'
53 items_on_page: 12
54 theme: material
55 language: '%locale%'
56 rss_limit: 50
57 reading_speed: 1
58 cache_lifetime: 10
59 action_mark_as_read: 1
60 list_mode: 0
61 fetching_error_message_title: 'No title found'
62 fetching_error_message: |
63 wallabag can't retrieve contents for this article. Please <a href="http://doc.wallabag.org/en/user/errors_during_fetching.html#how-can-i-help-to-fix-that">troubleshoot this issue</a>.
64 api_limit_mass_actions: 10
65
66wallabag_user:
67 registration_enabled: "%fosuser_registration%"
68
69wallabag_import:
70 allow_mimetypes: ['application/octet-stream', 'application/json', 'text/plain', 'text/csv']
71 resource_dir: "%kernel.root_dir%/../web/uploads/import"
72
73# Twig Configuration 38# Twig Configuration
74twig: 39twig:
75 debug: "%kernel.debug%" 40 debug: "%kernel.debug%"
diff --git a/app/config/security.yml b/app/config/security.yml
index efb00a53..ffb1d356 100644
--- a/app/config/security.yml
+++ b/app/config/security.yml
@@ -56,6 +56,7 @@ security:
56 access_control: 56 access_control:
57 - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY } 57 - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY }
58 - { path: ^/api/version, roles: IS_AUTHENTICATED_ANONYMOUSLY } 58 - { path: ^/api/version, roles: IS_AUTHENTICATED_ANONYMOUSLY }
59 - { path: ^/api/user, roles: IS_AUTHENTICATED_ANONYMOUSLY }
59 - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } 60 - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
60 - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } 61 - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
61 - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } 62 - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
diff --git a/app/config/wallabag.yml b/app/config/wallabag.yml
new file mode 100644
index 00000000..d8c593c6
--- /dev/null
+++ b/app/config/wallabag.yml
@@ -0,0 +1,164 @@
1wallabag_core:
2 version: 2.2.3
3 paypal_url: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9UBA65LG3FX9Y&lc=gb"
4 languages:
5 en: 'English'
6 fr: 'Français'
7 de: 'Deutsch'
8 tr: 'Türkçe'
9 fa: 'فارسی'
10 ro: 'Română'
11 pl: 'Polish'
12 da: 'Dansk'
13 es: 'Español'
14 oc: 'Occitan'
15 it: 'Italiano'
16 pt: 'Português'
17 items_on_page: 12
18 theme: material
19 language: '%locale%'
20 rss_limit: 50
21 reading_speed: 1
22 cache_lifetime: 10
23 action_mark_as_read: 1
24 list_mode: 0
25 fetching_error_message_title: 'No title found'
26 fetching_error_message: |
27 wallabag can't retrieve contents for this article. Please <a href="http://doc.wallabag.org/en/user/errors_during_fetching.html#how-can-i-help-to-fix-that">troubleshoot this issue</a>.
28 api_limit_mass_actions: 10
29 default_internal_settings:
30 -
31 name: share_public
32 value: 1
33 section: entry
34 -
35 name: carrot
36 value: 1
37 section: entry
38 -
39 name: share_diaspora
40 value: 1
41 section: entry
42 -
43 name: diaspora_url
44 value: http://diasporapod.com
45 section: entry
46 -
47 name: share_unmark
48 value: 1
49 section: entry
50 -
51 name: unmark_url
52 value: https://unmark.it
53 section: entry
54 -
55 name: share_shaarli
56 value: 1
57 section: entry
58 -
59 name: share_scuttle
60 value: 1
61 section: entry
62 -
63 name: shaarli_url
64 value: http://myshaarli.com
65 section: entry
66 -
67 name: scuttle_url
68 value: http://scuttle.org
69 section: entry
70 -
71 name: share_mail
72 value: 1
73 section: entry
74 -
75 name: share_twitter
76 value: 1
77 section: entry
78 -
79 name: show_printlink
80 value: 1
81 section: entry
82 -
83 name: restricted_access
84 value: 0
85 section: entry
86 -
87 name: export_epub
88 value: 1
89 section: export
90 -
91 name: export_mobi
92 value: 1
93 section: export
94 -
95 name: export_pdf
96 value: 1
97 section: export
98 -
99 name: export_csv
100 value: 1
101 section: export
102 -
103 name: export_json
104 value: 1
105 section: export
106 -
107 name: export_txt
108 value: 1
109 section: export
110 -
111 name: export_xml
112 value: 1
113 section: export
114 -
115 name: import_with_redis
116 value: 0
117 section: import
118 -
119 name: import_with_rabbitmq
120 value: 0
121 section: import
122 -
123 name: piwik_enabled
124 value: 0
125 section: analytics
126 -
127 name: piwik_host
128 value: v2.wallabag.org
129 section: analytics
130 -
131 name: piwik_site_id
132 value: 1
133 section: analytics
134 -
135 name: demo_mode_enabled
136 value: 0
137 section: misc
138 -
139 name: demo_mode_username
140 value: wallabag
141 section: misc
142 -
143 name: download_images_enabled
144 value: 0
145 section: misc
146 -
147 name: wallabag_support_url
148 value: https://www.wallabag.org/pages/support.html
149 section: misc
150 -
151 name: wallabag_url
152 value: http://v2.wallabag.org
153 section: misc
154 -
155 name: api_user_registration
156 value: 0
157 section: api
158
159wallabag_user:
160 registration_enabled: "%fosuser_registration%"
161
162wallabag_import:
163 allow_mimetypes: ['application/octet-stream', 'application/json', 'text/plain', 'text/csv']
164 resource_dir: "%kernel.root_dir%/../web/uploads/import"
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
index 93c8157e..09b73ccb 100644
--- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
@@ -299,65 +299,18 @@ class EntryRestController extends WallabagRestController
299 $this->validateAuthentication(); 299 $this->validateAuthentication();
300 300
301 $url = $request->request->get('url'); 301 $url = $request->request->get('url');
302 $title = $request->request->get('title');
303 $tags = $request->request->get('tags', []);
304 $isArchived = $request->request->get('archive');
305 $isStarred = $request->request->get('starred');
306 $content = $request->request->get('content');
307 $language = $request->request->get('language');
308 $picture = $request->request->get('preview_picture');
309 $publishedAt = $request->request->get('published_at');
310 $authors = $request->request->get('authors', '');
311 302
312 $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId()); 303 $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId(
304 $url,
305 $this->getUser()->getId()
306 );
313 307
314 if (false === $entry) { 308 if (false === $entry) {
315 $entry = new Entry($this->getUser()); 309 $entry = new Entry($this->getUser());
316 }
317
318 try {
319 $this->get('wallabag_core.content_proxy')->updateEntry(
320 $entry,
321 $url,
322 [
323 'title' => $title,
324 'html' => $content,
325 'url' => $url,
326 'language' => $language,
327 'date' => $publishedAt,
328 // faking the preview picture
329 'open_graph' => [
330 'og_image' => $picture,
331 ],
332 'authors' => explode(',', $authors),
333 ]
334 );
335 } catch (\Exception $e) {
336 $this->get('logger')->error('Error while saving an entry', [
337 'exception' => $e,
338 'entry' => $entry,
339 ]);
340 $entry->setUrl($url); 310 $entry->setUrl($url);
341 } 311 }
342 312
343 if (!empty($tags)) { 313 $this->upsertEntry($entry, $request);
344 $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags);
345 }
346
347 if (!is_null($isStarred)) {
348 $entry->setStarred((bool) $isStarred);
349 }
350
351 if (!is_null($isArchived)) {
352 $entry->setArchived((bool) $isArchived);
353 }
354
355 $em = $this->getDoctrine()->getManager();
356 $em->persist($entry);
357 $em->flush();
358
359 // entry saved, dispatch event about it!
360 $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
361 314
362 return $this->sendResponse($entry); 315 return $this->sendResponse($entry);
363 } 316 }
@@ -374,6 +327,11 @@ class EntryRestController extends WallabagRestController
374 * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."}, 327 * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
375 * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="archived the entry."}, 328 * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="archived the entry."},
376 * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="starred the entry."}, 329 * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="starred the entry."},
330 * {"name"="content", "dataType"="string", "required"=false, "description"="Content of the entry"},
331 * {"name"="language", "dataType"="string", "required"=false, "description"="Language of the entry"},
332 * {"name"="preview_picture", "dataType"="string", "required"=false, "description"="Preview picture of the entry"},
333 * {"name"="published_at", "dataType"="datetime|integer", "format"="YYYY-MM-DDTHH:II:SS+TZ or a timestamp", "required"=false, "description"="Published date of the entry"},
334 * {"name"="authors", "dataType"="string", "format"="Name Firstname,author2,author3", "required"=false, "description"="Authors of the entry"},
377 * } 335 * }
378 * ) 336 * )
379 * 337 *
@@ -384,29 +342,7 @@ class EntryRestController extends WallabagRestController
384 $this->validateAuthentication(); 342 $this->validateAuthentication();
385 $this->validateUserAccess($entry->getUser()->getId()); 343 $this->validateUserAccess($entry->getUser()->getId());
386 344
387 $title = $request->request->get('title'); 345 $this->upsertEntry($entry, $request, true);
388 $isArchived = $request->request->get('archive');
389 $isStarred = $request->request->get('starred');
390
391 if (!is_null($title)) {
392 $entry->setTitle($title);
393 }
394
395 if (!is_null($isArchived)) {
396 $entry->setArchived((bool) $isArchived);
397 }
398
399 if (!is_null($isStarred)) {
400 $entry->setStarred((bool) $isStarred);
401 }
402
403 $tags = $request->request->get('tags', '');
404 if (!empty($tags)) {
405 $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags);
406 }
407
408 $em = $this->getDoctrine()->getManager();
409 $em->flush();
410 346
411 return $this->sendResponse($entry); 347 return $this->sendResponse($entry);
412 } 348 }
@@ -673,4 +609,68 @@ class EntryRestController extends WallabagRestController
673 609
674 return (new JsonResponse())->setJson($json); 610 return (new JsonResponse())->setJson($json);
675 } 611 }
612
613 /**
614 * Update or Insert a new entry.
615 *
616 * @param Entry $entry
617 * @param Request $request
618 * @param bool $disableContentUpdate If we don't want the content to be update by fetching the url (used when patching instead of posting)
619 */
620 private function upsertEntry(Entry $entry, Request $request, $disableContentUpdate = false)
621 {
622 $title = $request->request->get('title');
623 $tags = $request->request->get('tags', []);
624 $isArchived = $request->request->get('archive');
625 $isStarred = $request->request->get('starred');
626 $content = $request->request->get('content');
627 $language = $request->request->get('language');
628 $picture = $request->request->get('preview_picture');
629 $publishedAt = $request->request->get('published_at');
630 $authors = $request->request->get('authors', '');
631
632 try {
633 $this->get('wallabag_core.content_proxy')->updateEntry(
634 $entry,
635 $entry->getUrl(),
636 [
637 'title' => !empty($title) ? $title : $entry->getTitle(),
638 'html' => !empty($content) ? $content : $entry->getContent(),
639 'url' => $entry->getUrl(),
640 'language' => !empty($language) ? $language : $entry->getLanguage(),
641 'date' => !empty($publishedAt) ? $publishedAt : $entry->getPublishedAt(),
642 // faking the open graph preview picture
643 'open_graph' => [
644 'og_image' => !empty($picture) ? $picture : $entry->getPreviewPicture(),
645 ],
646 'authors' => is_string($authors) ? explode(',', $authors) : $entry->getPublishedBy(),
647 ],
648 $disableContentUpdate
649 );
650 } catch (\Exception $e) {
651 $this->get('logger')->error('Error while saving an entry', [
652 'exception' => $e,
653 'entry' => $entry,
654 ]);
655 }
656
657 if (!is_null($isArchived)) {
658 $entry->setArchived((bool) $isArchived);
659 }
660
661 if (!is_null($isStarred)) {
662 $entry->setStarred((bool) $isStarred);
663 }
664
665 if (!empty($tags)) {
666 $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags);
667 }
668
669 $em = $this->getDoctrine()->getManager();
670 $em->persist($entry);
671 $em->flush();
672
673 // entry saved, dispatch event about it!
674 $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
675 }
676} 676}
diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php
index a1b78e3f..8f675b8d 100644
--- a/src/Wallabag/ApiBundle/Controller/UserRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php
@@ -43,16 +43,18 @@ class UserRestController extends WallabagRestController
43 */ 43 */
44 public function putUserAction(Request $request) 44 public function putUserAction(Request $request)
45 { 45 {
46 if (!$this->container->getParameter('fosuser_registration')) { 46 if (!$this->getParameter('fosuser_registration') || !$this->get('craue_config')->get('api_user_registration')) {
47 $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); 47 $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json');
48 48
49 return (new JsonResponse())->setJson($json)->setStatusCode(403); 49 return (new JsonResponse())
50 ->setJson($json)
51 ->setStatusCode(JsonResponse::HTTP_FORBIDDEN);
50 } 52 }
51 53
52 $userManager = $this->get('fos_user.user_manager'); 54 $userManager = $this->get('fos_user.user_manager');
53 $user = $userManager->createUser(); 55 $user = $userManager->createUser();
54 // enable created user by default 56 // user will be disabled BY DEFAULT to avoid spamming account to be enabled
55 $user->setEnabled(true); 57 $user->setEnabled(false);
56 58
57 $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [ 59 $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [
58 'csrf_protection' => false, 60 'csrf_protection' => false,
@@ -90,7 +92,9 @@ class UserRestController extends WallabagRestController
90 92
91 $json = $this->get('serializer')->serialize(['error' => $errors], 'json'); 93 $json = $this->get('serializer')->serialize(['error' => $errors], 'json');
92 94
93 return (new JsonResponse())->setJson($json)->setStatusCode(400); 95 return (new JsonResponse())
96 ->setJson($json)
97 ->setStatusCode(JsonResponse::HTTP_BAD_REQUEST);
94 } 98 }
95 99
96 $userManager->updateUser($user); 100 $userManager->updateUser($user);
@@ -99,17 +103,18 @@ class UserRestController extends WallabagRestController
99 $event = new UserEvent($user, $request); 103 $event = new UserEvent($user, $request);
100 $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); 104 $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event);
101 105
102 return $this->sendUser($user); 106 return $this->sendUser($user, JsonResponse::HTTP_CREATED);
103 } 107 }
104 108
105 /** 109 /**
106 * Send user response. 110 * Send user response.
107 * 111 *
108 * @param User $user 112 * @param User $user
113 * @param int $status HTTP Status code to send
109 * 114 *
110 * @return JsonResponse 115 * @return JsonResponse
111 */ 116 */
112 private function sendUser(User $user) 117 private function sendUser(User $user, $status = JsonResponse::HTTP_OK)
113 { 118 {
114 $json = $this->get('serializer')->serialize( 119 $json = $this->get('serializer')->serialize(
115 $user, 120 $user,
@@ -117,7 +122,9 @@ class UserRestController extends WallabagRestController
117 SerializationContext::create()->setGroups(['user_api']) 122 SerializationContext::create()->setGroups(['user_api'])
118 ); 123 );
119 124
120 return (new JsonResponse())->setJson($json); 125 return (new JsonResponse())
126 ->setJson($json)
127 ->setStatusCode($status);
121 } 128 }
122 129
123 /** 130 /**
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php
index d9608246..0f119377 100644
--- a/src/Wallabag/CoreBundle/Command/InstallCommand.php
+++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php
@@ -292,165 +292,7 @@ class InstallCommand extends ContainerAwareCommand
292 // cleanup before insert new stuff 292 // cleanup before insert new stuff
293 $em->createQuery('DELETE FROM CraueConfigBundle:Setting')->execute(); 293 $em->createQuery('DELETE FROM CraueConfigBundle:Setting')->execute();
294 294
295 $settings = [ 295 foreach ($this->getContainer()->getParameter('wallabag_core.default_internal_settings') as $setting) {
296 [
297 'name' => 'share_public',
298 'value' => '1',
299 'section' => 'entry',
300 ],
301 [
302 'name' => 'carrot',
303 'value' => '1',
304 'section' => 'entry',
305 ],
306 [
307 'name' => 'share_diaspora',
308 'value' => '1',
309 'section' => 'entry',
310 ],
311 [
312 'name' => 'diaspora_url',
313 'value' => 'http://diasporapod.com',
314 'section' => 'entry',
315 ],
316 [
317 'name' => 'share_unmark',
318 'value' => '1',
319 'section' => 'entry',
320 ],
321 [
322 'name' => 'unmark_url',
323 'value' => 'https://unmark.it',
324 'section' => 'entry',
325 ],
326 [
327 'name' => 'share_shaarli',
328 'value' => '1',
329 'section' => 'entry',
330 ],
331 [
332 'name' => 'shaarli_url',
333 'value' => 'http://myshaarli.com',
334 'section' => 'entry',
335 ],
336 [
337 'name' => 'share_scuttle',
338 'value' => '1',
339 'section' => 'entry',
340 ],
341 [
342 'name' => 'scuttle_url',
343 'value' => 'http://scuttle.org',
344 'section' => 'entry',
345 ],
346 [
347 'name' => 'share_mail',
348 'value' => '1',
349 'section' => 'entry',
350 ],
351 [
352 'name' => 'share_twitter',
353 'value' => '1',
354 'section' => 'entry',
355 ],
356 [
357 'name' => 'export_epub',
358 'value' => '1',
359 'section' => 'export',
360 ],
361 [
362 'name' => 'export_mobi',
363 'value' => '1',
364 'section' => 'export',
365 ],
366 [
367 'name' => 'export_pdf',
368 'value' => '1',
369 'section' => 'export',
370 ],
371 [
372 'name' => 'export_csv',
373 'value' => '1',
374 'section' => 'export',
375 ],
376 [
377 'name' => 'export_json',
378 'value' => '1',
379 'section' => 'export',
380 ],
381 [
382 'name' => 'export_txt',
383 'value' => '1',
384 'section' => 'export',
385 ],
386 [
387 'name' => 'export_xml',
388 'value' => '1',
389 'section' => 'export',
390 ],
391 [
392 'name' => 'import_with_redis',
393 'value' => '0',
394 'section' => 'import',
395 ],
396 [
397 'name' => 'import_with_rabbitmq',
398 'value' => '0',
399 'section' => 'import',
400 ],
401 [
402 'name' => 'show_printlink',
403 'value' => '1',
404 'section' => 'entry',
405 ],
406 [
407 'name' => 'wallabag_support_url',
408 'value' => 'https://www.wallabag.org/pages/support.html',
409 'section' => 'misc',
410 ],
411 [
412 'name' => 'wallabag_url',
413 'value' => '',
414 'section' => 'misc',
415 ],
416 [
417 'name' => 'piwik_enabled',
418 'value' => '0',
419 'section' => 'analytics',
420 ],
421 [
422 'name' => 'piwik_host',
423 'value' => 'v2.wallabag.org',
424 'section' => 'analytics',
425 ],
426 [
427 'name' => 'piwik_site_id',
428 'value' => '1',
429 'section' => 'analytics',
430 ],
431 [
432 'name' => 'demo_mode_enabled',
433 'value' => '0',
434 'section' => 'misc',
435 ],
436 [
437 'name' => 'demo_mode_username',
438 'value' => 'wallabag',
439 'section' => 'misc',
440 ],
441 [
442 'name' => 'download_images_enabled',
443 'value' => '0',
444 'section' => 'misc',
445 ],
446 [
447 'name' => 'restricted_access',
448 'value' => '0',
449 'section' => 'entry',
450 ],
451 ];
452
453 foreach ($settings as $setting) {
454 $newSetting = new Setting(); 296 $newSetting = new Setting();
455 $newSetting->setName($setting['name']); 297 $newSetting->setName($setting['name']);
456 $newSetting->setValue($setting['value']); 298 $newSetting->setValue($setting['value']);
diff --git a/src/Wallabag/CoreBundle/Command/ShowUserCommand.php b/src/Wallabag/CoreBundle/Command/ShowUserCommand.php
new file mode 100644
index 00000000..0eeaabc4
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Command/ShowUserCommand.php
@@ -0,0 +1,77 @@
1<?php
2
3namespace Wallabag\CoreBundle\Command;
4
5use Doctrine\ORM\NoResultException;
6use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
7use Symfony\Component\Console\Input\InputArgument;
8use Symfony\Component\Console\Input\InputInterface;
9use Symfony\Component\Console\Output\OutputInterface;
10use Wallabag\UserBundle\Entity\User;
11
12class ShowUserCommand extends ContainerAwareCommand
13{
14 /** @var OutputInterface */
15 protected $output;
16
17 protected function configure()
18 {
19 $this
20 ->setName('wallabag:user:show')
21 ->setDescription('Show user details')
22 ->setHelp('This command shows the details for an user')
23 ->addArgument(
24 'username',
25 InputArgument::REQUIRED,
26 'User to show details for'
27 );
28 }
29
30 protected function execute(InputInterface $input, OutputInterface $output)
31 {
32 $this->output = $output;
33
34 $username = $input->getArgument('username');
35
36 try {
37 $user = $this->getUser($username);
38 $this->showUser($user);
39 } catch (NoResultException $e) {
40 $output->writeln(sprintf('<error>User "%s" not found.</error>', $username));
41
42 return 1;
43 }
44
45 return 0;
46 }
47
48 /**
49 * @param User $user
50 */
51 private function showUser(User $user)
52 {
53 $this->output->writeln(sprintf('Username : %s', $user->getUsername()));
54 $this->output->writeln(sprintf('Email : %s', $user->getEmail()));
55 $this->output->writeln(sprintf('Display name : %s', $user->getName()));
56 $this->output->writeln(sprintf('Creation date : %s', $user->getCreatedAt()->format('Y-m-d H:i:s')));
57 $this->output->writeln(sprintf('Last login : %s', $user->getLastLogin() !== null ? $user->getLastLogin()->format('Y-m-d H:i:s') : 'never'));
58 $this->output->writeln(sprintf('2FA activated: %s', $user->isTwoFactorAuthentication() ? 'yes' : 'no'));
59 }
60
61 /**
62 * Fetches a user from its username.
63 *
64 * @param string $username
65 *
66 * @return \Wallabag\UserBundle\Entity\User
67 */
68 private function getUser($username)
69 {
70 return $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($username);
71 }
72
73 private function getDoctrine()
74 {
75 return $this->getContainer()->get('doctrine');
76 }
77}
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php
index aaeb9ee9..a52288e6 100644
--- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php
@@ -6,173 +6,27 @@ use Doctrine\Common\DataFixtures\AbstractFixture;
6use Doctrine\Common\DataFixtures\OrderedFixtureInterface; 6use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
7use Doctrine\Common\Persistence\ObjectManager; 7use Doctrine\Common\Persistence\ObjectManager;
8use Craue\ConfigBundle\Entity\Setting; 8use Craue\ConfigBundle\Entity\Setting;
9use Symfony\Component\DependencyInjection\ContainerAwareInterface;
10use Symfony\Component\DependencyInjection\ContainerInterface;
9 11
10class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface 12class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
11{ 13{
12 /** 14 /**
15 * @var ContainerInterface
16 */
17 private $container;
18
19 public function setContainer(ContainerInterface $container = null)
20 {
21 $this->container = $container;
22 }
23
24 /**
13 * {@inheritdoc} 25 * {@inheritdoc}
14 */ 26 */
15 public function load(ObjectManager $manager) 27 public function load(ObjectManager $manager)
16 { 28 {
17 $settings = [ 29 foreach ($this->container->getParameter('wallabag_core.default_internal_settings') as $setting) {
18 [
19 'name' => 'share_public',
20 'value' => '1',
21 'section' => 'entry',
22 ],
23 [
24 'name' => 'carrot',
25 'value' => '1',
26 'section' => 'entry',
27 ],
28 [
29 'name' => 'share_diaspora',
30 'value' => '1',
31 'section' => 'entry',
32 ],
33 [
34 'name' => 'diaspora_url',
35 'value' => 'http://diasporapod.com',
36 'section' => 'entry',
37 ],
38 [
39 'name' => 'share_unmark',
40 'value' => '1',
41 'section' => 'entry',
42 ],
43 [
44 'name' => 'unmark_url',
45 'value' => 'https://unmark.it',
46 'section' => 'entry',
47 ],
48 [
49 'name' => 'share_shaarli',
50 'value' => '1',
51 'section' => 'entry',
52 ],
53 [
54 'name' => 'share_scuttle',
55 'value' => '1',
56 'section' => 'entry',
57 ],
58 [
59 'name' => 'shaarli_url',
60 'value' => 'http://myshaarli.com',
61 'section' => 'entry',
62 ],
63 [
64 'name' => 'scuttle_url',
65 'value' => 'http://scuttle.org',
66 'section' => 'entry',
67 ],
68 [
69 'name' => 'share_mail',
70 'value' => '1',
71 'section' => 'entry',
72 ],
73 [
74 'name' => 'share_twitter',
75 'value' => '1',
76 'section' => 'entry',
77 ],
78 [
79 'name' => 'export_epub',
80 'value' => '1',
81 'section' => 'export',
82 ],
83 [
84 'name' => 'export_mobi',
85 'value' => '1',
86 'section' => 'export',
87 ],
88 [
89 'name' => 'export_pdf',
90 'value' => '1',
91 'section' => 'export',
92 ],
93 [
94 'name' => 'export_csv',
95 'value' => '1',
96 'section' => 'export',
97 ],
98 [
99 'name' => 'export_json',
100 'value' => '1',
101 'section' => 'export',
102 ],
103 [
104 'name' => 'export_txt',
105 'value' => '1',
106 'section' => 'export',
107 ],
108 [
109 'name' => 'export_xml',
110 'value' => '1',
111 'section' => 'export',
112 ],
113 [
114 'name' => 'import_with_redis',
115 'value' => '0',
116 'section' => 'import',
117 ],
118 [
119 'name' => 'import_with_rabbitmq',
120 'value' => '0',
121 'section' => 'import',
122 ],
123 [
124 'name' => 'show_printlink',
125 'value' => '1',
126 'section' => 'entry',
127 ],
128 [
129 'name' => 'wallabag_support_url',
130 'value' => 'https://www.wallabag.org/pages/support.html',
131 'section' => 'misc',
132 ],
133 [
134 'name' => 'wallabag_url',
135 'value' => 'http://v2.wallabag.org',
136 'section' => 'misc',
137 ],
138 [
139 'name' => 'piwik_enabled',
140 'value' => '0',
141 'section' => 'analytics',
142 ],
143 [
144 'name' => 'piwik_host',
145 'value' => 'v2.wallabag.org',
146 'section' => 'analytics',
147 ],
148 [
149 'name' => 'piwik_site_id',
150 'value' => '1',
151 'section' => 'analytics',
152 ],
153 [
154 'name' => 'demo_mode_enabled',
155 'value' => '0',
156 'section' => 'misc',
157 ],
158 [
159 'name' => 'demo_mode_username',
160 'value' => 'wallabag',
161 'section' => 'misc',
162 ],
163 [
164 'name' => 'download_images_enabled',
165 'value' => '0',
166 'section' => 'misc',
167 ],
168 [
169 'name' => 'restricted_access',
170 'value' => '0',
171 'section' => 'entry',
172 ],
173 ];
174
175 foreach ($settings as $setting) {
176 $newSetting = new Setting(); 30 $newSetting = new Setting();
177 $newSetting->setName($setting['name']); 31 $newSetting->setName($setting['name']);
178 $newSetting->setValue($setting['value']); 32 $newSetting->setValue($setting['value']);
diff --git a/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php b/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php
index 8b5b5744..33df92d3 100644
--- a/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php
+++ b/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php
@@ -52,6 +52,17 @@ class Configuration implements ConfigurationInterface
52 ->scalarNode('api_limit_mass_actions') 52 ->scalarNode('api_limit_mass_actions')
53 ->defaultValue(10) 53 ->defaultValue(10)
54 ->end() 54 ->end()
55 ->arrayNode('default_internal_settings')
56 ->prototype('array')
57 ->children()
58 ->scalarNode('name')->end()
59 ->scalarNode('value')->end()
60 ->enumNode('section')
61 ->values(['entry', 'misc', 'api', 'analytics', 'export', 'import'])
62 ->end()
63 ->end()
64 ->end()
65 ->end()
55 ->end() 66 ->end()
56 ; 67 ;
57 68
diff --git a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php
index a2a703cb..b4d8a386 100644
--- a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php
+++ b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php
@@ -28,6 +28,7 @@ class WallabagCoreExtension extends Extension
28 $container->setParameter('wallabag_core.fetching_error_message', $config['fetching_error_message']); 28 $container->setParameter('wallabag_core.fetching_error_message', $config['fetching_error_message']);
29 $container->setParameter('wallabag_core.fetching_error_message_title', $config['fetching_error_message_title']); 29 $container->setParameter('wallabag_core.fetching_error_message_title', $config['fetching_error_message_title']);
30 $container->setParameter('wallabag_core.api_limit_mass_actions', $config['api_limit_mass_actions']); 30 $container->setParameter('wallabag_core.api_limit_mass_actions', $config['api_limit_mass_actions']);
31 $container->setParameter('wallabag_core.default_internal_settings', $config['default_internal_settings']);
31 32
32 $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 33 $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
33 $loader->load('services.yml'); 34 $loader->load('services.yml');
diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
index bfaa1976..d5820e66 100644
--- a/src/Wallabag/CoreBundle/Helper/ContentProxy.php
+++ b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
@@ -105,7 +105,7 @@ class ContentProxy
105 } 105 }
106 } 106 }
107 107
108 if (!empty($content['authors'])) { 108 if (!empty($content['authors']) && is_array($content['authors'])) {
109 $entry->setPublishedBy($content['authors']); 109 $entry->setPublishedBy($content['authors']);
110 } 110 }
111 111
diff --git a/src/Wallabag/CoreBundle/Helper/DownloadImages.php b/src/Wallabag/CoreBundle/Helper/DownloadImages.php
index 54e23a05..ed888cdb 100644
--- a/src/Wallabag/CoreBundle/Helper/DownloadImages.php
+++ b/src/Wallabag/CoreBundle/Helper/DownloadImages.php
@@ -5,6 +5,7 @@ namespace Wallabag\CoreBundle\Helper;
5use Psr\Log\LoggerInterface; 5use Psr\Log\LoggerInterface;
6use Symfony\Component\DomCrawler\Crawler; 6use Symfony\Component\DomCrawler\Crawler;
7use GuzzleHttp\Client; 7use GuzzleHttp\Client;
8use GuzzleHttp\Message\Response;
8use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser; 9use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser;
9use Symfony\Component\Finder\Finder; 10use Symfony\Component\Finder\Finder;
10 11
@@ -116,13 +117,11 @@ class DownloadImages
116 return false; 117 return false;
117 } 118 }
118 119
119 $ext = $this->mimeGuesser->guess($res->getHeader('content-type')); 120 $ext = $this->getExtensionFromResponse($res, $imagePath);
120 $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]); 121 if (false === $res) {
121 if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) {
122 $this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping: '.$imagePath);
123
124 return false; 122 return false;
125 } 123 }
124
126 $hashImage = hash('crc32', $absolutePath); 125 $hashImage = hash('crc32', $absolutePath);
127 $localPath = $folderPath.'/'.$hashImage.'.'.$ext; 126 $localPath = $folderPath.'/'.$hashImage.'.'.$ext;
128 127
@@ -237,4 +236,45 @@ class DownloadImages
237 236
238 return false; 237 return false;
239 } 238 }
239
240 /**
241 * Retrieve and validate the extension from the response of the url of the image.
242 *
243 * @param Response $res Guzzle Response
244 * @param string $imagePath Path from the src image from the content (used for log only)
245 *
246 * @return string|false Extension name or false if validation failed
247 */
248 private function getExtensionFromResponse(Response $res, $imagePath)
249 {
250 $ext = $this->mimeGuesser->guess($res->getHeader('content-type'));
251 $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]);
252
253 // ok header doesn't have the extension, try a different way
254 if (empty($ext)) {
255 $types = [
256 'jpeg' => "\xFF\xD8\xFF",
257 'gif' => 'GIF',
258 'png' => "\x89\x50\x4e\x47\x0d\x0a",
259 ];
260 $bytes = substr((string) $res->getBody(), 0, 8);
261
262 foreach ($types as $type => $header) {
263 if (0 === strpos($bytes, $header)) {
264 $ext = $type;
265 break;
266 }
267 }
268
269 $this->logger->debug('DownloadImages: Checking extension (alternative)', ['ext' => $ext]);
270 }
271
272 if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) {
273 $this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping: '.$imagePath);
274
275 return false;
276 }
277
278 return $ext;
279 }
240} 280}
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
index 70e9575a..16e8072b 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
@@ -24,7 +24,7 @@ menu:
24 tags: 'Tags' 24 tags: 'Tags'
25 internal_settings: 'Strumenti' 25 internal_settings: 'Strumenti'
26 import: 'Importa' 26 import: 'Importa'
27 howto: 'How to' 27 howto: 'Come fare'
28 # developer: 'API clients management' 28 # developer: 'API clients management'
29 logout: 'Logout' 29 logout: 'Logout'
30 about: 'About' 30 about: 'About'
@@ -44,8 +44,8 @@ footer:
44 wallabag: 44 wallabag:
45 elsewhere: 'Porta wallabag con te' 45 elsewhere: 'Porta wallabag con te'
46 social: 'Social' 46 social: 'Social'
47 powered_by: 'powered by' 47 powered_by: 'Offerto da'
48 about: 'About' 48 about: 'A proposito'
49 # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day! 49 # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
50 50
51config: 51config:
@@ -55,7 +55,7 @@ config:
55 rss: 'RSS' 55 rss: 'RSS'
56 user_info: 'Informazioni utente' 56 user_info: 'Informazioni utente'
57 password: 'Password' 57 password: 'Password'
58 rules: 'Regole di tagging' 58 rules: 'Regole di etichettatura'
59 new_user: 'Aggiungi utente' 59 new_user: 'Aggiungi utente'
60 form: 60 form:
61 save: 'Salva' 61 save: 'Salva'
@@ -83,7 +83,7 @@ config:
83 # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account." 83 # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account."
84 form_rss: 84 form_rss:
85 description: 'I feed RSS generati da wallabag ti permettono di leggere i tuoi contenuti salvati con il tuo lettore di RSS preferito. Prima, devi generare un token.' 85 description: 'I feed RSS generati da wallabag ti permettono di leggere i tuoi contenuti salvati con il tuo lettore di RSS preferito. Prima, devi generare un token.'
86 token_label: 'RSS token' 86 token_label: 'Token RSS'
87 no_token: 'Nessun token' 87 no_token: 'Nessun token'
88 token_create: 'Crea il tuo token' 88 token_create: 'Crea il tuo token'
89 token_reset: 'Rigenera il tuo token' 89 token_reset: 'Rigenera il tuo token'
@@ -94,10 +94,10 @@ config:
94 archive: 'archiviati' 94 archive: 'archiviati'
95 rss_limit: 'Numero di elementi nel feed' 95 rss_limit: 'Numero di elementi nel feed'
96 form_user: 96 form_user:
97 two_factor_description: "Abilitando la two factor authentication riceverai una e-mail con un codice per ogni nuova connesione non verificata" 97 two_factor_description: "Abilitando l'\autenticazione a due fattori riceverai una e-mail con un codice per ogni nuova connesione non verificata"
98 name_label: 'Nome' 98 name_label: 'Nome'
99 email_label: 'E-mail' 99 email_label: 'E-mail'
100 twoFactorAuthentication_label: 'Two factor authentication' 100 twoFactorAuthentication_label: 'Autenticazione a due fattori'
101 # help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email." 101 # help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
102 delete: 102 delete:
103 # title: Delete my account (a.k.a danger zone) 103 # title: Delete my account (a.k.a danger zone)
@@ -119,19 +119,19 @@ config:
119 repeat_new_password_label: 'Ripeti la nuova password' 119 repeat_new_password_label: 'Ripeti la nuova password'
120 form_rules: 120 form_rules:
121 if_label: 'se' 121 if_label: 'se'
122 then_tag_as_label: 'allora tagga come' 122 then_tag_as_label: 'allora etichetta come'
123 delete_rule_label: 'elimina' 123 delete_rule_label: 'elimina'
124 # edit_rule_label: 'edit' 124 # edit_rule_label: 'edit'
125 rule_label: 'Regola' 125 rule_label: 'Regola'
126 tags_label: 'Tag' 126 tags_label: 'Etichetta'
127 faq: 127 faq:
128 title: 'FAQ' 128 title: 'FAQ'
129 tagging_rules_definition_title: 'Cosa significa « regole di tagging » ?' 129 tagging_rules_definition_title: 'Cosa significa « regole di etichettatura» ?'
130 tagging_rules_definition_description: 'Sono regole utilizzate da wallabag per taggare automaticamente i contenuti.<br />Ogni volta che viene aggiunto un contenuto, tutte le regole di tagging rules vengono utilizzate per aggiungere i tag configurati, risparmiandoti il lavoro di classificare i contenuti manualmente.' 130 tagging_rules_definition_description: 'Sono regole utilizzate da wallabag per etichettare automaticamente i contenuti.<br />Ogni volta che viene aggiunto un contenuto, tutte le regole di etichettatura vengono utilizzate per aggiungere le etichette configurate, risparmiandoti il lavoro di classificare i contenuti manualmente.'
131 how_to_use_them_title: 'Come si usano?' 131 how_to_use_them_title: 'Come si usano?'
132 how_to_use_them_description: 'Diciamo che vuoi taggare un contenuto come « <i>lettura veloce</i> » quando il tempo di lettura è inferiore ai 3 minuti.<br />In questo case, devi mettere « readingTime &lt;= 3 » nel campo <i>Regola</i> e « <i>lettura veloce</i> » nel campo <i>Tag</i>.<br />Molti tag si possono aggiungere contemporanemente separandoli con una virgola: « <i>lettura veloce, da leggere</i> »<br />Regole complesse possono essere scritte utilizzando gli operatori predefiniti: se « <i>readingTime &gt;= 5 AND domainName = "github.com"</i> » allora tagga « <i>lettura lunga, github </i> »' 132 how_to_use_them_description: 'Diciamo che vuoi etichettare un contenuto come « <i>lettura veloce</i> » quando il tempo di lettura è inferiore ai 3 minuti.<br />In questo case, devi mettere « readingTime &lt;= 3 » nel campo <i>Regola</i> e « <i>lettura veloce</i> » nel campo <i>Etichette</i>.<br />Molte etichette si possono aggiungere contemporanemente separandole con una virgola: « <i>lettura veloce, da leggere</i> »<br />Regole complesse possono essere scritte utilizzando gli operatori predefiniti: se « <i>readingTime &gt;= 5 AND domainName = "github.com"</i> » allora etichetta « <i>lettura lunga, github </i> »'
133 variables_available_title: 'Quali operatori e variabili posso utilizzare per scrivere delle regole?' 133 variables_available_title: 'Quali operatori e variabili posso utilizzare per scrivere delle regole?'
134 variables_available_description: 'I seguenti operatori e variabili posso essere utilizzati per scrivere regole di tagging:' 134 variables_available_description: 'I seguenti operatori e variabili posso essere utilizzati per scrivere regole di etichettatura:'
135 meaning: 'Significato' 135 meaning: 'Significato'
136 variable_description: 136 variable_description:
137 label: 'Variabile' 137 label: 'Variabile'
@@ -211,7 +211,7 @@ entry:
211 view_original_article: 'Contenuto originale' 211 view_original_article: 'Contenuto originale'
212 re_fetch_content: 'Ri-ottieni pagina' 212 re_fetch_content: 'Ri-ottieni pagina'
213 delete: 'Elimina' 213 delete: 'Elimina'
214 add_a_tag: 'Aggiungi un tag' 214 add_a_tag: 'Aggiungi un''etichetta'
215 share_content: 'Condividi' 215 share_content: 'Condividi'
216 share_email_label: 'E-mail' 216 share_email_label: 'E-mail'
217 # public_link: 'public link' 217 # public_link: 'public link'
@@ -222,7 +222,7 @@ entry:
222 label: 'Problemi?' 222 label: 'Problemi?'
223 description: 'Questo contenuto viene visualizzato male?' 223 description: 'Questo contenuto viene visualizzato male?'
224 edit_title: 'Modifica titolo' 224 edit_title: 'Modifica titolo'
225 original_article: 'originale' 225 original_article: 'Originale'
226 annotations_on_the_entry: '{0} Nessuna annotazione|{1} Una annotazione|]1,Inf[ %count% annotazioni' 226 annotations_on_the_entry: '{0} Nessuna annotazione|{1} Una annotazione|]1,Inf[ %count% annotazioni'
227 created_at: 'Data di creazione' 227 created_at: 'Data di creazione'
228 # published_at: 'Publication date' 228 # published_at: 'Publication date'
@@ -242,11 +242,11 @@ entry:
242 public: 242 public:
243 # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>" 243 # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>"
244 confirm: 244 confirm:
245 # delete: "Are you sure you want to remove that article?" 245 delete: "Vuoi veramente rimuovere quell'articolo?"
246 # delete_tag: "Are you sure you want to remove that tag from that article?" 246 delete_tag: "Vuoi veramente rimuovere quell'etichetta da quell'articolo?"
247 247
248about: 248about:
249 page_title: 'About' 249 page_title: 'A proposito'
250 top_menu: 250 top_menu:
251 who_behind_wallabag: "Chi c'è dietro a wallabag" 251 who_behind_wallabag: "Chi c'è dietro a wallabag"
252 getting_help: 'Ottieni aiuto' 252 getting_help: 'Ottieni aiuto'
@@ -265,7 +265,7 @@ about:
265 bug_reports: 'Bug reports' 265 bug_reports: 'Bug reports'
266 support: '<a href="https://github.com/wallabag/wallabag/issues">su GitHub</a>' 266 support: '<a href="https://github.com/wallabag/wallabag/issues">su GitHub</a>'
267 helping: 267 helping:
268 description: 'wallabag è gratuito opensource. Puoi aiutarci:' 268 description: 'wallabag è gratuito ed OpenSource. Puoi aiutarci:'
269 by_contributing: 'per contribuire al progetto:' 269 by_contributing: 'per contribuire al progetto:'
270 by_contributing_2: 'un elenco delle attività richieste' 270 by_contributing_2: 'un elenco delle attività richieste'
271 by_paypal: 'via Paypal' 271 by_paypal: 'via Paypal'
@@ -273,7 +273,7 @@ about:
273 description: 'Un grazie ai collaboratori di wallabag web application' 273 description: 'Un grazie ai collaboratori di wallabag web application'
274 third_party: 274 third_party:
275 description: 'Ecco un elenco delle librerie di terze parti utilizzate in wallabag (con le rispettive licenze):' 275 description: 'Ecco un elenco delle librerie di terze parti utilizzate in wallabag (con le rispettive licenze):'
276 package: 'Package' 276 package: 'Pacchetto'
277 license: 'Licenza' 277 license: 'Licenza'
278 278
279howto: 279howto:
@@ -299,7 +299,7 @@ howto:
299 ios: 'sullo store di iTunes' 299 ios: 'sullo store di iTunes'
300 windows: 'sullo store di Microsoft' 300 windows: 'sullo store di Microsoft'
301 bookmarklet: 301 bookmarklet:
302 description: 'Trascinando e rilasciando questo link sulla barra dei bookmark del tuo browser:' 302 description: 'Trascinando e rilasciando questo link sulla barra dei preferiti del tuo browser:'
303 shortcuts: 303 shortcuts:
304 # page_description: Here are the shortcuts available in wallabag. 304 # page_description: Here are the shortcuts available in wallabag.
305 # shortcut: Shortcut 305 # shortcut: Shortcut
@@ -333,7 +333,7 @@ quickstart:
333 # more: 'More…' 333 # more: 'More…'
334 intro: 334 intro:
335 title: 'Benvenuto su wallabag!' 335 title: 'Benvenuto su wallabag!'
336 paragraph_1: "Un tour in cui ti guideremo per scoprire e che ti mostrerà delle funzionalità che potrebbero interessarti." 336 paragraph_1: "Ti accompagneremo alla scoperta di wallabag e ti mostreremo delle funzionalità che potrebbero interessarti."
337 paragraph_2: 'Seguici!' 337 paragraph_2: 'Seguici!'
338 configure: 338 configure:
339 title: "Configura l'applicazione" 339 title: "Configura l'applicazione"
@@ -383,9 +383,9 @@ quickstart:
383 gitter: 'Su Gitter' 383 gitter: 'Su Gitter'
384 384
385tag: 385tag:
386 page_title: 'Tags' 386 page_title: 'Etichette'
387 list: 387 list:
388 number_on_the_page: "{0} Non ci sono tag.|{1} C'è un tag.|]1,Inf[ ci sono %count% tag." 388 number_on_the_page: "{0} Non ci sono etichette.|{1} C'è un'etichetta.|]1,Inf[ ci sono %count% etichette."
389 # see_untagged_entries: 'See untagged entries' 389 # see_untagged_entries: 'See untagged entries'
390 new: 390 new:
391 # add: 'Add' 391 # add: 'Add'
@@ -403,20 +403,20 @@ import:
403 save_label: 'Carica file' 403 save_label: 'Carica file'
404 pocket: 404 pocket:
405 page_title: 'Importa da > Pocket' 405 page_title: 'Importa da > Pocket'
406 description: "Questo importatore copierà tutti i tuoi dati da Pocket. Pocket non ci consente di ottenere contenuti dal loro servzio, così il contenuto leggibile di ogni articolo verrà ri-ottenuto da wallabag." 406 description: "Questo importatore copierà tutti i tuoi dati da Pocket. Pocket non ci consente di ottenere contenuti dal loro servizio, così il contenuto leggibile di ogni articolo verrà ri-ottenuto da wallabag."
407 config_missing: 407 config_missing:
408 description: "Importazione da Pocket non configurata." 408 description: "Importazione da Pocket non configurata."
409 admin_message: 'Devi definire %keyurls% una pocket_consumer_key %keyurle%.' 409 admin_message: 'Devi definire %keyurls% una pocket_consumer_key %keyurle%.'
410 user_message: 'Il tuo amministratore di server deve define una API Key per Pocket.' 410 user_message: 'Il tuo amministratore del server deve definire una API Key per Pocket.'
411 authorize_message: 'Puoi importare dati dal tuo account Pocket. Devi solo cliccare sul pulsante sottostante e autorizzare la connessione a getpocket.com.' 411 authorize_message: 'Puoi importare dati dal tuo account Pocket. Devi solo cliccare sul pulsante sottostante e autorizzare la connessione a getpocket.com.'
412 connect_to_pocket: 'Connetti a Pocket and importa i dati' 412 connect_to_pocket: 'Connetti a Pocket and importa i dati'
413 wallabag_v1: 413 wallabag_v1:
414 page_title: 'Importa da > Wallabag v1' 414 page_title: 'Importa da > Wallabag v1'
415 description: 'Questo importatore copierà tutti i tuoi dati da un wallabag v1. Nella tua pagina di configurazione, clicca su "JSON export" nella sezione "Esport i tuoi dati di wallabag". Otterrai un file "wallabag-export-1-xxxx-xx-xx.json".' 415 description: 'Questo importatore copierà tutti i tuoi dati da un wallabag v1. Nella tua pagina di configurazione, clicca su "JSON export" nella sezione "Esporta i tuoi dati di wallabag". Otterrai un file "wallabag-export-1-xxxx-xx-xx.json".'
416 how_to: 'Seleziona la tua esportazione di wallabag e clicca sul pulsante sottostante caricare il file e importare i dati.' 416 how_to: 'Seleziona la tua esportazione di wallabag e clicca sul pulsante sottostante caricare il file e importare i dati.'
417 wallabag_v2: 417 wallabag_v2:
418 page_title: 'Importa da > Wallabag v2' 418 page_title: 'Importa da > Wallabag v2'
419 description: 'Questo importatore copierà tutti i tuoi dati da un wallabag v2. Vai in "Tutti i contenuti", e, nella sidebar di esportazione, clicca su "JSON". Otterrai un file "Tutti i contenuti.json".' 419 description: 'Questo importatore copierà tutti i tuoi dati da un wallabag v2. Vai in "Tutti i contenuti", e, nella barra laterale di esportazione, clicca su "JSON". Otterrai un file "Tutti i contenuti.json'
420 readability: 420 readability:
421 page_title: 'Importa da > Readability' 421 page_title: 'Importa da > Readability'
422 # description: 'This importer will import all your Readability articles. On the tools (https://www.readability.com/tools/) page, click on "Export your data" in the "Data Export" section. You will received an email to download a json (which does not end with .json in fact).' 422 # description: 'This importer will import all your Readability articles. On the tools (https://www.readability.com/tools/) page, click on "Export your data" in the "Data Export" section. You will received an email to download a json (which does not end with .json in fact).'
@@ -455,19 +455,19 @@ developer:
455 title: 'Client esistenti' 455 title: 'Client esistenti'
456 field_id: 'Client ID' 456 field_id: 'Client ID'
457 field_secret: 'Client secret' 457 field_secret: 'Client secret'
458 field_uris: 'Redirect URI' 458 field_uris: 'URI di reindirizzamento'
459 field_grant_types: 'Tipi di grant permessi' 459 field_grant_types: 'Tipi di permessi concessi'
460 no_client: 'Ancora nessun client.' 460 no_client: 'Ancora nessun client.'
461 remove: 461 remove:
462 warn_message_1: "Hai la possibilit di rimuovere questo client.L'operazione è IRREVERSIBILE!" 462 warn_message_1: "Hai la possibilit di rimuovere questo client. L'operazione è IRREVERSIBILE!"
463 warn_message_2: "Se lo rimuovi, ogni app configurata con questo client non sarà più in grado di autenticarsi." 463 warn_message_2: "Se lo rimuovi, ogni app configurata con questo client non sarà più in grado di autenticarsi."
464 action: 'Rimuovi questo client' 464 action: 'Rimuovi questo client'
465 client: 465 client:
466 # page_title: 'API clients management > Nuovo client' 466 # page_title: 'API clients management > Nuovo client'
467 page_description: 'Stai per creare un nuovo client. Compila i campi sottostanti per il redirect URI della tua applicazione.' 467 page_description: 'Stai per creare un nuovo client. Compila i campi sottostanti per lo URI di reindirizzamento della tua applicazione.'
468 form: 468 form:
469 # name_label: 'Name of the client' 469 # name_label: 'Name of the client'
470 redirect_uris_label: 'Redirect URI' 470 redirect_uris_label: 'URI di reindirizzamento'
471 save_label: 'Crea un nuovo client' 471 save_label: 'Crea un nuovo client'
472 action_back: 'Indietro' 472 action_back: 'Indietro'
473 client_parameter: 473 client_parameter:
@@ -477,7 +477,7 @@ developer:
477 field_id: 'Client ID' 477 field_id: 'Client ID'
478 field_secret: 'Client secret' 478 field_secret: 'Client secret'
479 back: 'Indietro' 479 back: 'Indietro'
480 read_howto: 'Leggi howto "Come creare la mia prima applicazione"' 480 read_howto: 'Leggi "Come creare la mia prima applicazione"'
481 howto: 481 howto:
482 # page_title: 'API clients management > Come creare la mia prima applicazione' 482 # page_title: 'API clients management > Come creare la mia prima applicazione'
483 description: 483 description:
@@ -530,9 +530,9 @@ flashes:
530 password_not_updated_demo: "In modalità demo, non puoi cambiare la password dell'utente." 530 password_not_updated_demo: "In modalità demo, non puoi cambiare la password dell'utente."
531 user_updated: 'Informazioni aggiornate' 531 user_updated: 'Informazioni aggiornate'
532 rss_updated: 'Informazioni RSS aggiornate' 532 rss_updated: 'Informazioni RSS aggiornate'
533 tagging_rules_updated: 'Regole di tagging aggiornate' 533 tagging_rules_updated: 'Regole di etichettatura aggiornate'
534 tagging_rules_deleted: 'Regola di tagging aggiornate' 534 tagging_rules_deleted: 'Regole di etichettatura eliminate'
535 rss_token_updated: 'RSS token aggiornato' 535 rss_token_updated: 'Token RSS aggiornato'
536 # annotations_reset: Annotations reset 536 # annotations_reset: Annotations reset
537 # tags_reset: Tags reset 537 # tags_reset: Tags reset
538 # entries_reset: Entries reset 538 # entries_reset: Entries reset
@@ -552,7 +552,7 @@ flashes:
552 entry_deleted: 'Contenuto eliminato' 552 entry_deleted: 'Contenuto eliminato'
553 tag: 553 tag:
554 notice: 554 notice:
555 tag_added: 'Tag aggiunto' 555 tag_added: 'Etichetta aggiunta'
556 import: 556 import:
557 notice: 557 notice:
558 failed: 'Importazione fallita, riprova.' 558 failed: 'Importazione fallita, riprova.'
diff --git a/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
index 0968cfaf..74ec34b1 100644
--- a/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
+++ b/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
@@ -477,6 +477,10 @@ class EntryRestControllerTest extends WallabagApiTestCase
477 'tags' => 'new tag '.uniqid(), 477 'tags' => 'new tag '.uniqid(),
478 'starred' => '1', 478 'starred' => '1',
479 'archive' => '0', 479 'archive' => '0',
480 'language' => 'de_DE',
481 'preview_picture' => 'http://preview.io/picture.jpg',
482 'authors' => 'bob,sponge',
483 'content' => 'awesome',
480 ]); 484 ]);
481 485
482 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 486 $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
@@ -488,6 +492,11 @@ class EntryRestControllerTest extends WallabagApiTestCase
488 $this->assertEquals('New awesome title', $content['title']); 492 $this->assertEquals('New awesome title', $content['title']);
489 $this->assertGreaterThan($nbTags, count($content['tags'])); 493 $this->assertGreaterThan($nbTags, count($content['tags']));
490 $this->assertEquals(1, $content['user_id']); 494 $this->assertEquals(1, $content['user_id']);
495 $this->assertEquals('de_DE', $content['language']);
496 $this->assertEquals('http://preview.io/picture.jpg', $content['preview_picture']);
497 $this->assertContains('sponge', $content['published_by']);
498 $this->assertContains('bob', $content['published_by']);
499 $this->assertEquals('awesome', $content['content']);
491 } 500 }
492 501
493 public function testPatchEntryWithoutQuotes() 502 public function testPatchEntryWithoutQuotes()
@@ -509,6 +518,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
509 'tags' => 'new tag '.uniqid(), 518 'tags' => 'new tag '.uniqid(),
510 'starred' => 1, 519 'starred' => 1,
511 'archive' => 0, 520 'archive' => 0,
521 'authors' => ['bob', 'sponge'],
512 ]); 522 ]);
513 523
514 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 524 $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
@@ -519,6 +529,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
519 $this->assertEquals($entry->getUrl(), $content['url']); 529 $this->assertEquals($entry->getUrl(), $content['url']);
520 $this->assertEquals('New awesome title', $content['title']); 530 $this->assertEquals('New awesome title', $content['title']);
521 $this->assertGreaterThan($nbTags, count($content['tags'])); 531 $this->assertGreaterThan($nbTags, count($content['tags']));
532 $this->assertTrue(empty($content['published_by']), 'Authors were not saved because of an array instead of a string');
522 } 533 }
523 534
524 public function testGetTagsEntry() 535 public function testGetTagsEntry()
diff --git a/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php
index 3f4969a5..5735bc58 100644
--- a/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php
+++ b/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php
@@ -27,15 +27,32 @@ class UserRestControllerTest extends WallabagApiTestCase
27 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 27 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
28 } 28 }
29 29
30 public function testGetUserWithoutAuthentication()
31 {
32 $client = static::createClient();
33 $client->request('GET', '/api/user.json');
34 $this->assertEquals(401, $client->getResponse()->getStatusCode());
35
36 $content = json_decode($client->getResponse()->getContent(), true);
37
38 $this->assertArrayHasKey('error', $content);
39 $this->assertArrayHasKey('error_description', $content);
40
41 $this->assertEquals('access_denied', $content['error']);
42
43 $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type'));
44 }
45
30 public function testCreateNewUser() 46 public function testCreateNewUser()
31 { 47 {
48 $this->client->getContainer()->get('craue_config')->set('api_user_registration', 1);
32 $this->client->request('PUT', '/api/user.json', [ 49 $this->client->request('PUT', '/api/user.json', [
33 'username' => 'google', 50 'username' => 'google',
34 'password' => 'googlegoogle', 51 'password' => 'googlegoogle',
35 'email' => 'wallabag@google.com', 52 'email' => 'wallabag@google.com',
36 ]); 53 ]);
37 54
38 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 55 $this->assertEquals(201, $this->client->getResponse()->getStatusCode());
39 56
40 $content = json_decode($this->client->getResponse()->getContent(), true); 57 $content = json_decode($this->client->getResponse()->getContent(), true);
41 58
@@ -50,30 +67,51 @@ class UserRestControllerTest extends WallabagApiTestCase
50 67
51 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 68 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
52 69
53 // remove the created user to avoid side effect on other tests 70 $this->client->getContainer()->get('craue_config')->set('api_user_registration', 0);
54 // @todo remove these lines when test will be isolated 71 }
55 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager'); 72
73 public function testCreateNewUserWithoutAuthentication()
74 {
75 // create a new client instead of using $this->client to be sure client isn't authenticated
76 $client = static::createClient();
77 $client->getContainer()->get('craue_config')->set('api_user_registration', 1);
78 $client->request('PUT', '/api/user.json', [
79 'username' => 'google',
80 'password' => 'googlegoogle',
81 'email' => 'wallabag@google.com',
82 ]);
83
84 $this->assertEquals(201, $client->getResponse()->getStatusCode());
85
86 $content = json_decode($client->getResponse()->getContent(), true);
56 87
57 $query = $em->createQuery('DELETE FROM Wallabag\CoreBundle\Entity\Config c WHERE c.user = :user_id'); 88 $this->assertArrayHasKey('id', $content);
58 $query->setParameter('user_id', $content['id']); 89 $this->assertArrayHasKey('email', $content);
59 $query->execute(); 90 $this->assertArrayHasKey('username', $content);
91 $this->assertArrayHasKey('created_at', $content);
92 $this->assertArrayHasKey('updated_at', $content);
60 93
61 $query = $em->createQuery('DELETE FROM Wallabag\UserBundle\Entity\User u WHERE u.id = :id'); 94 $this->assertEquals('wallabag@google.com', $content['email']);
62 $query->setParameter('id', $content['id']); 95 $this->assertEquals('google', $content['username']);
63 $query->execute(); 96
97 $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type'));
98
99 $client->getContainer()->get('craue_config')->set('api_user_registration', 0);
64 } 100 }
65 101
66 public function testCreateNewUserWithExistingEmail() 102 public function testCreateNewUserWithExistingEmail()
67 { 103 {
68 $this->client->request('PUT', '/api/user.json', [ 104 $client = static::createClient();
105 $client->getContainer()->get('craue_config')->set('api_user_registration', 1);
106 $client->request('PUT', '/api/user.json', [
69 'username' => 'admin', 107 'username' => 'admin',
70 'password' => 'googlegoogle', 108 'password' => 'googlegoogle',
71 'email' => 'bigboss@wallabag.org', 109 'email' => 'bigboss@wallabag.org',
72 ]); 110 ]);
73 111
74 $this->assertEquals(400, $this->client->getResponse()->getStatusCode()); 112 $this->assertEquals(400, $client->getResponse()->getStatusCode());
75 113
76 $content = json_decode($this->client->getResponse()->getContent(), true); 114 $content = json_decode($client->getResponse()->getContent(), true);
77 115
78 $this->assertArrayHasKey('error', $content); 116 $this->assertArrayHasKey('error', $content);
79 $this->assertArrayHasKey('username', $content['error']); 117 $this->assertArrayHasKey('username', $content['error']);
@@ -85,26 +123,50 @@ class UserRestControllerTest extends WallabagApiTestCase
85 $this->assertEquals('This value is already used.', $content['error']['username'][0]); 123 $this->assertEquals('This value is already used.', $content['error']['username'][0]);
86 $this->assertEquals('This value is already used.', $content['error']['email'][0]); 124 $this->assertEquals('This value is already used.', $content['error']['email'][0]);
87 125
88 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 126 $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type'));
127
128 $client->getContainer()->get('craue_config')->set('api_user_registration', 0);
89 } 129 }
90 130
91 public function testCreateNewUserWithTooShortPassword() 131 public function testCreateNewUserWithTooShortPassword()
92 { 132 {
93 $this->client->request('PUT', '/api/user.json', [ 133 $client = static::createClient();
134 $client->getContainer()->get('craue_config')->set('api_user_registration', 1);
135 $client->request('PUT', '/api/user.json', [
94 'username' => 'facebook', 136 'username' => 'facebook',
95 'password' => 'face', 137 'password' => 'face',
96 'email' => 'facebook@wallabag.org', 138 'email' => 'facebook@wallabag.org',
97 ]); 139 ]);
98 140
99 $this->assertEquals(400, $this->client->getResponse()->getStatusCode()); 141 $this->assertEquals(400, $client->getResponse()->getStatusCode());
100 142
101 $content = json_decode($this->client->getResponse()->getContent(), true); 143 $content = json_decode($client->getResponse()->getContent(), true);
102 144
103 $this->assertArrayHasKey('error', $content); 145 $this->assertArrayHasKey('error', $content);
104 $this->assertArrayHasKey('password', $content['error']); 146 $this->assertArrayHasKey('password', $content['error']);
105 147
106 $this->assertEquals('validator.password_too_short', $content['error']['password'][0]); 148 $this->assertEquals('validator.password_too_short', $content['error']['password'][0]);
107 149
108 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 150 $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type'));
151
152 $client->getContainer()->get('craue_config')->set('api_user_registration', 0);
153 }
154
155 public function testCreateNewUserWhenRegistrationIsDisabled()
156 {
157 $client = static::createClient();
158 $client->request('PUT', '/api/user.json', [
159 'username' => 'facebook',
160 'password' => 'face',
161 'email' => 'facebook@wallabag.org',
162 ]);
163
164 $this->assertEquals(403, $client->getResponse()->getStatusCode());
165
166 $content = json_decode($client->getResponse()->getContent(), true);
167
168 $this->assertArrayHasKey('error', $content);
169
170 $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type'));
109 } 171 }
110} 172}
diff --git a/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
index c87e58de..df638e8f 100644
--- a/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
+++ b/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
@@ -8,12 +8,14 @@ class WallabagRestControllerTest extends WallabagApiTestCase
8{ 8{
9 public function testGetVersion() 9 public function testGetVersion()
10 { 10 {
11 $this->client->request('GET', '/api/version'); 11 // create a new client instead of using $this->client to be sure client isn't authenticated
12 $client = static::createClient();
13 $client->request('GET', '/api/version');
12 14
13 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 15 $this->assertEquals(200, $client->getResponse()->getStatusCode());
14 16
15 $content = json_decode($this->client->getResponse()->getContent(), true); 17 $content = json_decode($client->getResponse()->getContent(), true);
16 18
17 $this->assertEquals($this->client->getContainer()->getParameter('wallabag_core.version'), $content); 19 $this->assertEquals($client->getContainer()->getParameter('wallabag_core.version'), $content);
18 } 20 }
19} 21}
diff --git a/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php b/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php
new file mode 100644
index 00000000..3b928d1e
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php
@@ -0,0 +1,95 @@
1<?php
2
3namespace Tests\Wallabag\CoreBundle\Command;
4
5use Symfony\Bundle\FrameworkBundle\Console\Application;
6use Symfony\Component\Console\Tester\CommandTester;
7use Wallabag\CoreBundle\Command\CleanDuplicatesCommand;
8use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
9use Wallabag\CoreBundle\Command\ShowUserCommand;
10use Wallabag\CoreBundle\Entity\Entry;
11use Wallabag\UserBundle\Entity\User;
12
13class ShowUserCommandTest extends WallabagCoreTestCase
14{
15 /**
16 * @expectedException \Symfony\Component\Console\Exception\RuntimeException
17 * @expectedExceptionMessage Not enough arguments
18 */
19 public function testRunShowUserCommandWithoutUsername()
20 {
21 $application = new Application($this->getClient()->getKernel());
22 $application->add(new ShowUserCommand());
23
24 $command = $application->find('wallabag:user:show');
25
26 $tester = new CommandTester($command);
27 $tester->execute([
28 'command' => $command->getName(),
29 ]);
30 }
31
32 public function testRunShowUserCommandWithBadUsername()
33 {
34 $application = new Application($this->getClient()->getKernel());
35 $application->add(new ShowUserCommand());
36
37 $command = $application->find('wallabag:user:show');
38
39 $tester = new CommandTester($command);
40 $tester->execute([
41 'command' => $command->getName(),
42 'username' => 'unknown',
43 ]);
44
45 $this->assertContains('User "unknown" not found', $tester->getDisplay());
46 }
47
48 public function testRunShowUserCommandForUser()
49 {
50 $application = new Application($this->getClient()->getKernel());
51 $application->add(new ShowUserCommand());
52
53 $command = $application->find('wallabag:user:show');
54
55 $tester = new CommandTester($command);
56 $tester->execute([
57 'command' => $command->getName(),
58 'username' => 'admin',
59 ]);
60
61 $this->assertContains('Username : admin', $tester->getDisplay());
62 $this->assertContains('Email : bigboss@wallabag.org', $tester->getDisplay());
63 $this->assertContains('Display name : Big boss', $tester->getDisplay());
64 $this->assertContains('2FA activated: no', $tester->getDisplay());
65 }
66
67 public function testShowUser()
68 {
69 $client = $this->getClient();
70 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
71
72 $this->logInAs('admin');
73
74 /** @var User $user */
75 $user = $em->getRepository('WallabagUserBundle:User')->findOneById($this->getLoggedInUserId());
76
77 $user->setName('Bug boss');
78 $em->persist($user);
79
80 $em->flush();
81
82 $application = new Application($this->getClient()->getKernel());
83 $application->add(new ShowUserCommand());
84
85 $command = $application->find('wallabag:user:show');
86
87 $tester = new CommandTester($command);
88 $tester->execute([
89 'command' => $command->getName(),
90 'username' => 'admin',
91 ]);
92
93 $this->assertContains('Display name : Bug boss', $tester->getDisplay());
94 }
95}
diff --git a/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php b/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php
index 9125f8dc..c02f9658 100644
--- a/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php
+++ b/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php
@@ -157,4 +157,29 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase
157 157
158 $this->assertFalse($res, 'Absolute image can not be determined, so it will not be replaced'); 158 $this->assertFalse($res, 'Absolute image can not be determined, so it will not be replaced');
159 } 159 }
160
161 public function testProcessRealImage()
162 {
163 $client = new Client();
164
165 $mock = new Mock([
166 new Response(200, ['content-type' => null], Stream::factory(file_get_contents(__DIR__.'/../fixtures/image-no-content-type.jpg'))),
167 ]);
168
169 $client->getEmitter()->attach($mock);
170
171 $logHandler = new TestHandler();
172 $logger = new Logger('test', array($logHandler));
173
174 $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger);
175
176 $res = $download->processSingleImage(
177 123,
178 'https://cdn.theconversation.com/files/157200/article/width926/gsj2rjp2-1487348607.jpg',
179 'https://theconversation.com/conversation-avec-gerald-bronner-ce-nest-pas-la-post-verite-qui-nous-menace-mais-lextension-de-notre-credulite-73089'
180 );
181
182 $this->assertContains('http://wallabag.io/assets/images/9/b/9b0ead26/', $res, 'Content-Type was empty but data is ok for an image');
183 $this->assertContains('DownloadImages: Checking extension (alternative)', $logHandler->getRecords()[3]['message']);
184 }
160} 185}
diff --git a/tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpg b/tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpg
new file mode 100644
index 00000000..0c60e952
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpg
Binary files differ