From: Nicolas Lœuillet Date: Wed, 7 Jun 2017 14:30:27 +0000 (+0200) Subject: Merge pull request #3093 from aaa2000/annotation-error-on-save X-Git-Tag: 2.3.0~31^2~66 X-Git-Url: https://git.immae.eu/?a=commitdiff_plain;h=7bb3aa31776ffce2735a3b16f6ad80bb17946d4d;hp=c406cef5b69b0d6c43adef33b5374b209347b637;p=github%2Fwallabag%2Fwallabag.git Merge pull request #3093 from aaa2000/annotation-error-on-save Displays an error with an annotation with a too long quote --- 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 @@ -: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 index 00000000..451d16ba --- /dev/null +++ b/app/DoctrineMigrations/Version20170602075214.php @@ -0,0 +1,52 @@ +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';"); + } +} 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" # 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 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" 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 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" 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 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" 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 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: "اعمال" # 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 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" 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 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" # 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 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" 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 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" 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 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" # 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 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ă" # 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 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 @@ # 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 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: - { 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 troubleshoot this issue. - 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%" 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: 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 index 00000000..d8c593c6 --- /dev/null +++ b/app/config/wallabag.yml @@ -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 troubleshoot this issue. + 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" 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 $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)); + } } 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 */ 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); } /** 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 // 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 index 00000000..0eeaabc4 --- /dev/null +++ b/src/Wallabag/CoreBundle/Command/ShowUserCommand.php @@ -0,0 +1,77 @@ +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('User "%s" not found.', $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'); + } +} 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; 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']); 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 ->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() ; 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 $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'); 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 } } - if (!empty($content['authors'])) { + if (!empty($content['authors']) && is_array($content['authors'])) { $entry->setPublishedBy($content['authors']); } 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; 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; + } } 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: 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.
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.
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 « lettura veloce » quando il tempo di lettura è inferiore ai 3 minuti.
In questo case, devi mettere « readingTime <= 3 » nel campo Regola e « lettura veloce » nel campo Tag.
Molti tag si possono aggiungere contemporanemente separandoli con una virgola: « lettura veloce, da leggere »
Regole complesse possono essere scritte utilizzando gli operatori predefiniti: se « readingTime >= 5 AND domainName = "github.com" » allora tagga « lettura lunga, github »' + how_to_use_them_description: 'Diciamo che vuoi etichettare un contenuto come « lettura veloce » quando il tempo di lettura è inferiore ai 3 minuti.
In questo case, devi mettere « readingTime <= 3 » nel campo Regola e « lettura veloce » nel campo Etichette.
Molte etichette si possono aggiungere contemporanemente separandole con una virgola: « lettura veloce, da leggere »
Regole complesse possono essere scritte utilizzando gli operatori predefiniti: se « readingTime >= 5 AND domainName = "github.com" » allora etichetta « lettura lunga, github »' 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 wallabag" 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: 'su GitHub' 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.' 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 '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() 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 $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')); } } 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 { 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 index 00000000..3b928d1e --- /dev/null +++ b/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php @@ -0,0 +1,95 @@ +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()); + } +} 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 $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 index 00000000..0c60e952 Binary files /dev/null and b/tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpg differ