]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
Merge pull request #3093 from aaa2000/annotation-error-on-save
authorNicolas Lœuillet <nicolas@loeuillet.org>
Wed, 7 Jun 2017 14:30:27 +0000 (16:30 +0200)
committerGitHub <noreply@github.com>
Wed, 7 Jun 2017 14:30:27 +0000 (16:30 +0200)
Displays an error with an annotation with a too long quote

33 files changed:
.github/ISSUE_TEMPLATE.md
app/DoctrineMigrations/Version20170602075214.php [new file with mode: 0644]
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml
app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml
app/config/config.yml
app/config/security.yml
app/config/wallabag.yml [new file with mode: 0644]
src/Wallabag/ApiBundle/Controller/EntryRestController.php
src/Wallabag/ApiBundle/Controller/UserRestController.php
src/Wallabag/CoreBundle/Command/InstallCommand.php
src/Wallabag/CoreBundle/Command/ShowUserCommand.php [new file with mode: 0644]
src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php
src/Wallabag/CoreBundle/DependencyInjection/Configuration.php
src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php
src/Wallabag/CoreBundle/Helper/ContentProxy.php
src/Wallabag/CoreBundle/Helper/DownloadImages.php
src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php
tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php [new file with mode: 0644]
tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php
tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpg [new file with mode: 0644]

index 38bf2df8dcf96848505e1b5d4aa3d9239101a119..968544607a615bf370e6bf5a3a7c2f7b676d70ff 100644 (file)
@@ -1,4 +1,4 @@
-: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
+: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
 
 ### Issue details
 
diff --git a/app/DoctrineMigrations/Version20170602075214.php b/app/DoctrineMigrations/Version20170602075214.php
new file mode 100644 (file)
index 0000000..451d16b
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+
+namespace Application\Migrations;
+
+use Doctrine\DBAL\Migrations\AbstractMigration;
+use Doctrine\DBAL\Schema\Schema;
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Add api_user_registration in craue_config_setting.
+ */
+class Version20170602075214 extends AbstractMigration implements ContainerAwareInterface
+{
+    /**
+     * @var ContainerInterface
+     */
+    private $container;
+
+    public function setContainer(ContainerInterface $container = null)
+    {
+        $this->container = $container;
+    }
+
+    private function getTable($tableName)
+    {
+        return $this->container->getParameter('database_table_prefix').$tableName;
+    }
+
+    /**
+     * @param Schema $schema
+     */
+    public function up(Schema $schema)
+    {
+        $apiUserRegistration = $this->container
+            ->get('doctrine.orm.default_entity_manager')
+            ->getConnection()
+            ->fetchArray('SELECT * FROM '.$this->getTable('craue_config_setting')." WHERE name = 'api_user_registration'");
+
+        $this->skipIf(false !== $apiUserRegistration, 'It seems that you already played this migration.');
+
+        $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('api_user_registration', '0', 'api')");
+    }
+
+    /**
+     * @param Schema $schema
+     */
+    public function down(Schema $schema)
+    {
+        $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'api_user_registration';");
+    }
+}
index d1f7e3b5e6442e35f747b0f0218a47128d8337a9..20e938f5a007c90a3f45599aaaa6a779fb4d4716 100644 (file)
@@ -34,3 +34,4 @@ demo_mode_username: "Demobruger"
 # share_public: Allow public url for entries
 # download_images_enabled: Download images locally
 # restricted_access: Enable authentication for websites with paywall
+# api_user_registration: Enable user to be registered using the API
index 1105675bd94632d25055c417042ad867f0f1d174..526d41bc59dbd6492aed550913231b6d2fc8aafd 100644 (file)
@@ -34,3 +34,4 @@ demo_mode_username: "Test-Benutzer"
 share_public: Erlaube eine öffentliche URL für Einträge
 # download_images_enabled: Download images locally
 # restricted_access: Enable authentication for websites with paywall
+# api_user_registration: Enable user to be registered using the API
index 802599b3ec5edf064c3ceef393fc8b1fb813b8f5..3c0037f38d749558af8280f6a953a60f3bd1c624 100644 (file)
@@ -34,3 +34,4 @@ demo_mode_username: "Demo user"
 share_public: Allow public url for entries
 download_images_enabled: Download images locally
 restricted_access: Enable authentication for websites with paywall
+api_user_registration: Enable user to be registered using the API
index b3ac18ed3cd32cb7bd45ad27f269050977b86b93..9986966906486ba11d6dcdda59a95a755411c96f 100644 (file)
@@ -34,3 +34,4 @@ demo_mode_username: "Nombre de usuario demo"
 share_public: Permitir URL pública para los artículos
 download_images_enabled: Descargar imágenes localmente
 restricted_access: Activar autenticación para websites con paywall
+# api_user_registration: Enable user to be registered using the API
index c73d63e233cffc178cbb9ca3029b4478786dc67d..2e1307e58886b75b14c95da4658f2a5b4755565d 100644 (file)
@@ -34,3 +34,4 @@ modify_settings: "اعمال"
 # share_public: Allow public url for entries
 # download_images_enabled: Download images locally
 # restricted_access: Enable authentication for websites with paywall
+# api_user_registration: Enable user to be registered using the API
index a53174ae5ddd3f2326f035cbdc37adde7e408923..454053ad2352db23038e7d3ed7b2690205c961c8 100644 (file)
@@ -34,3 +34,4 @@ demo_mode_username: "Utilisateur de la démo"
 share_public: Autoriser une URL publique pour les articles
 download_images_enabled: Télécharger les images en local
 restricted_access: Activer l'authentification pour les articles derrière un paywall
+api_user_registration: Activer la création de compte depuis l'API
index 3d53fc8d1358b50e0454aebab90de1368616927f..4dbd2ff8e195ed1366a885af61ebbf6eb3d9a94c 100644 (file)
@@ -34,3 +34,4 @@ demo_mode_username: "Utente Demo"
 # share_public: Allow public url for entries
 # download_images_enabled: Download images locally
 # restricted_access: Enable authentication for websites with paywall
+api_user_registration: Abilita la registrazione dell'utente attraverso l'API
index 79f75245a0a7c4df8d268a00208cd8eaaf366977..00c06638da81afb097aec8fe5b37dce39fee8a5c 100644 (file)
@@ -34,3 +34,4 @@ demo_mode_username: "Utilizaire de la demostracion"
 share_public: Autorizar una URL publica pels articles
 download_images_enabled: Telecargar los imatges en local
 restricted_access: Activar l'autenticacion pels sites amb peatge
+# api_user_registration: Enable user to be registered using the API
index 02fe98e30ad358416843f8aa9deb2c7038cc4006..ada11b3aa7585d9245f6b909539980e27d154997 100644 (file)
@@ -34,3 +34,4 @@ demo_mode_username: "Użytkownik Demonstracyjny"
 share_public: Zezwalaj na publiczny adres url dla wpisow
 download_images_enabled: Pobierz obrazy lokalnie
 restricted_access: Włącz autoryzację dla stron z paywallem
+api_user_registration: Włącz rejestrację użytkownika przy użyciu API
index 4a061bce74e2838c41e601e8dae55efc5f61f5ec..59af9610539b772c7f57745e9f940eedd85e9f65 100644 (file)
@@ -34,3 +34,4 @@ demo_mode_username: "Usuário demo"
 # share_public: Allow public url for entries
 # download_images_enabled: Download images locally
 # restricted_access: Enable authentication for websites with paywall
+# api_user_registration: Enable user to be registered using the API
index 5ee48074ba247c76c00f1fb823ab3c3359579869..104e37c6ade9654d27384705f3e939c0981a21fb 100644 (file)
@@ -34,3 +34,4 @@ modify_settings: "aplică"
 # share_public: Allow public url for entries
 # download_images_enabled: Download images locally
 # restricted_access: Enable authentication for websites with paywall
+# api_user_registration: Enable user to be registered using the API
index d83a4b7b66dd2113ad9febf4013167e25705701a..1579366d2ed609e7e11ae29cf111b03144fdc95d 100644 (file)
@@ -34,3 +34,4 @@
 # share_public: Allow public url for entries
 # download_images_enabled: Download images locally
 # restricted_access: Enable authentication for websites with paywall
+# api_user_registration: Enable user to be registered using the API
index 04f8547dea49dfc953142cb0228908d05ca5cf0a..2bc5e3b359292de4e5ff477d2fc976b81ab484f0 100644 (file)
@@ -2,6 +2,7 @@ imports:
     - { resource: parameters.yml }
     - { resource: security.yml }
     - { resource: services.yml }
+    - { resource: wallabag.yml }
 
 parameters:
     # Allows to use the live reload feature for changes in assets
@@ -34,42 +35,6 @@ framework:
     http_method_override: true
     assets: ~
 
-wallabag_core:
-    version: 2.2.3
-    paypal_url: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9UBA65LG3FX9Y&lc=gb"
-    languages:
-        en: 'English'
-        fr: 'Français'
-        de: 'Deutsch'
-        tr: 'Türkçe'
-        fa: 'فارسی'
-        ro: 'Română'
-        pl: 'Polish'
-        da: 'Dansk'
-        es: 'Español'
-        oc: 'Occitan'
-        it: 'Italiano'
-        pt: 'Português'
-    items_on_page: 12
-    theme: material
-    language: '%locale%'
-    rss_limit: 50
-    reading_speed: 1
-    cache_lifetime: 10
-    action_mark_as_read: 1
-    list_mode: 0
-    fetching_error_message_title: 'No title found'
-    fetching_error_message: |
-        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>.
-    api_limit_mass_actions: 10
-
-wallabag_user:
-    registration_enabled: "%fosuser_registration%"
-
-wallabag_import:
-    allow_mimetypes: ['application/octet-stream', 'application/json', 'text/plain', 'text/csv']
-    resource_dir: "%kernel.root_dir%/../web/uploads/import"
-
 # Twig Configuration
 twig:
     debug: "%kernel.debug%"
index efb00a5348135d7ad16f94ec3760f0a7771564d7..ffb1d356fd29d8b081a78a088c47afc04176ba49 100644 (file)
@@ -56,6 +56,7 @@ security:
     access_control:
         - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY }
         - { path: ^/api/version, roles: IS_AUTHENTICATED_ANONYMOUSLY }
+        - { path: ^/api/user, roles: IS_AUTHENTICATED_ANONYMOUSLY }
         - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
         - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
         - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
diff --git a/app/config/wallabag.yml b/app/config/wallabag.yml
new file mode 100644 (file)
index 0000000..d8c593c
--- /dev/null
@@ -0,0 +1,164 @@
+wallabag_core:
+    version: 2.2.3
+    paypal_url: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9UBA65LG3FX9Y&lc=gb"
+    languages:
+        en: 'English'
+        fr: 'Français'
+        de: 'Deutsch'
+        tr: 'Türkçe'
+        fa: 'فارسی'
+        ro: 'Română'
+        pl: 'Polish'
+        da: 'Dansk'
+        es: 'Español'
+        oc: 'Occitan'
+        it: 'Italiano'
+        pt: 'Português'
+    items_on_page: 12
+    theme: material
+    language: '%locale%'
+    rss_limit: 50
+    reading_speed: 1
+    cache_lifetime: 10
+    action_mark_as_read: 1
+    list_mode: 0
+    fetching_error_message_title: 'No title found'
+    fetching_error_message: |
+        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>.
+    api_limit_mass_actions: 10
+    default_internal_settings:
+        -
+            name: share_public
+            value: 1
+            section: entry
+        -
+            name: carrot
+            value: 1
+            section: entry
+        -
+            name: share_diaspora
+            value: 1
+            section: entry
+        -
+            name: diaspora_url
+            value: http://diasporapod.com
+            section: entry
+        -
+            name: share_unmark
+            value: 1
+            section: entry
+        -
+            name: unmark_url
+            value: https://unmark.it
+            section: entry
+        -
+            name: share_shaarli
+            value: 1
+            section: entry
+        -
+            name: share_scuttle
+            value: 1
+            section: entry
+        -
+            name: shaarli_url
+            value: http://myshaarli.com
+            section: entry
+        -
+            name: scuttle_url
+            value: http://scuttle.org
+            section: entry
+        -
+            name: share_mail
+            value: 1
+            section: entry
+        -
+            name: share_twitter
+            value: 1
+            section: entry
+        -
+            name: show_printlink
+            value: 1
+            section: entry
+        -
+            name: restricted_access
+            value: 0
+            section: entry
+        -
+            name: export_epub
+            value: 1
+            section: export
+        -
+            name: export_mobi
+            value: 1
+            section: export
+        -
+            name: export_pdf
+            value: 1
+            section: export
+        -
+            name: export_csv
+            value: 1
+            section: export
+        -
+            name: export_json
+            value: 1
+            section: export
+        -
+            name: export_txt
+            value: 1
+            section: export
+        -
+            name: export_xml
+            value: 1
+            section: export
+        -
+            name: import_with_redis
+            value: 0
+            section: import
+        -
+            name: import_with_rabbitmq
+            value: 0
+            section: import
+        -
+            name: piwik_enabled
+            value: 0
+            section: analytics
+        -
+            name: piwik_host
+            value: v2.wallabag.org
+            section: analytics
+        -
+            name: piwik_site_id
+            value: 1
+            section: analytics
+        -
+            name: demo_mode_enabled
+            value: 0
+            section: misc
+        -
+            name: demo_mode_username
+            value: wallabag
+            section: misc
+        -
+            name: download_images_enabled
+            value: 0
+            section: misc
+        -
+            name: wallabag_support_url
+            value: https://www.wallabag.org/pages/support.html
+            section: misc
+        -
+            name: wallabag_url
+            value: http://v2.wallabag.org
+            section: misc
+        -
+            name: api_user_registration
+            value: 0
+            section: api
+
+wallabag_user:
+    registration_enabled: "%fosuser_registration%"
+
+wallabag_import:
+    allow_mimetypes: ['application/octet-stream', 'application/json', 'text/plain', 'text/csv']
+    resource_dir: "%kernel.root_dir%/../web/uploads/import"
index 93c8157e758a934905663846516fccc27b46e50b..09b73ccb4edb81c6393c9fa085f77726e1cf8ba7 100644 (file)
@@ -299,65 +299,18 @@ class EntryRestController extends WallabagRestController
         $this->validateAuthentication();
 
         $url = $request->request->get('url');
-        $title = $request->request->get('title');
-        $tags = $request->request->get('tags', []);
-        $isArchived = $request->request->get('archive');
-        $isStarred = $request->request->get('starred');
-        $content = $request->request->get('content');
-        $language = $request->request->get('language');
-        $picture = $request->request->get('preview_picture');
-        $publishedAt = $request->request->get('published_at');
-        $authors = $request->request->get('authors', '');
 
-        $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId());
+        $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId(
+            $url,
+            $this->getUser()->getId()
+        );
 
         if (false === $entry) {
             $entry = new Entry($this->getUser());
-        }
-
-        try {
-            $this->get('wallabag_core.content_proxy')->updateEntry(
-                $entry,
-                $url,
-                [
-                    'title' => $title,
-                    'html' => $content,
-                    'url' => $url,
-                    'language' => $language,
-                    'date' => $publishedAt,
-                    // faking the preview picture
-                    'open_graph' => [
-                        'og_image' => $picture,
-                    ],
-                    'authors' => explode(',', $authors),
-                ]
-            );
-        } catch (\Exception $e) {
-            $this->get('logger')->error('Error while saving an entry', [
-                'exception' => $e,
-                'entry' => $entry,
-            ]);
             $entry->setUrl($url);
         }
 
-        if (!empty($tags)) {
-            $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags);
-        }
-
-        if (!is_null($isStarred)) {
-            $entry->setStarred((bool) $isStarred);
-        }
-
-        if (!is_null($isArchived)) {
-            $entry->setArchived((bool) $isArchived);
-        }
-
-        $em = $this->getDoctrine()->getManager();
-        $em->persist($entry);
-        $em->flush();
-
-        // entry saved, dispatch event about it!
-        $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
+        $this->upsertEntry($entry, $request);
 
         return $this->sendResponse($entry);
     }
@@ -374,6 +327,11 @@ class EntryRestController extends WallabagRestController
      *          {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
      *          {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="archived the entry."},
      *          {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="starred the entry."},
+     *          {"name"="content", "dataType"="string", "required"=false, "description"="Content of the entry"},
+     *          {"name"="language", "dataType"="string", "required"=false, "description"="Language of the entry"},
+     *          {"name"="preview_picture", "dataType"="string", "required"=false, "description"="Preview picture of the entry"},
+     *          {"name"="published_at", "dataType"="datetime|integer", "format"="YYYY-MM-DDTHH:II:SS+TZ or a timestamp", "required"=false, "description"="Published date of the entry"},
+     *          {"name"="authors", "dataType"="string", "format"="Name Firstname,author2,author3", "required"=false, "description"="Authors of the entry"},
      *      }
      * )
      *
@@ -384,29 +342,7 @@ class EntryRestController extends WallabagRestController
         $this->validateAuthentication();
         $this->validateUserAccess($entry->getUser()->getId());
 
-        $title = $request->request->get('title');
-        $isArchived = $request->request->get('archive');
-        $isStarred = $request->request->get('starred');
-
-        if (!is_null($title)) {
-            $entry->setTitle($title);
-        }
-
-        if (!is_null($isArchived)) {
-            $entry->setArchived((bool) $isArchived);
-        }
-
-        if (!is_null($isStarred)) {
-            $entry->setStarred((bool) $isStarred);
-        }
-
-        $tags = $request->request->get('tags', '');
-        if (!empty($tags)) {
-            $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags);
-        }
-
-        $em = $this->getDoctrine()->getManager();
-        $em->flush();
+        $this->upsertEntry($entry, $request, true);
 
         return $this->sendResponse($entry);
     }
@@ -673,4 +609,68 @@ class EntryRestController extends WallabagRestController
 
         return (new JsonResponse())->setJson($json);
     }
+
+    /**
+     * Update or Insert a new entry.
+     *
+     * @param Entry   $entry
+     * @param Request $request
+     * @param bool    $disableContentUpdate If we don't want the content to be update by fetching the url (used when patching instead of posting)
+     */
+    private function upsertEntry(Entry $entry, Request $request, $disableContentUpdate = false)
+    {
+        $title = $request->request->get('title');
+        $tags = $request->request->get('tags', []);
+        $isArchived = $request->request->get('archive');
+        $isStarred = $request->request->get('starred');
+        $content = $request->request->get('content');
+        $language = $request->request->get('language');
+        $picture = $request->request->get('preview_picture');
+        $publishedAt = $request->request->get('published_at');
+        $authors = $request->request->get('authors', '');
+
+        try {
+            $this->get('wallabag_core.content_proxy')->updateEntry(
+                $entry,
+                $entry->getUrl(),
+                [
+                    'title' => !empty($title) ? $title : $entry->getTitle(),
+                    'html' => !empty($content) ? $content : $entry->getContent(),
+                    'url' => $entry->getUrl(),
+                    'language' => !empty($language) ? $language : $entry->getLanguage(),
+                    'date' => !empty($publishedAt) ? $publishedAt : $entry->getPublishedAt(),
+                    // faking the open graph preview picture
+                    'open_graph' => [
+                        'og_image' => !empty($picture) ? $picture : $entry->getPreviewPicture(),
+                    ],
+                    'authors' => is_string($authors) ? explode(',', $authors) : $entry->getPublishedBy(),
+                ],
+                $disableContentUpdate
+            );
+        } catch (\Exception $e) {
+            $this->get('logger')->error('Error while saving an entry', [
+                'exception' => $e,
+                'entry' => $entry,
+            ]);
+        }
+
+        if (!is_null($isArchived)) {
+            $entry->setArchived((bool) $isArchived);
+        }
+
+        if (!is_null($isStarred)) {
+            $entry->setStarred((bool) $isStarred);
+        }
+
+        if (!empty($tags)) {
+            $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags);
+        }
+
+        $em = $this->getDoctrine()->getManager();
+        $em->persist($entry);
+        $em->flush();
+
+        // entry saved, dispatch event about it!
+        $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
+    }
 }
index a1b78e3ff932a97cf8586738377fb59516d19550..8f675b8df9431c93f64ef23fc45319c3f23e5f19 100644 (file)
@@ -43,16 +43,18 @@ class UserRestController extends WallabagRestController
      */
     public function putUserAction(Request $request)
     {
-        if (!$this->container->getParameter('fosuser_registration')) {
+        if (!$this->getParameter('fosuser_registration') || !$this->get('craue_config')->get('api_user_registration')) {
             $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json');
 
-            return (new JsonResponse())->setJson($json)->setStatusCode(403);
+            return (new JsonResponse())
+                ->setJson($json)
+                ->setStatusCode(JsonResponse::HTTP_FORBIDDEN);
         }
 
         $userManager = $this->get('fos_user.user_manager');
         $user = $userManager->createUser();
-        // enable created user by default
-        $user->setEnabled(true);
+        // user will be disabled BY DEFAULT to avoid spamming account to be enabled
+        $user->setEnabled(false);
 
         $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [
             'csrf_protection' => false,
@@ -90,7 +92,9 @@ class UserRestController extends WallabagRestController
 
             $json = $this->get('serializer')->serialize(['error' => $errors], 'json');
 
-            return (new JsonResponse())->setJson($json)->setStatusCode(400);
+            return (new JsonResponse())
+                ->setJson($json)
+                ->setStatusCode(JsonResponse::HTTP_BAD_REQUEST);
         }
 
         $userManager->updateUser($user);
@@ -99,17 +103,18 @@ class UserRestController extends WallabagRestController
         $event = new UserEvent($user, $request);
         $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event);
 
-        return $this->sendUser($user);
+        return $this->sendUser($user, JsonResponse::HTTP_CREATED);
     }
 
     /**
      * Send user response.
      *
      * @param User $user
+     * @param int  $status HTTP Status code to send
      *
      * @return JsonResponse
      */
-    private function sendUser(User $user)
+    private function sendUser(User $user, $status = JsonResponse::HTTP_OK)
     {
         $json = $this->get('serializer')->serialize(
             $user,
@@ -117,7 +122,9 @@ class UserRestController extends WallabagRestController
             SerializationContext::create()->setGroups(['user_api'])
         );
 
-        return (new JsonResponse())->setJson($json);
+        return (new JsonResponse())
+            ->setJson($json)
+            ->setStatusCode($status);
     }
 
     /**
index d9608246e47da188e496a5b7b6874987010cdc39..0f119377fe54d041a73e8df2ec4407628c28695d 100644 (file)
@@ -292,165 +292,7 @@ class InstallCommand extends ContainerAwareCommand
         // cleanup before insert new stuff
         $em->createQuery('DELETE FROM CraueConfigBundle:Setting')->execute();
 
-        $settings = [
-            [
-                'name' => 'share_public',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'carrot',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_diaspora',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'diaspora_url',
-                'value' => 'http://diasporapod.com',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_unmark',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'unmark_url',
-                'value' => 'https://unmark.it',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_shaarli',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'shaarli_url',
-                'value' => 'http://myshaarli.com',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_scuttle',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'scuttle_url',
-                'value' => 'http://scuttle.org',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_mail',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_twitter',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'export_epub',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_mobi',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_pdf',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_csv',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_json',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_txt',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_xml',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'import_with_redis',
-                'value' => '0',
-                'section' => 'import',
-            ],
-            [
-                'name' => 'import_with_rabbitmq',
-                'value' => '0',
-                'section' => 'import',
-            ],
-            [
-                'name' => 'show_printlink',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'wallabag_support_url',
-                'value' => 'https://www.wallabag.org/pages/support.html',
-                'section' => 'misc',
-            ],
-            [
-                'name' => 'wallabag_url',
-                'value' => '',
-                'section' => 'misc',
-            ],
-            [
-                'name' => 'piwik_enabled',
-                'value' => '0',
-                'section' => 'analytics',
-            ],
-            [
-                'name' => 'piwik_host',
-                'value' => 'v2.wallabag.org',
-                'section' => 'analytics',
-            ],
-            [
-                'name' => 'piwik_site_id',
-                'value' => '1',
-                'section' => 'analytics',
-            ],
-            [
-                'name' => 'demo_mode_enabled',
-                'value' => '0',
-                'section' => 'misc',
-            ],
-            [
-                'name' => 'demo_mode_username',
-                'value' => 'wallabag',
-                'section' => 'misc',
-            ],
-            [
-                'name' => 'download_images_enabled',
-                'value' => '0',
-                'section' => 'misc',
-            ],
-            [
-                'name' => 'restricted_access',
-                'value' => '0',
-                'section' => 'entry',
-            ],
-        ];
-
-        foreach ($settings as $setting) {
+        foreach ($this->getContainer()->getParameter('wallabag_core.default_internal_settings') as $setting) {
             $newSetting = new Setting();
             $newSetting->setName($setting['name']);
             $newSetting->setValue($setting['value']);
diff --git a/src/Wallabag/CoreBundle/Command/ShowUserCommand.php b/src/Wallabag/CoreBundle/Command/ShowUserCommand.php
new file mode 100644 (file)
index 0000000..0eeaabc
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+
+namespace Wallabag\CoreBundle\Command;
+
+use Doctrine\ORM\NoResultException;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Wallabag\UserBundle\Entity\User;
+
+class ShowUserCommand extends ContainerAwareCommand
+{
+    /** @var OutputInterface */
+    protected $output;
+
+    protected function configure()
+    {
+        $this
+            ->setName('wallabag:user:show')
+            ->setDescription('Show user details')
+            ->setHelp('This command shows the details for an user')
+            ->addArgument(
+                'username',
+                InputArgument::REQUIRED,
+                'User to show details for'
+            );
+    }
+
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $this->output = $output;
+
+        $username = $input->getArgument('username');
+
+        try {
+            $user = $this->getUser($username);
+            $this->showUser($user);
+        } catch (NoResultException $e) {
+            $output->writeln(sprintf('<error>User "%s" not found.</error>', $username));
+
+            return 1;
+        }
+
+        return 0;
+    }
+
+    /**
+     * @param User $user
+     */
+    private function showUser(User $user)
+    {
+        $this->output->writeln(sprintf('Username : %s', $user->getUsername()));
+        $this->output->writeln(sprintf('Email : %s', $user->getEmail()));
+        $this->output->writeln(sprintf('Display name : %s', $user->getName()));
+        $this->output->writeln(sprintf('Creation date : %s', $user->getCreatedAt()->format('Y-m-d H:i:s')));
+        $this->output->writeln(sprintf('Last login : %s', $user->getLastLogin() !== null ? $user->getLastLogin()->format('Y-m-d H:i:s') : 'never'));
+        $this->output->writeln(sprintf('2FA activated: %s', $user->isTwoFactorAuthentication() ? 'yes' : 'no'));
+    }
+
+    /**
+     * Fetches a user from its username.
+     *
+     * @param string $username
+     *
+     * @return \Wallabag\UserBundle\Entity\User
+     */
+    private function getUser($username)
+    {
+        return $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($username);
+    }
+
+    private function getDoctrine()
+    {
+        return $this->getContainer()->get('doctrine');
+    }
+}
index aaeb9ee99cad5a6853e6f150623f2081dacc4e81..a52288e6f5fec79f7e20ec3792b15b005319bf02 100644 (file)
@@ -6,173 +6,27 @@ use Doctrine\Common\DataFixtures\AbstractFixture;
 use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
 use Doctrine\Common\Persistence\ObjectManager;
 use Craue\ConfigBundle\Entity\Setting;
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
-class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface
+class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
 {
+    /**
+     * @var ContainerInterface
+     */
+    private $container;
+
+    public function setContainer(ContainerInterface $container = null)
+    {
+        $this->container = $container;
+    }
+
     /**
      * {@inheritdoc}
      */
     public function load(ObjectManager $manager)
     {
-        $settings = [
-            [
-                'name' => 'share_public',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'carrot',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_diaspora',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'diaspora_url',
-                'value' => 'http://diasporapod.com',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_unmark',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'unmark_url',
-                'value' => 'https://unmark.it',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_shaarli',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_scuttle',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'shaarli_url',
-                'value' => 'http://myshaarli.com',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'scuttle_url',
-                'value' => 'http://scuttle.org',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_mail',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'share_twitter',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'export_epub',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_mobi',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_pdf',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_csv',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_json',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_txt',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'export_xml',
-                'value' => '1',
-                'section' => 'export',
-            ],
-            [
-                'name' => 'import_with_redis',
-                'value' => '0',
-                'section' => 'import',
-            ],
-            [
-                'name' => 'import_with_rabbitmq',
-                'value' => '0',
-                'section' => 'import',
-            ],
-            [
-                'name' => 'show_printlink',
-                'value' => '1',
-                'section' => 'entry',
-            ],
-            [
-                'name' => 'wallabag_support_url',
-                'value' => 'https://www.wallabag.org/pages/support.html',
-                'section' => 'misc',
-            ],
-            [
-                'name' => 'wallabag_url',
-                'value' => 'http://v2.wallabag.org',
-                'section' => 'misc',
-            ],
-            [
-                'name' => 'piwik_enabled',
-                'value' => '0',
-                'section' => 'analytics',
-            ],
-            [
-                'name' => 'piwik_host',
-                'value' => 'v2.wallabag.org',
-                'section' => 'analytics',
-            ],
-            [
-                'name' => 'piwik_site_id',
-                'value' => '1',
-                'section' => 'analytics',
-            ],
-            [
-                'name' => 'demo_mode_enabled',
-                'value' => '0',
-                'section' => 'misc',
-            ],
-            [
-                'name' => 'demo_mode_username',
-                'value' => 'wallabag',
-                'section' => 'misc',
-            ],
-            [
-                'name' => 'download_images_enabled',
-                'value' => '0',
-                'section' => 'misc',
-            ],
-            [
-                'name' => 'restricted_access',
-                'value' => '0',
-                'section' => 'entry',
-            ],
-        ];
-
-        foreach ($settings as $setting) {
+        foreach ($this->container->getParameter('wallabag_core.default_internal_settings') as $setting) {
             $newSetting = new Setting();
             $newSetting->setName($setting['name']);
             $newSetting->setValue($setting['value']);
index 8b5b57442d358d055f203e87e3fa94c94b932521..33df92d3c8dc202671951d04e1f66ec9cb9b258f 100644 (file)
@@ -52,6 +52,17 @@ class Configuration implements ConfigurationInterface
                 ->scalarNode('api_limit_mass_actions')
                     ->defaultValue(10)
                 ->end()
+                ->arrayNode('default_internal_settings')
+                    ->prototype('array')
+                        ->children()
+                            ->scalarNode('name')->end()
+                            ->scalarNode('value')->end()
+                            ->enumNode('section')
+                                ->values(['entry', 'misc', 'api', 'analytics', 'export', 'import'])
+                            ->end()
+                        ->end()
+                    ->end()
+                ->end()
             ->end()
         ;
 
index a2a703cb6c40a910abfe1ea99ca0dd9a57fc4616..b4d8a3866a59db84a4b993c59a4498c3fb9957f4 100644 (file)
@@ -28,6 +28,7 @@ class WallabagCoreExtension extends Extension
         $container->setParameter('wallabag_core.fetching_error_message', $config['fetching_error_message']);
         $container->setParameter('wallabag_core.fetching_error_message_title', $config['fetching_error_message_title']);
         $container->setParameter('wallabag_core.api_limit_mass_actions', $config['api_limit_mass_actions']);
+        $container->setParameter('wallabag_core.default_internal_settings', $config['default_internal_settings']);
 
         $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
         $loader->load('services.yml');
index bfaa197695941af57dde87e751f95d1a1d0cc30c..d5820e6633e2250f1a53c7554046f5fc238a781f 100644 (file)
@@ -105,7 +105,7 @@ class ContentProxy
             }
         }
 
-        if (!empty($content['authors'])) {
+        if (!empty($content['authors']) && is_array($content['authors'])) {
             $entry->setPublishedBy($content['authors']);
         }
 
index 54e23a052684bc87c3508fd2dbc632d15294c891..ed888cdb031ae52afd2b6624378c7927a0366e4d 100644 (file)
@@ -5,6 +5,7 @@ namespace Wallabag\CoreBundle\Helper;
 use Psr\Log\LoggerInterface;
 use Symfony\Component\DomCrawler\Crawler;
 use GuzzleHttp\Client;
+use GuzzleHttp\Message\Response;
 use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser;
 use Symfony\Component\Finder\Finder;
 
@@ -116,13 +117,11 @@ class DownloadImages
             return false;
         }
 
-        $ext = $this->mimeGuesser->guess($res->getHeader('content-type'));
-        $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]);
-        if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) {
-            $this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping: '.$imagePath);
-
+        $ext = $this->getExtensionFromResponse($res, $imagePath);
+        if (false === $res) {
             return false;
         }
+
         $hashImage = hash('crc32', $absolutePath);
         $localPath = $folderPath.'/'.$hashImage.'.'.$ext;
 
@@ -237,4 +236,45 @@ class DownloadImages
 
         return false;
     }
+
+    /**
+     * Retrieve and validate the extension from the response of the url of the image.
+     *
+     * @param Response $res       Guzzle Response
+     * @param string   $imagePath Path from the src image from the content (used for log only)
+     *
+     * @return string|false Extension name or false if validation failed
+     */
+    private function getExtensionFromResponse(Response $res, $imagePath)
+    {
+        $ext = $this->mimeGuesser->guess($res->getHeader('content-type'));
+        $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]);
+
+        // ok header doesn't have the extension, try a different way
+        if (empty($ext)) {
+            $types = [
+                'jpeg' => "\xFF\xD8\xFF",
+                'gif' => 'GIF',
+                'png' => "\x89\x50\x4e\x47\x0d\x0a",
+            ];
+            $bytes = substr((string) $res->getBody(), 0, 8);
+
+            foreach ($types as $type => $header) {
+                if (0 === strpos($bytes, $header)) {
+                    $ext = $type;
+                    break;
+                }
+            }
+
+            $this->logger->debug('DownloadImages: Checking extension (alternative)', ['ext' => $ext]);
+        }
+
+        if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) {
+            $this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping: '.$imagePath);
+
+            return false;
+        }
+
+        return $ext;
+    }
 }
index 70e9575a158d172e463fa05fe4299a0413826218..16e8072b4465f58f6ff07a059e29efec3ad3f861 100644 (file)
@@ -24,7 +24,7 @@ menu:
         tags: 'Tags'
         internal_settings: 'Strumenti'
         import: 'Importa'
-        howto: 'How to'
+        howto: 'Come fare'
         # developer: 'API clients management'
         logout: 'Logout'
         about: 'About'
@@ -44,8 +44,8 @@ footer:
     wallabag:
         elsewhere: 'Porta wallabag con te'
         social: 'Social'
-        powered_by: 'powered by'
-        about: 'About'
+        powered_by: 'Offerto da'
+        about: 'A proposito'
     # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
@@ -55,7 +55,7 @@ config:
         rss: 'RSS'
         user_info: 'Informazioni utente'
         password: 'Password'
-        rules: 'Regole di tagging'
+        rules: 'Regole di etichettatura'
         new_user: 'Aggiungi utente'
     form:
         save: 'Salva'
@@ -83,7 +83,7 @@ config:
         # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account."
     form_rss:
         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.'
-        token_label: 'RSS token'
+        token_label: 'Token RSS'
         no_token: 'Nessun token'
         token_create: 'Crea il tuo token'
         token_reset: 'Rigenera il tuo token'
@@ -94,10 +94,10 @@ config:
             archive: 'archiviati'
         rss_limit: 'Numero di elementi nel feed'
     form_user:
-        two_factor_description: "Abilitando la two factor authentication riceverai una e-mail con un codice per ogni nuova connesione non verificata"
+        two_factor_description: "Abilitando l'\autenticazione a due fattori riceverai una e-mail con un codice per ogni nuova connesione non verificata"
         name_label: 'Nome'
         email_label: 'E-mail'
-        twoFactorAuthentication_label: 'Two factor authentication'
+        twoFactorAuthentication_label: 'Autenticazione a due fattori'
         # help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
         delete:
             # title: Delete my account (a.k.a danger zone)
@@ -119,19 +119,19 @@ config:
         repeat_new_password_label: 'Ripeti la nuova password'
     form_rules:
         if_label: 'se'
-        then_tag_as_label: 'allora tagga come'
+        then_tag_as_label: 'allora etichetta come'
         delete_rule_label: 'elimina'
         # edit_rule_label: 'edit'
         rule_label: 'Regola'
-        tags_label: 'Tag'
+        tags_label: 'Etichetta'
         faq:
             title: 'FAQ'
-            tagging_rules_definition_title: 'Cosa significa « regole di tagging » ?'
-            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.'
+            tagging_rules_definition_title: 'Cosa significa « regole di etichettatura» ?'
+            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.'
             how_to_use_them_title: 'Come si usano?'
-            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> »'
+            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> »'
             variables_available_title: 'Quali operatori e variabili posso utilizzare per scrivere delle regole?'
-            variables_available_description: 'I seguenti operatori e variabili posso essere utilizzati per scrivere regole di tagging:'
+            variables_available_description: 'I seguenti operatori e variabili posso essere utilizzati per scrivere regole di etichettatura:'
             meaning: 'Significato'
             variable_description:
                 label: 'Variabile'
@@ -211,7 +211,7 @@ entry:
             view_original_article: 'Contenuto originale'
             re_fetch_content: 'Ri-ottieni pagina'
             delete: 'Elimina'
-            add_a_tag: 'Aggiungi un tag'
+            add_a_tag: 'Aggiungi un''etichetta'
             share_content: 'Condividi'
             share_email_label: 'E-mail'
             # public_link: 'public link'
@@ -222,7 +222,7 @@ entry:
                 label: 'Problemi?'
                 description: 'Questo contenuto viene visualizzato male?'
         edit_title: 'Modifica titolo'
-        original_article: 'originale'
+        original_article: 'Originale'
         annotations_on_the_entry: '{0} Nessuna annotazione|{1} Una annotazione|]1,Inf[ %count% annotazioni'
         created_at: 'Data di creazione'
         # published_at: 'Publication date'
@@ -242,11 +242,11 @@ entry:
     public:
         # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>"
     confirm:
-        # delete: "Are you sure you want to remove that article?"
-        # delete_tag: "Are you sure you want to remove that tag from that article?"
+        delete: "Vuoi veramente rimuovere quell'articolo?"
+        delete_tag: "Vuoi veramente rimuovere quell'etichetta da quell'articolo?"
 
 about:
-    page_title: 'About'
+    page_title: 'A proposito'
     top_menu:
         who_behind_wallabag: "Chi c'è dietro a wallabag"
         getting_help: 'Ottieni aiuto'
@@ -265,7 +265,7 @@ about:
         bug_reports: 'Bug reports'
         support: '<a href="https://github.com/wallabag/wallabag/issues">su GitHub</a>'
     helping:
-        description: 'wallabag è gratuito opensource. Puoi aiutarci:'
+        description: 'wallabag è gratuito ed OpenSource. Puoi aiutarci:'
         by_contributing: 'per contribuire al progetto:'
         by_contributing_2: 'un elenco delle attività richieste'
         by_paypal: 'via Paypal'
@@ -273,7 +273,7 @@ about:
         description: 'Un grazie ai collaboratori di wallabag web application'
     third_party:
         description: 'Ecco un elenco delle librerie di terze parti utilizzate in wallabag (con le rispettive licenze):'
-        package: 'Package'
+        package: 'Pacchetto'
         license: 'Licenza'
 
 howto:
@@ -299,7 +299,7 @@ howto:
         ios: 'sullo store di iTunes'
         windows: 'sullo store di Microsoft'
     bookmarklet:
-        description: 'Trascinando e rilasciando questo link sulla barra dei bookmark del tuo browser:'
+        description: 'Trascinando e rilasciando questo link sulla barra dei preferiti del tuo browser:'
     shortcuts:
         # page_description: Here are the shortcuts available in wallabag.
         # shortcut: Shortcut
@@ -333,7 +333,7 @@ quickstart:
     # more: 'More…'
     intro:
         title: 'Benvenuto su wallabag!'
-        paragraph_1: "Un tour in cui ti guideremo per scoprire e che ti mostrerà delle funzionalità che potrebbero interessarti."
+        paragraph_1: "Ti accompagneremo alla scoperta di wallabag e ti mostreremo delle funzionalità che potrebbero interessarti."
         paragraph_2: 'Seguici!'
     configure:
         title: "Configura l'applicazione"
@@ -383,9 +383,9 @@ quickstart:
         gitter: 'Su Gitter'
 
 tag:
-    page_title: 'Tags'
+    page_title: 'Etichette'
     list:
-        number_on_the_page: "{0} Non ci sono tag.|{1} C'è un tag.|]1,Inf[ ci sono %count% tag."
+        number_on_the_page: "{0} Non ci sono etichette.|{1} C'è un'etichetta.|]1,Inf[ ci sono %count% etichette."
         # see_untagged_entries: 'See untagged entries'
     new:
         # add: 'Add'
@@ -403,20 +403,20 @@ import:
         save_label: 'Carica file'
     pocket:
         page_title: 'Importa da > Pocket'
-        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."
+        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."
         config_missing:
             description: "Importazione da Pocket non configurata."
             admin_message: 'Devi definire %keyurls% una pocket_consumer_key %keyurle%.'
-            user_message: 'Il tuo amministratore di server deve define una API Key per Pocket.'
+            user_message: 'Il tuo amministratore del server deve definire una API Key per Pocket.'
         authorize_message: 'Puoi importare dati dal tuo account Pocket. Devi solo cliccare sul pulsante sottostante e autorizzare la connessione a getpocket.com.'
         connect_to_pocket: 'Connetti a Pocket and importa i dati'
     wallabag_v1:
         page_title: 'Importa da > Wallabag v1'
-        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".'
+        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".'
         how_to: 'Seleziona la tua esportazione di wallabag e clicca sul pulsante sottostante caricare il file e importare i dati.'
     wallabag_v2:
         page_title: 'Importa da > Wallabag v2'
-        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".'
+        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'
     readability:
         page_title: 'Importa da > Readability'
         # 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:
         title: 'Client esistenti'
         field_id: 'Client ID'
         field_secret: 'Client secret'
-        field_uris: 'Redirect URI'
-        field_grant_types: 'Tipi di grant permessi'
+        field_uris: 'URI di reindirizzamento'
+        field_grant_types: 'Tipi di permessi concessi'
         no_client: 'Ancora nessun client.'
     remove:
-        warn_message_1: "Hai la possibilitò di rimuovere questo client.L'operazione è IRREVERSIBILE!"
+        warn_message_1: "Hai la possibilità di rimuovere questo client. L'operazione è IRREVERSIBILE!"
         warn_message_2: "Se lo rimuovi, ogni app configurata con questo client non sarà più in grado di autenticarsi."
         action: 'Rimuovi questo client'
     client:
         # page_title: 'API clients management > Nuovo client'
-        page_description: 'Stai per creare un nuovo client. Compila i campi sottostanti per il redirect URI della tua applicazione.'
+        page_description: 'Stai per creare un nuovo client. Compila i campi sottostanti per lo URI di reindirizzamento della tua applicazione.'
         form:
             # name_label: 'Name of the client'
-            redirect_uris_label: 'Redirect URI'
+            redirect_uris_label: 'URI di reindirizzamento'
             save_label: 'Crea un nuovo client'
         action_back: 'Indietro'
     client_parameter:
@@ -477,7 +477,7 @@ developer:
         field_id: 'Client ID'
         field_secret: 'Client secret'
         back: 'Indietro'
-        read_howto: 'Leggi howto "Come creare la mia prima applicazione"'
+        read_howto: 'Leggi "Come creare la mia prima applicazione"'
     howto:
         # page_title: 'API clients management > Come creare la mia prima applicazione'
         description:
@@ -530,9 +530,9 @@ flashes:
             password_not_updated_demo: "In modalità demo, non puoi cambiare la password dell'utente."
             user_updated: 'Informazioni aggiornate'
             rss_updated: 'Informazioni RSS aggiornate'
-            tagging_rules_updated: 'Regole di tagging aggiornate'
-            tagging_rules_deleted: 'Regola di tagging aggiornate'
-            rss_token_updated: 'RSS token aggiornato'
+            tagging_rules_updated: 'Regole di etichettatura aggiornate'
+            tagging_rules_deleted: 'Regole di etichettatura eliminate'
+            rss_token_updated: 'Token RSS aggiornato'
             # annotations_reset: Annotations reset
             # tags_reset: Tags reset
             # entries_reset: Entries reset
@@ -552,7 +552,7 @@ flashes:
             entry_deleted: 'Contenuto eliminato'
     tag:
         notice:
-            tag_added: 'Tag aggiunto'
+            tag_added: 'Etichetta aggiunta'
     import:
         notice:
             failed: 'Importazione fallita, riprova.'
index 0968cfafc9d4132cb3e0c0adfe55a15dffab389c..74ec34b17bcbba81c2525c3941e038502b2ffa9b 100644 (file)
@@ -477,6 +477,10 @@ class EntryRestControllerTest extends WallabagApiTestCase
             'tags' => 'new tag '.uniqid(),
             'starred' => '1',
             'archive' => '0',
+            'language' => 'de_DE',
+            'preview_picture' => 'http://preview.io/picture.jpg',
+            'authors' => 'bob,sponge',
+            'content' => 'awesome',
         ]);
 
         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
@@ -488,6 +492,11 @@ class EntryRestControllerTest extends WallabagApiTestCase
         $this->assertEquals('New awesome title', $content['title']);
         $this->assertGreaterThan($nbTags, count($content['tags']));
         $this->assertEquals(1, $content['user_id']);
+        $this->assertEquals('de_DE', $content['language']);
+        $this->assertEquals('http://preview.io/picture.jpg', $content['preview_picture']);
+        $this->assertContains('sponge', $content['published_by']);
+        $this->assertContains('bob', $content['published_by']);
+        $this->assertEquals('awesome', $content['content']);
     }
 
     public function testPatchEntryWithoutQuotes()
@@ -509,6 +518,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
             'tags' => 'new tag '.uniqid(),
             'starred' => 1,
             'archive' => 0,
+            'authors' => ['bob', 'sponge'],
         ]);
 
         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
@@ -519,6 +529,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
         $this->assertEquals($entry->getUrl(), $content['url']);
         $this->assertEquals('New awesome title', $content['title']);
         $this->assertGreaterThan($nbTags, count($content['tags']));
+        $this->assertTrue(empty($content['published_by']), 'Authors were not saved because of an array instead of a string');
     }
 
     public function testGetTagsEntry()
index 3f4969a534bd7e6f4b2bb3701251a273e2b6301c..5735bc5819e78cdf2e79db188f8d3d907da1a127 100644 (file)
@@ -27,15 +27,32 @@ class UserRestControllerTest extends WallabagApiTestCase
         $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
     }
 
+    public function testGetUserWithoutAuthentication()
+    {
+        $client = static::createClient();
+        $client->request('GET', '/api/user.json');
+        $this->assertEquals(401, $client->getResponse()->getStatusCode());
+
+        $content = json_decode($client->getResponse()->getContent(), true);
+
+        $this->assertArrayHasKey('error', $content);
+        $this->assertArrayHasKey('error_description', $content);
+
+        $this->assertEquals('access_denied', $content['error']);
+
+        $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type'));
+    }
+
     public function testCreateNewUser()
     {
+        $this->client->getContainer()->get('craue_config')->set('api_user_registration', 1);
         $this->client->request('PUT', '/api/user.json', [
             'username' => 'google',
             'password' => 'googlegoogle',
             'email' => 'wallabag@google.com',
         ]);
 
-        $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+        $this->assertEquals(201, $this->client->getResponse()->getStatusCode());
 
         $content = json_decode($this->client->getResponse()->getContent(), true);
 
@@ -50,30 +67,51 @@ class UserRestControllerTest extends WallabagApiTestCase
 
         $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
 
-        // remove the created user to avoid side effect on other tests
-        // @todo remove these lines when test will be isolated
-        $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
+        $this->client->getContainer()->get('craue_config')->set('api_user_registration', 0);
+    }
+
+    public function testCreateNewUserWithoutAuthentication()
+    {
+        // create a new client instead of using $this->client to be sure client isn't authenticated
+        $client = static::createClient();
+        $client->getContainer()->get('craue_config')->set('api_user_registration', 1);
+        $client->request('PUT', '/api/user.json', [
+            'username' => 'google',
+            'password' => 'googlegoogle',
+            'email' => 'wallabag@google.com',
+        ]);
+
+        $this->assertEquals(201, $client->getResponse()->getStatusCode());
+
+        $content = json_decode($client->getResponse()->getContent(), true);
 
-        $query = $em->createQuery('DELETE FROM Wallabag\CoreBundle\Entity\Config c WHERE c.user = :user_id');
-        $query->setParameter('user_id', $content['id']);
-        $query->execute();
+        $this->assertArrayHasKey('id', $content);
+        $this->assertArrayHasKey('email', $content);
+        $this->assertArrayHasKey('username', $content);
+        $this->assertArrayHasKey('created_at', $content);
+        $this->assertArrayHasKey('updated_at', $content);
 
-        $query = $em->createQuery('DELETE FROM Wallabag\UserBundle\Entity\User u WHERE u.id = :id');
-        $query->setParameter('id', $content['id']);
-        $query->execute();
+        $this->assertEquals('wallabag@google.com', $content['email']);
+        $this->assertEquals('google', $content['username']);
+
+        $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type'));
+
+        $client->getContainer()->get('craue_config')->set('api_user_registration', 0);
     }
 
     public function testCreateNewUserWithExistingEmail()
     {
-        $this->client->request('PUT', '/api/user.json', [
+        $client = static::createClient();
+        $client->getContainer()->get('craue_config')->set('api_user_registration', 1);
+        $client->request('PUT', '/api/user.json', [
             'username' => 'admin',
             'password' => 'googlegoogle',
             'email' => 'bigboss@wallabag.org',
         ]);
 
-        $this->assertEquals(400, $this->client->getResponse()->getStatusCode());
+        $this->assertEquals(400, $client->getResponse()->getStatusCode());
 
-        $content = json_decode($this->client->getResponse()->getContent(), true);
+        $content = json_decode($client->getResponse()->getContent(), true);
 
         $this->assertArrayHasKey('error', $content);
         $this->assertArrayHasKey('username', $content['error']);
@@ -85,26 +123,50 @@ class UserRestControllerTest extends WallabagApiTestCase
         $this->assertEquals('This value is already used.', $content['error']['username'][0]);
         $this->assertEquals('This value is already used.', $content['error']['email'][0]);
 
-        $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+        $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type'));
+
+        $client->getContainer()->get('craue_config')->set('api_user_registration', 0);
     }
 
     public function testCreateNewUserWithTooShortPassword()
     {
-        $this->client->request('PUT', '/api/user.json', [
+        $client = static::createClient();
+        $client->getContainer()->get('craue_config')->set('api_user_registration', 1);
+        $client->request('PUT', '/api/user.json', [
             'username' => 'facebook',
             'password' => 'face',
             'email' => 'facebook@wallabag.org',
         ]);
 
-        $this->assertEquals(400, $this->client->getResponse()->getStatusCode());
+        $this->assertEquals(400, $client->getResponse()->getStatusCode());
 
-        $content = json_decode($this->client->getResponse()->getContent(), true);
+        $content = json_decode($client->getResponse()->getContent(), true);
 
         $this->assertArrayHasKey('error', $content);
         $this->assertArrayHasKey('password', $content['error']);
 
         $this->assertEquals('validator.password_too_short', $content['error']['password'][0]);
 
-        $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+        $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type'));
+
+        $client->getContainer()->get('craue_config')->set('api_user_registration', 0);
+    }
+
+    public function testCreateNewUserWhenRegistrationIsDisabled()
+    {
+        $client = static::createClient();
+        $client->request('PUT', '/api/user.json', [
+            'username' => 'facebook',
+            'password' => 'face',
+            'email' => 'facebook@wallabag.org',
+        ]);
+
+        $this->assertEquals(403, $client->getResponse()->getStatusCode());
+
+        $content = json_decode($client->getResponse()->getContent(), true);
+
+        $this->assertArrayHasKey('error', $content);
+
+        $this->assertEquals('application/json', $client->getResponse()->headers->get('Content-Type'));
     }
 }
index c87e58de0d3fac350277290f9227e20cf08a0304..df638e8f4605146a856f9b870e220e285a103386 100644 (file)
@@ -8,12 +8,14 @@ class WallabagRestControllerTest extends WallabagApiTestCase
 {
     public function testGetVersion()
     {
-        $this->client->request('GET', '/api/version');
+        // create a new client instead of using $this->client to be sure client isn't authenticated
+        $client = static::createClient();
+        $client->request('GET', '/api/version');
 
-        $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+        $this->assertEquals(200, $client->getResponse()->getStatusCode());
 
-        $content = json_decode($this->client->getResponse()->getContent(), true);
+        $content = json_decode($client->getResponse()->getContent(), true);
 
-        $this->assertEquals($this->client->getContainer()->getParameter('wallabag_core.version'), $content);
+        $this->assertEquals($client->getContainer()->getParameter('wallabag_core.version'), $content);
     }
 }
diff --git a/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php b/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php
new file mode 100644 (file)
index 0000000..3b928d1
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+
+namespace Tests\Wallabag\CoreBundle\Command;
+
+use Symfony\Bundle\FrameworkBundle\Console\Application;
+use Symfony\Component\Console\Tester\CommandTester;
+use Wallabag\CoreBundle\Command\CleanDuplicatesCommand;
+use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
+use Wallabag\CoreBundle\Command\ShowUserCommand;
+use Wallabag\CoreBundle\Entity\Entry;
+use Wallabag\UserBundle\Entity\User;
+
+class ShowUserCommandTest extends WallabagCoreTestCase
+{
+    /**
+     * @expectedException \Symfony\Component\Console\Exception\RuntimeException
+     * @expectedExceptionMessage Not enough arguments
+     */
+    public function testRunShowUserCommandWithoutUsername()
+    {
+        $application = new Application($this->getClient()->getKernel());
+        $application->add(new ShowUserCommand());
+
+        $command = $application->find('wallabag:user:show');
+
+        $tester = new CommandTester($command);
+        $tester->execute([
+            'command' => $command->getName(),
+        ]);
+    }
+
+    public function testRunShowUserCommandWithBadUsername()
+    {
+        $application = new Application($this->getClient()->getKernel());
+        $application->add(new ShowUserCommand());
+
+        $command = $application->find('wallabag:user:show');
+
+        $tester = new CommandTester($command);
+        $tester->execute([
+            'command' => $command->getName(),
+            'username' => 'unknown',
+        ]);
+
+        $this->assertContains('User "unknown" not found', $tester->getDisplay());
+    }
+
+    public function testRunShowUserCommandForUser()
+    {
+        $application = new Application($this->getClient()->getKernel());
+        $application->add(new ShowUserCommand());
+
+        $command = $application->find('wallabag:user:show');
+
+        $tester = new CommandTester($command);
+        $tester->execute([
+            'command' => $command->getName(),
+            'username' => 'admin',
+        ]);
+
+        $this->assertContains('Username : admin', $tester->getDisplay());
+        $this->assertContains('Email : bigboss@wallabag.org', $tester->getDisplay());
+        $this->assertContains('Display name : Big boss', $tester->getDisplay());
+        $this->assertContains('2FA activated: no', $tester->getDisplay());
+    }
+
+    public function testShowUser()
+    {
+        $client = $this->getClient();
+        $em = $client->getContainer()->get('doctrine.orm.entity_manager');
+
+        $this->logInAs('admin');
+
+        /** @var User $user */
+        $user = $em->getRepository('WallabagUserBundle:User')->findOneById($this->getLoggedInUserId());
+
+        $user->setName('Bug boss');
+        $em->persist($user);
+
+        $em->flush();
+
+        $application = new Application($this->getClient()->getKernel());
+        $application->add(new ShowUserCommand());
+
+        $command = $application->find('wallabag:user:show');
+
+        $tester = new CommandTester($command);
+        $tester->execute([
+            'command' => $command->getName(),
+            'username' => 'admin',
+        ]);
+
+        $this->assertContains('Display name : Bug boss', $tester->getDisplay());
+    }
+}
index 9125f8dcb2da20fbeb0ebd61a67efbdba11f00dc..c02f96587cc663eab3caf0eefeb8af5cd387e5f4 100644 (file)
@@ -157,4 +157,29 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase
 
         $this->assertFalse($res, 'Absolute image can not be determined, so it will not be replaced');
     }
+
+    public function testProcessRealImage()
+    {
+        $client = new Client();
+
+        $mock = new Mock([
+            new Response(200, ['content-type' => null], Stream::factory(file_get_contents(__DIR__.'/../fixtures/image-no-content-type.jpg'))),
+        ]);
+
+        $client->getEmitter()->attach($mock);
+
+        $logHandler = new TestHandler();
+        $logger = new Logger('test', array($logHandler));
+
+        $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger);
+
+        $res = $download->processSingleImage(
+            123,
+            'https://cdn.theconversation.com/files/157200/article/width926/gsj2rjp2-1487348607.jpg',
+            'https://theconversation.com/conversation-avec-gerald-bronner-ce-nest-pas-la-post-verite-qui-nous-menace-mais-lextension-de-notre-credulite-73089'
+        );
+
+        $this->assertContains('http://wallabag.io/assets/images/9/b/9b0ead26/', $res, 'Content-Type was empty but data is ok for an image');
+        $this->assertContains('DownloadImages: Checking extension (alternative)', $logHandler->getRecords()[3]['message']);
+    }
 }
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 (file)
index 0000000..0c60e95
Binary files /dev/null and b/tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpg differ