aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag
diff options
context:
space:
mode:
authorJérémy Benoist <j0k3r@users.noreply.github.com>2019-01-03 09:14:26 +0100
committerGitHub <noreply@github.com>2019-01-03 09:14:26 +0100
commit2378fd6347dd1a824c8e1f4f7c3892c6eccddc85 (patch)
treecd039dc92f7a7a0dde5c6ca7484b8a9eefc359ca /src/Wallabag
parent4d0c632c70ea50d459c3c55ddda2e0f394dd51cb (diff)
parent6c40d7fc85b98e335adf765d1c6b4465647da62c (diff)
downloadwallabag-2378fd6347dd1a824c8e1f4f7c3892c6eccddc85.tar.gz
wallabag-2378fd6347dd1a824c8e1f4f7c3892c6eccddc85.tar.zst
wallabag-2378fd6347dd1a824c8e1f4f7c3892c6eccddc85.zip
Merge pull request #3823 from wallabag/fix-tag-api-leak
Fix tag API leak
Diffstat (limited to 'src/Wallabag')
-rw-r--r--src/Wallabag/ApiBundle/Controller/TagRestController.php22
-rw-r--r--src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php197
-rw-r--r--src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php43
-rw-r--r--src/Wallabag/CoreBundle/Repository/TagRepository.php53
4 files changed, 170 insertions, 145 deletions
diff --git a/src/Wallabag/ApiBundle/Controller/TagRestController.php b/src/Wallabag/ApiBundle/Controller/TagRestController.php
index c6d6df6a..f3498f55 100644
--- a/src/Wallabag/ApiBundle/Controller/TagRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/TagRestController.php
@@ -46,12 +46,14 @@ class TagRestController extends WallabagRestController
46 $this->validateAuthentication(); 46 $this->validateAuthentication();
47 $label = $request->get('tag', ''); 47 $label = $request->get('tag', '');
48 48
49 $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($label); 49 $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findByLabelsAndUser([$label], $this->getUser()->getId());
50 50
51 if (empty($tag)) { 51 if (empty($tags)) {
52 throw $this->createNotFoundException('Tag not found'); 52 throw $this->createNotFoundException('Tag not found');
53 } 53 }
54 54
55 $tag = $tags[0];
56
55 $this->getDoctrine() 57 $this->getDoctrine()
56 ->getRepository('WallabagCoreBundle:Entry') 58 ->getRepository('WallabagCoreBundle:Entry')
57 ->removeTag($this->getUser()->getId(), $tag); 59 ->removeTag($this->getUser()->getId(), $tag);
@@ -80,15 +82,7 @@ class TagRestController extends WallabagRestController
80 82
81 $tagsLabels = $request->get('tags', ''); 83 $tagsLabels = $request->get('tags', '');
82 84
83 $tags = []; 85 $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findByLabelsAndUser(explode(',', $tagsLabels), $this->getUser()->getId());
84
85 foreach (explode(',', $tagsLabels) as $tagLabel) {
86 $tagEntity = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($tagLabel);
87
88 if (!empty($tagEntity)) {
89 $tags[] = $tagEntity;
90 }
91 }
92 86
93 if (empty($tags)) { 87 if (empty($tags)) {
94 throw $this->createNotFoundException('Tags not found'); 88 throw $this->createNotFoundException('Tags not found');
@@ -120,6 +114,12 @@ class TagRestController extends WallabagRestController
120 { 114 {
121 $this->validateAuthentication(); 115 $this->validateAuthentication();
122 116
117 $tagFromDb = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findByLabelsAndUser([$tag->getLabel()], $this->getUser()->getId());
118
119 if (empty($tagFromDb)) {
120 throw $this->createNotFoundException('Tag not found');
121 }
122
123 $this->getDoctrine() 123 $this->getDoctrine()
124 ->getRepository('WallabagCoreBundle:Entry') 124 ->getRepository('WallabagCoreBundle:Entry')
125 ->removeTag($this->getUser()->getId(), $tag); 125 ->removeTag($this->getUser()->getId(), $tag);
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php
index 0e1510a2..8e7a1d2a 100644
--- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php
@@ -14,97 +14,112 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface
14 */ 14 */
15 public function load(ObjectManager $manager) 15 public function load(ObjectManager $manager)
16 { 16 {
17 $entry1 = new Entry($this->getReference('admin-user')); 17 $entries = [
18 $entry1->setUrl('http://0.0.0.0/entry1'); 18 'entry1' => [
19 $entry1->setReadingTime(11); 19 'user' => 'admin-user',
20 $entry1->setDomainName('domain.io'); 20 'url' => 'http://0.0.0.0/entry1',
21 $entry1->setMimetype('text/html'); 21 'reading_time' => 11,
22 $entry1->setTitle('test title entry1'); 22 'domain' => 'domain.io',
23 $entry1->setContent('This is my content /o/'); 23 'mime' => 'text/html',
24 $entry1->setLanguage('en'); 24 'title' => 'test title entry1',
25 25 'content' => 'This is my content /o/',
26 $entry1->addTag($this->getReference('foo-tag')); 26 'language' => 'en',
27 $entry1->addTag($this->getReference('baz-tag')); 27 'tags' => ['foo-tag', 'baz-tag'],
28 28 ],
29 $manager->persist($entry1); 29 'entry2' => [
30 30 'user' => 'admin-user',
31 $this->addReference('entry1', $entry1); 31 'url' => 'http://0.0.0.0/entry2',
32 32 'reading_time' => 1,
33 $entry2 = new Entry($this->getReference('admin-user')); 33 'domain' => 'domain.io',
34 $entry2->setUrl('http://0.0.0.0/entry2'); 34 'mime' => 'text/html',
35 $entry2->setReadingTime(1); 35 'title' => 'test title entry2',
36 $entry2->setDomainName('domain.io'); 36 'content' => 'This is my content /o/',
37 $entry2->setMimetype('text/html'); 37 'origin' => 'ftp://oneftp.tld',
38 $entry2->setTitle('test title entry2'); 38 'language' => 'fr',
39 $entry2->setContent('This is my content /o/'); 39 ],
40 $entry2->setOriginUrl('ftp://oneftp.tld'); 40 'entry3' => [
41 $entry2->setLanguage('fr'); 41 'user' => 'bob-user',
42 42 'url' => 'http://0.0.0.0/entry3',
43 $manager->persist($entry2); 43 'reading_time' => 1,
44 44 'domain' => 'domain.io',
45 $this->addReference('entry2', $entry2); 45 'mime' => 'text/html',
46 46 'title' => 'test title entry3',
47 $entry3 = new Entry($this->getReference('bob-user')); 47 'content' => 'This is my content /o/',
48 $entry3->setUrl('http://0.0.0.0/entry3'); 48 'language' => 'en',
49 $entry3->setReadingTime(1); 49 'tags' => ['foo-tag', 'bar-tag', 'bob-tag'],
50 $entry3->setDomainName('domain.io'); 50 ],
51 $entry3->setMimetype('text/html'); 51 'entry4' => [
52 $entry3->setTitle('test title entry3'); 52 'user' => 'admin-user',
53 $entry3->setContent('This is my content /o/'); 53 'url' => 'http://0.0.0.0/entry4',
54 $entry3->setLanguage('en'); 54 'reading_time' => 12,
55 55 'domain' => 'domain.io',
56 $entry3->addTag($this->getReference('foo-tag')); 56 'mime' => 'text/html',
57 $entry3->addTag($this->getReference('bar-tag')); 57 'title' => 'test title entry4',
58 58 'content' => 'This is my content /o/',
59 $manager->persist($entry3); 59 'language' => 'en',
60 60 'tags' => ['foo-tag', 'bar-tag'],
61 $this->addReference('entry3', $entry3); 61 ],
62 62 'entry5' => [
63 $entry4 = new Entry($this->getReference('admin-user')); 63 'user' => 'admin-user',
64 $entry4->setUrl('http://0.0.0.0/entry4'); 64 'url' => 'http://0.0.0.0/entry5',
65 $entry4->setReadingTime(12); 65 'reading_time' => 12,
66 $entry4->setDomainName('domain.io'); 66 'domain' => 'domain.io',
67 $entry4->setMimetype('text/html'); 67 'mime' => 'text/html',
68 $entry4->setTitle('test title entry4'); 68 'title' => 'test title entry5',
69 $entry4->setContent('This is my content /o/'); 69 'content' => 'This is my content /o/',
70 $entry4->setLanguage('en'); 70 'language' => 'fr',
71 71 'starred' => true,
72 $entry4->addTag($this->getReference('foo-tag')); 72 'preview' => 'http://0.0.0.0/image.jpg',
73 $entry4->addTag($this->getReference('bar-tag')); 73 ],
74 74 'entry6' => [
75 $manager->persist($entry4); 75 'user' => 'admin-user',
76 76 'url' => 'http://0.0.0.0/entry6',
77 $this->addReference('entry4', $entry4); 77 'reading_time' => 12,
78 78 'domain' => 'domain.io',
79 $entry5 = new Entry($this->getReference('admin-user')); 79 'mime' => 'text/html',
80 $entry5->setUrl('http://0.0.0.0/entry5'); 80 'title' => 'test title entry6',
81 $entry5->setReadingTime(12); 81 'content' => 'This is my content /o/',
82 $entry5->setDomainName('domain.io'); 82 'language' => 'de',
83 $entry5->setMimetype('text/html'); 83 'archived' => true,
84 $entry5->setTitle('test title entry5'); 84 'tags' => ['bar-tag'],
85 $entry5->setContent('This is my content /o/'); 85 ],
86 $entry5->setStarred(true); 86 ];
87 $entry5->setLanguage('fr'); 87
88 $entry5->setPreviewPicture('http://0.0.0.0/image.jpg'); 88 foreach ($entries as $reference => $item) {
89 89 $entry = new Entry($this->getReference($item['user']));
90 $manager->persist($entry5); 90 $entry->setUrl($item['url']);
91 91 $entry->setReadingTime($item['reading_time']);
92 $this->addReference('entry5', $entry5); 92 $entry->setDomainName($item['domain']);
93 93 $entry->setMimetype($item['mime']);
94 $entry6 = new Entry($this->getReference('admin-user')); 94 $entry->setTitle($item['title']);
95 $entry6->setUrl('http://0.0.0.0/entry6'); 95 $entry->setContent($item['content']);
96 $entry6->setReadingTime(12); 96 $entry->setLanguage($item['language']);
97 $entry6->setDomainName('domain.io'); 97
98 $entry6->setMimetype('text/html'); 98 if (isset($item['tags'])) {
99 $entry6->setTitle('test title entry6'); 99 foreach ($item['tags'] as $tag) {
100 $entry6->setContent('This is my content /o/'); 100 $entry->addTag($this->getReference($tag));
101 $entry6->setArchived(true); 101 }
102 $entry6->setLanguage('de'); 102 }
103 $entry6->addTag($this->getReference('bar-tag')); 103
104 104 if (isset($item['origin'])) {
105 $manager->persist($entry6); 105 $entry->setOriginUrl($item['origin']);
106 106 }
107 $this->addReference('entry6', $entry6); 107
108 if (isset($item['starred'])) {
109 $entry->setStarred($item['starred']);
110 }
111
112 if (isset($item['archived'])) {
113 $entry->setArchived($item['archived']);
114 }
115
116 if (isset($item['preview'])) {
117 $entry->setPreviewPicture($item['preview']);
118 }
119
120 $manager->persist($entry);
121 $this->addReference($reference, $entry);
122 }
108 123
109 $manager->flush(); 124 $manager->flush();
110 } 125 }
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php
index 0ecfd18b..485445c1 100644
--- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php
@@ -14,33 +14,22 @@ class LoadTagData extends AbstractFixture implements OrderedFixtureInterface
14 */ 14 */
15 public function load(ObjectManager $manager) 15 public function load(ObjectManager $manager)
16 { 16 {
17 $tag1 = new Tag(); 17 $tags = [
18 $tag1->setLabel('foo bar'); 18 'foo-bar-tag' => 'foo bar', //tag used for EntryControllerTest
19 19 'bar-tag' => 'bar',
20 $manager->persist($tag1); 20 'baz-tag' => 'baz', // tag used for ExportControllerTest
21 21 'foo-tag' => 'foo',
22 $this->addReference('foo-bar-tag', $tag1); 22 'bob-tag' => 'bob', // tag used for TagRestControllerTest
23 23 ];
24 $tag2 = new Tag(); 24
25 $tag2->setLabel('bar'); 25 foreach ($tags as $reference => $label) {
26 26 $tag = new Tag();
27 $manager->persist($tag2); 27 $tag->setLabel($label);
28 28
29 $this->addReference('bar-tag', $tag2); 29 $manager->persist($tag);
30 30
31 $tag3 = new Tag(); 31 $this->addReference($reference, $tag);
32 $tag3->setLabel('baz'); 32 }
33
34 $manager->persist($tag3);
35
36 $this->addReference('baz-tag', $tag3);
37
38 $tag4 = new Tag();
39 $tag4->setLabel('foo');
40
41 $manager->persist($tag4);
42
43 $this->addReference('foo-tag', $tag4);
44 33
45 $manager->flush(); 34 $manager->flush();
46 } 35 }
diff --git a/src/Wallabag/CoreBundle/Repository/TagRepository.php b/src/Wallabag/CoreBundle/Repository/TagRepository.php
index 3ae9d414..8464a6a5 100644
--- a/src/Wallabag/CoreBundle/Repository/TagRepository.php
+++ b/src/Wallabag/CoreBundle/Repository/TagRepository.php
@@ -3,6 +3,7 @@
3namespace Wallabag\CoreBundle\Repository; 3namespace Wallabag\CoreBundle\Repository;
4 4
5use Doctrine\ORM\EntityRepository; 5use Doctrine\ORM\EntityRepository;
6use Doctrine\ORM\QueryBuilder;
6use Wallabag\CoreBundle\Entity\Tag; 7use Wallabag\CoreBundle\Entity\Tag;
7 8
8class TagRepository extends EntityRepository 9class TagRepository extends EntityRepository
@@ -45,12 +46,8 @@ class TagRepository extends EntityRepository
45 */ 46 */
46 public function findAllTags($userId) 47 public function findAllTags($userId)
47 { 48 {
48 $ids = $this->createQueryBuilder('t') 49 $ids = $this->getQueryBuilderByUser($userId)
49 ->select('t.id') 50 ->select('t.id')
50 ->leftJoin('t.entries', 'e')
51 ->where('e.user = :userId')->setParameter('userId', $userId)
52 ->groupBy('t.id')
53 ->orderBy('t.slug')
54 ->getQuery() 51 ->getQuery()
55 ->getArrayResult(); 52 ->getArrayResult();
56 53
@@ -71,18 +68,30 @@ class TagRepository extends EntityRepository
71 */ 68 */
72 public function findAllFlatTagsWithNbEntries($userId) 69 public function findAllFlatTagsWithNbEntries($userId)
73 { 70 {
74 return $this->createQueryBuilder('t') 71 return $this->getQueryBuilderByUser($userId)
75 ->select('t.id, t.label, t.slug, count(e.id) as nbEntries') 72 ->select('t.id, t.label, t.slug, count(e.id) as nbEntries')
76 ->distinct(true) 73 ->distinct(true)
77 ->leftJoin('t.entries', 'e')
78 ->where('e.user = :userId')
79 ->groupBy('t.id')
80 ->orderBy('t.slug')
81 ->setParameter('userId', $userId)
82 ->getQuery() 74 ->getQuery()
83 ->getArrayResult(); 75 ->getArrayResult();
84 } 76 }
85 77
78 public function findByLabelsAndUser($labels, $userId)
79 {
80 $qb = $this->getQueryBuilderByUser($userId)
81 ->select('t.id');
82
83 $ids = $qb->andWhere($qb->expr()->in('t.label', $labels))
84 ->getQuery()
85 ->getArrayResult();
86
87 $tags = [];
88 foreach ($ids as $id) {
89 $tags[] = $this->find($id);
90 }
91
92 return $tags;
93 }
94
86 /** 95 /**
87 * Used only in test case to get a tag for our entry. 96 * Used only in test case to get a tag for our entry.
88 * 97 *
@@ -101,13 +110,9 @@ class TagRepository extends EntityRepository
101 110
102 public function findForArchivedArticlesByUser($userId) 111 public function findForArchivedArticlesByUser($userId)
103 { 112 {
104 $ids = $this->createQueryBuilder('t') 113 $ids = $this->getQueryBuilderByUser($userId)
105 ->select('t.id') 114 ->select('t.id')
106 ->leftJoin('t.entries', 'e')
107 ->where('e.user = :userId')->setParameter('userId', $userId)
108 ->andWhere('e.isArchived = true') 115 ->andWhere('e.isArchived = true')
109 ->groupBy('t.id')
110 ->orderBy('t.slug')
111 ->getQuery() 116 ->getQuery()
112 ->getArrayResult(); 117 ->getArrayResult();
113 118
@@ -118,4 +123,20 @@ class TagRepository extends EntityRepository
118 123
119 return $tags; 124 return $tags;
120 } 125 }
126
127 /**
128 * Retrieve a sorted list of tags used by a user.
129 *
130 * @param int $userId
131 *
132 * @return QueryBuilder
133 */
134 private function getQueryBuilderByUser($userId)
135 {
136 return $this->createQueryBuilder('t')
137 ->leftJoin('t.entries', 'e')
138 ->where('e.user = :userId')->setParameter('userId', $userId)
139 ->groupBy('t.id')
140 ->orderBy('t.slug');
141 }
121} 142}