]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
Merge pull request #3816 from wallabag/validate-import-entry
authorJérémy Benoist <j0k3r@users.noreply.github.com>
Fri, 4 Jan 2019 10:06:53 +0000 (11:06 +0100)
committerGitHub <noreply@github.com>
Fri, 4 Jan 2019 10:06:53 +0000 (11:06 +0100)
Validate imported entry to avoid error on import

src/Wallabag/ApiBundle/Controller/TagRestController.php
src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php
src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php
src/Wallabag/CoreBundle/Repository/TagRepository.php
tests/Wallabag/ApiBundle/Controller/TagRestControllerTest.php

index c6d6df6a91423718f5006cbace9f569eca6e7a7c..f3498f55a83f17bab2c881a75ea6918115dd1125 100644 (file)
@@ -46,12 +46,14 @@ class TagRestController extends WallabagRestController
         $this->validateAuthentication();
         $label = $request->get('tag', '');
 
-        $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($label);
+        $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findByLabelsAndUser([$label], $this->getUser()->getId());
 
-        if (empty($tag)) {
+        if (empty($tags)) {
             throw $this->createNotFoundException('Tag not found');
         }
 
+        $tag = $tags[0];
+
         $this->getDoctrine()
             ->getRepository('WallabagCoreBundle:Entry')
             ->removeTag($this->getUser()->getId(), $tag);
@@ -80,15 +82,7 @@ class TagRestController extends WallabagRestController
 
         $tagsLabels = $request->get('tags', '');
 
-        $tags = [];
-
-        foreach (explode(',', $tagsLabels) as $tagLabel) {
-            $tagEntity = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($tagLabel);
-
-            if (!empty($tagEntity)) {
-                $tags[] = $tagEntity;
-            }
-        }
+        $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findByLabelsAndUser(explode(',', $tagsLabels), $this->getUser()->getId());
 
         if (empty($tags)) {
             throw $this->createNotFoundException('Tags not found');
@@ -120,6 +114,12 @@ class TagRestController extends WallabagRestController
     {
         $this->validateAuthentication();
 
+        $tagFromDb = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findByLabelsAndUser([$tag->getLabel()], $this->getUser()->getId());
+
+        if (empty($tagFromDb)) {
+            throw $this->createNotFoundException('Tag not found');
+        }
+
         $this->getDoctrine()
             ->getRepository('WallabagCoreBundle:Entry')
             ->removeTag($this->getUser()->getId(), $tag);
index 0e1510a29bf450f7c8e9e6067fb7c6ee2af84012..8e7a1d2af9503eef8543d22722bf9292528626ff 100644 (file)
@@ -14,97 +14,112 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface
      */
     public function load(ObjectManager $manager)
     {
-        $entry1 = new Entry($this->getReference('admin-user'));
-        $entry1->setUrl('http://0.0.0.0/entry1');
-        $entry1->setReadingTime(11);
-        $entry1->setDomainName('domain.io');
-        $entry1->setMimetype('text/html');
-        $entry1->setTitle('test title entry1');
-        $entry1->setContent('This is my content /o/');
-        $entry1->setLanguage('en');
-
-        $entry1->addTag($this->getReference('foo-tag'));
-        $entry1->addTag($this->getReference('baz-tag'));
-
-        $manager->persist($entry1);
-
-        $this->addReference('entry1', $entry1);
-
-        $entry2 = new Entry($this->getReference('admin-user'));
-        $entry2->setUrl('http://0.0.0.0/entry2');
-        $entry2->setReadingTime(1);
-        $entry2->setDomainName('domain.io');
-        $entry2->setMimetype('text/html');
-        $entry2->setTitle('test title entry2');
-        $entry2->setContent('This is my content /o/');
-        $entry2->setOriginUrl('ftp://oneftp.tld');
-        $entry2->setLanguage('fr');
-
-        $manager->persist($entry2);
-
-        $this->addReference('entry2', $entry2);
-
-        $entry3 = new Entry($this->getReference('bob-user'));
-        $entry3->setUrl('http://0.0.0.0/entry3');
-        $entry3->setReadingTime(1);
-        $entry3->setDomainName('domain.io');
-        $entry3->setMimetype('text/html');
-        $entry3->setTitle('test title entry3');
-        $entry3->setContent('This is my content /o/');
-        $entry3->setLanguage('en');
-
-        $entry3->addTag($this->getReference('foo-tag'));
-        $entry3->addTag($this->getReference('bar-tag'));
-
-        $manager->persist($entry3);
-
-        $this->addReference('entry3', $entry3);
-
-        $entry4 = new Entry($this->getReference('admin-user'));
-        $entry4->setUrl('http://0.0.0.0/entry4');
-        $entry4->setReadingTime(12);
-        $entry4->setDomainName('domain.io');
-        $entry4->setMimetype('text/html');
-        $entry4->setTitle('test title entry4');
-        $entry4->setContent('This is my content /o/');
-        $entry4->setLanguage('en');
-
-        $entry4->addTag($this->getReference('foo-tag'));
-        $entry4->addTag($this->getReference('bar-tag'));
-
-        $manager->persist($entry4);
-
-        $this->addReference('entry4', $entry4);
-
-        $entry5 = new Entry($this->getReference('admin-user'));
-        $entry5->setUrl('http://0.0.0.0/entry5');
-        $entry5->setReadingTime(12);
-        $entry5->setDomainName('domain.io');
-        $entry5->setMimetype('text/html');
-        $entry5->setTitle('test title entry5');
-        $entry5->setContent('This is my content /o/');
-        $entry5->setStarred(true);
-        $entry5->setLanguage('fr');
-        $entry5->setPreviewPicture('http://0.0.0.0/image.jpg');
-
-        $manager->persist($entry5);
-
-        $this->addReference('entry5', $entry5);
-
-        $entry6 = new Entry($this->getReference('admin-user'));
-        $entry6->setUrl('http://0.0.0.0/entry6');
-        $entry6->setReadingTime(12);
-        $entry6->setDomainName('domain.io');
-        $entry6->setMimetype('text/html');
-        $entry6->setTitle('test title entry6');
-        $entry6->setContent('This is my content /o/');
-        $entry6->setArchived(true);
-        $entry6->setLanguage('de');
-        $entry6->addTag($this->getReference('bar-tag'));
-
-        $manager->persist($entry6);
-
-        $this->addReference('entry6', $entry6);
+        $entries = [
+            'entry1' => [
+                'user' => 'admin-user',
+                'url' => 'http://0.0.0.0/entry1',
+                'reading_time' => 11,
+                'domain' => 'domain.io',
+                'mime' => 'text/html',
+                'title' => 'test title entry1',
+                'content' => 'This is my content /o/',
+                'language' => 'en',
+                'tags' => ['foo-tag', 'baz-tag'],
+            ],
+            'entry2' => [
+                'user' => 'admin-user',
+                'url' => 'http://0.0.0.0/entry2',
+                'reading_time' => 1,
+                'domain' => 'domain.io',
+                'mime' => 'text/html',
+                'title' => 'test title entry2',
+                'content' => 'This is my content /o/',
+                'origin' => 'ftp://oneftp.tld',
+                'language' => 'fr',
+            ],
+            'entry3' => [
+                'user' => 'bob-user',
+                'url' => 'http://0.0.0.0/entry3',
+                'reading_time' => 1,
+                'domain' => 'domain.io',
+                'mime' => 'text/html',
+                'title' => 'test title entry3',
+                'content' => 'This is my content /o/',
+                'language' => 'en',
+                'tags' => ['foo-tag', 'bar-tag', 'bob-tag'],
+            ],
+            'entry4' => [
+                'user' => 'admin-user',
+                'url' => 'http://0.0.0.0/entry4',
+                'reading_time' => 12,
+                'domain' => 'domain.io',
+                'mime' => 'text/html',
+                'title' => 'test title entry4',
+                'content' => 'This is my content /o/',
+                'language' => 'en',
+                'tags' => ['foo-tag', 'bar-tag'],
+            ],
+            'entry5' => [
+                'user' => 'admin-user',
+                'url' => 'http://0.0.0.0/entry5',
+                'reading_time' => 12,
+                'domain' => 'domain.io',
+                'mime' => 'text/html',
+                'title' => 'test title entry5',
+                'content' => 'This is my content /o/',
+                'language' => 'fr',
+                'starred' => true,
+                'preview' => 'http://0.0.0.0/image.jpg',
+            ],
+            'entry6' => [
+                'user' => 'admin-user',
+                'url' => 'http://0.0.0.0/entry6',
+                'reading_time' => 12,
+                'domain' => 'domain.io',
+                'mime' => 'text/html',
+                'title' => 'test title entry6',
+                'content' => 'This is my content /o/',
+                'language' => 'de',
+                'archived' => true,
+                'tags' => ['bar-tag'],
+            ],
+        ];
+
+        foreach ($entries as $reference => $item) {
+            $entry = new Entry($this->getReference($item['user']));
+            $entry->setUrl($item['url']);
+            $entry->setReadingTime($item['reading_time']);
+            $entry->setDomainName($item['domain']);
+            $entry->setMimetype($item['mime']);
+            $entry->setTitle($item['title']);
+            $entry->setContent($item['content']);
+            $entry->setLanguage($item['language']);
+
+            if (isset($item['tags'])) {
+                foreach ($item['tags'] as $tag) {
+                    $entry->addTag($this->getReference($tag));
+                }
+            }
+
+            if (isset($item['origin'])) {
+                $entry->setOriginUrl($item['origin']);
+            }
+
+            if (isset($item['starred'])) {
+                $entry->setStarred($item['starred']);
+            }
+
+            if (isset($item['archived'])) {
+                $entry->setArchived($item['archived']);
+            }
+
+            if (isset($item['preview'])) {
+                $entry->setPreviewPicture($item['preview']);
+            }
+
+            $manager->persist($entry);
+            $this->addReference($reference, $entry);
+        }
 
         $manager->flush();
     }
index 0ecfd18b55ddab8c00f1616586f78a9f576af5c3..485445c1b99d6061721a217e85d195f6814a9481 100644 (file)
@@ -14,33 +14,22 @@ class LoadTagData extends AbstractFixture implements OrderedFixtureInterface
      */
     public function load(ObjectManager $manager)
     {
-        $tag1 = new Tag();
-        $tag1->setLabel('foo bar');
-
-        $manager->persist($tag1);
-
-        $this->addReference('foo-bar-tag', $tag1);
-
-        $tag2 = new Tag();
-        $tag2->setLabel('bar');
-
-        $manager->persist($tag2);
-
-        $this->addReference('bar-tag', $tag2);
-
-        $tag3 = new Tag();
-        $tag3->setLabel('baz');
-
-        $manager->persist($tag3);
-
-        $this->addReference('baz-tag', $tag3);
-
-        $tag4 = new Tag();
-        $tag4->setLabel('foo');
-
-        $manager->persist($tag4);
-
-        $this->addReference('foo-tag', $tag4);
+        $tags = [
+            'foo-bar-tag' => 'foo bar', //tag used for EntryControllerTest
+            'bar-tag' => 'bar',
+            'baz-tag' => 'baz', // tag used for ExportControllerTest
+            'foo-tag' => 'foo',
+            'bob-tag' => 'bob', // tag used for TagRestControllerTest
+        ];
+
+        foreach ($tags as $reference => $label) {
+            $tag = new Tag();
+            $tag->setLabel($label);
+
+            $manager->persist($tag);
+
+            $this->addReference($reference, $tag);
+        }
 
         $manager->flush();
     }
index 3ae9d4141161c4443eb98f9bc6533695558e6143..8464a6a55004c27cce23c5a2283af01dd56c1a74 100644 (file)
@@ -3,6 +3,7 @@
 namespace Wallabag\CoreBundle\Repository;
 
 use Doctrine\ORM\EntityRepository;
+use Doctrine\ORM\QueryBuilder;
 use Wallabag\CoreBundle\Entity\Tag;
 
 class TagRepository extends EntityRepository
@@ -45,12 +46,8 @@ class TagRepository extends EntityRepository
      */
     public function findAllTags($userId)
     {
-        $ids = $this->createQueryBuilder('t')
+        $ids = $this->getQueryBuilderByUser($userId)
             ->select('t.id')
-            ->leftJoin('t.entries', 'e')
-            ->where('e.user = :userId')->setParameter('userId', $userId)
-            ->groupBy('t.id')
-            ->orderBy('t.slug')
             ->getQuery()
             ->getArrayResult();
 
@@ -71,18 +68,30 @@ class TagRepository extends EntityRepository
      */
     public function findAllFlatTagsWithNbEntries($userId)
     {
-        return $this->createQueryBuilder('t')
+        return $this->getQueryBuilderByUser($userId)
             ->select('t.id, t.label, t.slug, count(e.id) as nbEntries')
             ->distinct(true)
-            ->leftJoin('t.entries', 'e')
-            ->where('e.user = :userId')
-            ->groupBy('t.id')
-            ->orderBy('t.slug')
-            ->setParameter('userId', $userId)
             ->getQuery()
             ->getArrayResult();
     }
 
+    public function findByLabelsAndUser($labels, $userId)
+    {
+        $qb = $this->getQueryBuilderByUser($userId)
+            ->select('t.id');
+
+        $ids = $qb->andWhere($qb->expr()->in('t.label', $labels))
+            ->getQuery()
+            ->getArrayResult();
+
+        $tags = [];
+        foreach ($ids as $id) {
+            $tags[] = $this->find($id);
+        }
+
+        return $tags;
+    }
+
     /**
      * Used only in test case to get a tag for our entry.
      *
@@ -101,13 +110,9 @@ class TagRepository extends EntityRepository
 
     public function findForArchivedArticlesByUser($userId)
     {
-        $ids = $this->createQueryBuilder('t')
+        $ids = $this->getQueryBuilderByUser($userId)
             ->select('t.id')
-            ->leftJoin('t.entries', 'e')
-            ->where('e.user = :userId')->setParameter('userId', $userId)
             ->andWhere('e.isArchived = true')
-            ->groupBy('t.id')
-            ->orderBy('t.slug')
             ->getQuery()
             ->getArrayResult();
 
@@ -118,4 +123,20 @@ class TagRepository extends EntityRepository
 
         return $tags;
     }
+
+    /**
+     * Retrieve a sorted list of tags used by a user.
+     *
+     * @param int $userId
+     *
+     * @return QueryBuilder
+     */
+    private function getQueryBuilderByUser($userId)
+    {
+        return $this->createQueryBuilder('t')
+            ->leftJoin('t.entries', 'e')
+            ->where('e.user = :userId')->setParameter('userId', $userId)
+            ->groupBy('t.id')
+            ->orderBy('t.slug');
+    }
 }
index 430e548d204078178b42bbdc957b9e6ee3ab1ebc..9daa94cd5346bf0a99d8cc73e0366666d830f749 100644 (file)
@@ -7,6 +7,8 @@ use Wallabag\CoreBundle\Entity\Tag;
 
 class TagRestControllerTest extends WallabagApiTestCase
 {
+    private $otherUserTagLabel = 'bob';
+
     public function testGetUserTags()
     {
         $this->client->request('GET', '/api/tags.json');
@@ -19,17 +21,33 @@ class TagRestControllerTest extends WallabagApiTestCase
         $this->assertArrayHasKey('id', $content[0]);
         $this->assertArrayHasKey('label', $content[0]);
 
+        $tagLabels = array_map(function ($i) {
+            return $i['label'];
+        }, $content);
+
+        $this->assertNotContains($this->otherUserTagLabel, $tagLabels, 'There is a possible tag leak');
+
         return end($content);
     }
 
     public function testDeleteUserTag()
     {
+        $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
+        $entry = $this->client->getContainer()
+            ->get('doctrine.orm.entity_manager')
+            ->getRepository('WallabagCoreBundle:Entry')
+            ->findOneWithTags($this->user->getId());
+
+        $entry = $entry[0];
+
         $tagLabel = 'tagtest';
         $tag = new Tag();
         $tag->setLabel($tagLabel);
-
-        $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
         $em->persist($tag);
+
+        $entry->addTag($tag);
+
+        $em->persist($entry);
         $em->flush();
         $em->clear();
 
@@ -53,6 +71,16 @@ class TagRestControllerTest extends WallabagApiTestCase
         $this->assertNull($tag, $tagLabel . ' was removed because it begun an orphan tag');
     }
 
+    public function testDeleteOtherUserTag()
+    {
+        $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
+        $tag = $em->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($this->otherUserTagLabel);
+
+        $this->client->request('DELETE', '/api/tags/' . $tag->getId() . '.json');
+
+        $this->assertSame(404, $this->client->getResponse()->getStatusCode());
+    }
+
     public function dataForDeletingTagByLabel()
     {
         return [
@@ -112,6 +140,13 @@ class TagRestControllerTest extends WallabagApiTestCase
         $this->assertSame(404, $this->client->getResponse()->getStatusCode());
     }
 
+    public function testDeleteTagByLabelOtherUser()
+    {
+        $this->client->request('DELETE', '/api/tag/label.json', ['tag' => $this->otherUserTagLabel]);
+
+        $this->assertSame(404, $this->client->getResponse()->getStatusCode());
+    }
+
     /**
      * @dataProvider dataForDeletingTagByLabel
      */
@@ -180,4 +215,11 @@ class TagRestControllerTest extends WallabagApiTestCase
 
         $this->assertSame(404, $this->client->getResponse()->getStatusCode());
     }
+
+    public function testDeleteTagsByLabelOtherUser()
+    {
+        $this->client->request('DELETE', '/api/tags/label.json', ['tags' => $this->otherUserTagLabel]);
+
+        $this->assertSame(404, $this->client->getResponse()->getStatusCode());
+    }
 }