aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorNicolas LÅ“uillet <nicolas@loeuillet.org>2015-02-09 12:52:06 +0100
committerNicolas LÅ“uillet <nicolas@loeuillet.org>2015-02-09 12:52:06 +0100
commit89c03230c3d51e618608b044b0e3f45cf0c06a11 (patch)
tree504e54ecfd8ae6203f76a19a910e5e6c5dee1c3e /src
parent8af35ad932177e0363412a868afc128b406e3322 (diff)
parent3b815d2de5a852fe2ebad5827bd4c9070aa175ea (diff)
downloadwallabag-89c03230c3d51e618608b044b0e3f45cf0c06a11.tar.gz
wallabag-89c03230c3d51e618608b044b0e3f45cf0c06a11.tar.zst
wallabag-89c03230c3d51e618608b044b0e3f45cf0c06a11.zip
Merge pull request #1062 from wallabag/v2-relation-entry-user
add a real relation between user and entry
Diffstat (limited to 'src')
-rw-r--r--src/Wallabag/CoreBundle/Controller/EntryController.php21
-rw-r--r--src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php35
-rw-r--r--src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php34
-rw-r--r--src/Wallabag/CoreBundle/Entity/Entry.php41
-rw-r--r--src/Wallabag/CoreBundle/Entity/User.php35
-rw-r--r--src/Wallabag/CoreBundle/Repository/EntryRepository.php63
-rw-r--r--src/Wallabag/CoreBundle/Security/Authentication/Encoder/WallabagPasswordEncoder.php88
-rw-r--r--src/Wallabag/CoreBundle/Security/Authentication/Provider/WallabagAuthenticationProvider.php89
-rw-r--r--src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php38
-rw-r--r--src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php40
-rw-r--r--src/Wallabag/CoreBundle/Tests/WallabagTestCase.php34
11 files changed, 448 insertions, 70 deletions
diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php
index 6326d31f..e0697ca3 100644
--- a/src/Wallabag/CoreBundle/Controller/EntryController.php
+++ b/src/Wallabag/CoreBundle/Controller/EntryController.php
@@ -19,8 +19,7 @@ class EntryController extends Controller
19 */ 19 */
20 public function addEntryAction(Request $request) 20 public function addEntryAction(Request $request)
21 { 21 {
22 $entry = new Entry(); 22 $entry = new Entry($this->getUser());
23 $entry->setUserId(1);
24 23
25 $form = $this->createFormBuilder($entry) 24 $form = $this->createFormBuilder($entry)
26 ->add('url', 'url') 25 ->add('url', 'url')
@@ -60,10 +59,10 @@ class EntryController extends Controller
60 */ 59 */
61 public function showUnreadAction() 60 public function showUnreadAction()
62 { 61 {
63 $repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry');
64 // TODO don't give the user ID like this
65 // TODO change pagination 62 // TODO change pagination
66 $entries = $repository->findUnreadByUser(1, 0); 63 $entries = $this->getDoctrine()
64 ->getRepository('WallabagCoreBundle:Entry')
65 ->findUnreadByUser($this->getUser()->getId(), 0);
67 66
68 return $this->render( 67 return $this->render(
69 'WallabagCoreBundle:Entry:entries.html.twig', 68 'WallabagCoreBundle:Entry:entries.html.twig',
@@ -79,10 +78,10 @@ class EntryController extends Controller
79 */ 78 */
80 public function showArchiveAction() 79 public function showArchiveAction()
81 { 80 {
82 $repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry');
83 // TODO don't give the user ID like this
84 // TODO change pagination 81 // TODO change pagination
85 $entries = $repository->findArchiveByUser(1, 0); 82 $entries = $this->getDoctrine()
83 ->getRepository('WallabagCoreBundle:Entry')
84 ->findArchiveByUser($this->getUser()->getId(), 0);
86 85
87 return $this->render( 86 return $this->render(
88 'WallabagCoreBundle:Entry:entries.html.twig', 87 'WallabagCoreBundle:Entry:entries.html.twig',
@@ -98,10 +97,10 @@ class EntryController extends Controller
98 */ 97 */
99 public function showStarredAction() 98 public function showStarredAction()
100 { 99 {
101 $repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry');
102 // TODO don't give the user ID like this
103 // TODO change pagination 100 // TODO change pagination
104 $entries = $repository->findStarredByUser(1, 0); 101 $entries = $this->getDoctrine()
102 ->getRepository('WallabagCoreBundle:Entry')
103 ->findStarredByUser($this->getUser()->getId(), 0);
105 104
106 return $this->render( 105 return $this->render(
107 'WallabagCoreBundle:Entry:entries.html.twig', 106 'WallabagCoreBundle:Entry:entries.html.twig',
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php
new file mode 100644
index 00000000..fccd06be
--- /dev/null
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php
@@ -0,0 +1,35 @@
1<?php
2
3namespace Wallabag\CoreBundle\DataFixtures\ORM;
4
5use Doctrine\Common\DataFixtures\AbstractFixture;
6use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
7use Doctrine\Common\Persistence\ObjectManager;
8use Wallabag\CoreBundle\Entity\Entry;
9
10class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface
11{
12 /**
13 * {@inheritDoc}
14 */
15 public function load(ObjectManager $manager)
16 {
17 $entry1 = new Entry($this->getReference('admin-user'));
18 $entry1->setUrl('http://0.0.0.0');
19 $entry1->setTitle('test title');
20 $entry1->setContent('This is my content /o/');
21
22 $manager->persist($entry1);
23 $manager->flush();
24
25 $this->addReference('entry1', $entry1);
26 }
27
28 /**
29 * {@inheritDoc}
30 */
31 public function getOrder()
32 {
33 return 20;
34 }
35}
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php
new file mode 100644
index 00000000..da788218
--- /dev/null
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php
@@ -0,0 +1,34 @@
1<?php
2
3namespace Wallabag\CoreBundle\DataFixtures\ORM;
4
5use Doctrine\Common\DataFixtures\AbstractFixture;
6use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
7use Doctrine\Common\Persistence\ObjectManager;
8use Wallabag\CoreBundle\Entity\User;
9
10class LoadUserData extends AbstractFixture implements OrderedFixtureInterface
11{
12 /**
13 * {@inheritDoc}
14 */
15 public function load(ObjectManager $manager)
16 {
17 $userAdmin = new User();
18 $userAdmin->setUsername('admin');
19 $userAdmin->setPassword('test');
20
21 $manager->persist($userAdmin);
22 $manager->flush();
23
24 $this->addReference('admin-user', $userAdmin);
25 }
26
27 /**
28 * {@inheritDoc}
29 */
30 public function getOrder()
31 {
32 return 10;
33 }
34}
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php
index a00762ca..937213b4 100644
--- a/src/Wallabag/CoreBundle/Entity/Entry.php
+++ b/src/Wallabag/CoreBundle/Entity/Entry.php
@@ -84,13 +84,6 @@ class Entry
84 /** 84 /**
85 * @var string 85 * @var string
86 * 86 *
87 * @ORM\Column(name="user_id", type="decimal", precision=10, scale=0, nullable=true)
88 */
89 private $userId;
90
91 /**
92 * @var string
93 *
94 * @ORM\Column(name="comments", type="text", nullable=true) 87 * @ORM\Column(name="comments", type="text", nullable=true)
95 */ 88 */
96 private $comments; 89 private $comments;
@@ -124,6 +117,19 @@ class Entry
124 private $isPublic; 117 private $isPublic;
125 118
126 /** 119 /**
120 * @ORM\ManyToOne(targetEntity="User", inversedBy="entries")
121 */
122 private $user;
123
124 /*
125 * @param User $user
126 */
127 public function __construct(User $user)
128 {
129 $this->user = $user;
130 }
131
132 /**
127 * Get id 133 * Get id
128 * 134 *
129 * @return integer 135 * @return integer
@@ -263,26 +269,11 @@ class Entry
263 } 269 }
264 270
265 /** 271 /**
266 * Set userId 272 * @return User
267 *
268 * @param string $userId
269 * @return Entry
270 */
271 public function setUserId($userId)
272 {
273 $this->userId = $userId;
274
275 return $this;
276 }
277
278 /**
279 * Get userId
280 *
281 * @return string
282 */ 273 */
283 public function getUserId() 274 public function getUser()
284 { 275 {
285 return $this->userId; 276 return $this->user;
286 } 277 }
287 278
288 /** 279 /**
diff --git a/src/Wallabag/CoreBundle/Entity/User.php b/src/Wallabag/CoreBundle/Entity/User.php
index 6abfd3ae..c83250c3 100644
--- a/src/Wallabag/CoreBundle/Entity/User.php
+++ b/src/Wallabag/CoreBundle/Entity/User.php
@@ -2,6 +2,7 @@
2 2
3namespace Wallabag\CoreBundle\Entity; 3namespace Wallabag\CoreBundle\Entity;
4 4
5use Doctrine\Common\Collections\ArrayCollection;
5use Doctrine\ORM\Mapping as ORM; 6use Doctrine\ORM\Mapping as ORM;
6use Symfony\Component\Security\Core\User\UserInterface; 7use Symfony\Component\Security\Core\User\UserInterface;
7use Symfony\Component\Security\Core\User\AdvancedUserInterface; 8use Symfony\Component\Security\Core\User\AdvancedUserInterface;
@@ -78,10 +79,16 @@ class User implements AdvancedUserInterface, \Serializable
78 */ 79 */
79 private $updatedAt; 80 private $updatedAt;
80 81
82 /**
83 * @ORM\OneToMany(targetEntity="Entry", mappedBy="user", cascade={"remove"})
84 */
85 private $entries;
86
81 public function __construct() 87 public function __construct()
82 { 88 {
83 $this->isActive = true; 89 $this->isActive = true;
84 $this->salt = md5(uniqid(null, true)); 90 $this->salt = md5(uniqid(null, true));
91 $this->entries = new ArrayCollection();
85 } 92 }
86 93
87 /** 94 /**
@@ -154,7 +161,11 @@ class User implements AdvancedUserInterface, \Serializable
154 */ 161 */
155 public function setPassword($password) 162 public function setPassword($password)
156 { 163 {
157 $this->password = $password; 164 if (!$password && 0 === strlen($password)) {
165 return;
166 }
167
168 $this->password = sha1($password.$this->getUsername().$this->getSalt());
158 169
159 return $this; 170 return $this;
160 } 171 }
@@ -232,6 +243,26 @@ class User implements AdvancedUserInterface, \Serializable
232 } 243 }
233 244
234 /** 245 /**
246 * @param Entry $entry
247 *
248 * @return User
249 */
250 public function addEntry(Entry $entry)
251 {
252 $this->entries[] = $entry;
253
254 return $this;
255 }
256
257 /**
258 * @return ArrayCollection<Entry>
259 */
260 public function getEntries()
261 {
262 return $this->entries;
263 }
264
265 /**
235 * @inheritDoc 266 * @inheritDoc
236 */ 267 */
237 public function eraseCredentials() 268 public function eraseCredentials()
diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php
index f4c803f9..5ae1337a 100644
--- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php
+++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php
@@ -11,19 +11,20 @@ class EntryRepository extends EntityRepository
11 /** 11 /**
12 * Retrieves unread entries for a user 12 * Retrieves unread entries for a user
13 * 13 *
14 * @param $userId 14 * @param int $userId
15 * @param $firstResult 15 * @param int $firstResult
16 * @param int $maxResults 16 * @param int $maxResults
17 *
17 * @return Paginator 18 * @return Paginator
18 */ 19 */
19 public function findUnreadByUser($userId, $firstResult, $maxResults = 12) 20 public function findUnreadByUser($userId, $firstResult, $maxResults = 12)
20 { 21 {
21 $qb = $this->createQueryBuilder('e') 22 $qb = $this->createQueryBuilder('e')
22 ->select('e')
23 ->setFirstResult($firstResult) 23 ->setFirstResult($firstResult)
24 ->setMaxResults($maxResults) 24 ->setMaxResults($maxResults)
25 ->leftJoin('e.user', 'u')
25 ->where('e.isArchived = false') 26 ->where('e.isArchived = false')
26 ->andWhere('e.userId =:userId')->setParameter('userId', $userId) 27 ->andWhere('u.id =:userId')->setParameter('userId', $userId)
27 ->andWhere('e.isDeleted=false') 28 ->andWhere('e.isDeleted=false')
28 ->orderBy('e.createdAt', 'desc') 29 ->orderBy('e.createdAt', 'desc')
29 ->getQuery(); 30 ->getQuery();
@@ -36,9 +37,10 @@ class EntryRepository extends EntityRepository
36 /** 37 /**
37 * Retrieves read entries for a user 38 * Retrieves read entries for a user
38 * 39 *
39 * @param $userId 40 * @param int $userId
40 * @param $firstResult 41 * @param int $firstResult
41 * @param int $maxResults 42 * @param int $maxResults
43 *
42 * @return Paginator 44 * @return Paginator
43 */ 45 */
44 public function findArchiveByUser($userId, $firstResult, $maxResults = 12) 46 public function findArchiveByUser($userId, $firstResult, $maxResults = 12)
@@ -47,8 +49,9 @@ class EntryRepository extends EntityRepository
47 ->select('e') 49 ->select('e')
48 ->setFirstResult($firstResult) 50 ->setFirstResult($firstResult)
49 ->setMaxResults($maxResults) 51 ->setMaxResults($maxResults)
52 ->leftJoin('e.user', 'u')
50 ->where('e.isArchived = true') 53 ->where('e.isArchived = true')
51 ->andWhere('e.userId =:userId')->setParameter('userId', $userId) 54 ->andWhere('u.id =:userId')->setParameter('userId', $userId)
52 ->andWhere('e.isDeleted=false') 55 ->andWhere('e.isDeleted=false')
53 ->orderBy('e.createdAt', 'desc') 56 ->orderBy('e.createdAt', 'desc')
54 ->getQuery(); 57 ->getQuery();
@@ -61,9 +64,10 @@ class EntryRepository extends EntityRepository
61 /** 64 /**
62 * Retrieves starred entries for a user 65 * Retrieves starred entries for a user
63 * 66 *
64 * @param $userId 67 * @param int $userId
65 * @param $firstResult 68 * @param int $firstResult
66 * @param int $maxResults 69 * @param int $maxResults
70 *
67 * @return Paginator 71 * @return Paginator
68 */ 72 */
69 public function findStarredByUser($userId, $firstResult, $maxResults = 12) 73 public function findStarredByUser($userId, $firstResult, $maxResults = 12)
@@ -72,9 +76,10 @@ class EntryRepository extends EntityRepository
72 ->select('e') 76 ->select('e')
73 ->setFirstResult($firstResult) 77 ->setFirstResult($firstResult)
74 ->setMaxResults($maxResults) 78 ->setMaxResults($maxResults)
79 ->leftJoin('e.user', 'u')
75 ->where('e.isStarred = true') 80 ->where('e.isStarred = true')
76 ->andWhere('e.userId =:userId')->setParameter('userId', $userId) 81 ->andWhere('u.id =:userId')->setParameter('userId', $userId)
77 ->andWhere('e.isDeleted=false') 82 ->andWhere('e.isDeleted = false')
78 ->orderBy('e.createdAt', 'desc') 83 ->orderBy('e.createdAt', 'desc')
79 ->getQuery(); 84 ->getQuery();
80 85
@@ -83,22 +88,34 @@ class EntryRepository extends EntityRepository
83 return $paginator; 88 return $paginator;
84 } 89 }
85 90
86 public function findEntries($userId, $isArchived, $isStarred, $isDeleted, $sort, $order) 91 /**
92 * Find Entries
93 *
94 * @param int $userId
95 * @param bool $isArchived
96 * @param bool $isStarred
97 * @param bool $isDeleted
98 * @param string $sort
99 * @param string $order
100 *
101 * @return ArrayCollection
102 */
103 public function findEntries($userId, $isArchived = null, $isStarred = null, $isDeleted = null, $sort = 'created', $order = 'ASC')
87 { 104 {
88 $qb = $this->createQueryBuilder('e') 105 $qb = $this->createQueryBuilder('e')
89 ->select('e') 106 ->leftJoin('e.user', 'u')
90 ->where('e.userId =:userId')->setParameter('userId', $userId); 107 ->where('u.id =:userId')->setParameter('userId', $userId);
91 108
92 if (!is_null($isArchived)) { 109 if (null !== $isArchived) {
93 $qb->andWhere('e.isArchived =:isArchived')->setParameter('isArchived', $isArchived); 110 $qb->andWhere('e.isArchived =:isArchived')->setParameter('isArchived', (bool) $isArchived);
94 } 111 }
95 112
96 if (!is_null($isStarred)) { 113 if (null !== $isStarred) {
97 $qb->andWhere('e.isStarred =:isStarred')->setParameter('isStarred', $isStarred); 114 $qb->andWhere('e.isStarred =:isStarred')->setParameter('isStarred', (bool) $isStarred);
98 } 115 }
99 116
100 if (!is_null($isDeleted)) { 117 if (null !== $isDeleted) {
101 $qb->andWhere('e.isDeleted =:isDeleted')->setParameter('isDeleted', $isDeleted); 118 $qb->andWhere('e.isDeleted =:isDeleted')->setParameter('isDeleted', (bool) $isDeleted);
102 } 119 }
103 120
104 if ('created' === $sort) { 121 if ('created' === $sort) {
diff --git a/src/Wallabag/CoreBundle/Security/Authentication/Encoder/WallabagPasswordEncoder.php b/src/Wallabag/CoreBundle/Security/Authentication/Encoder/WallabagPasswordEncoder.php
new file mode 100644
index 00000000..56f1affe
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Security/Authentication/Encoder/WallabagPasswordEncoder.php
@@ -0,0 +1,88 @@
1<?php
2
3namespace Wallabag\CoreBundle\Security\Authentication\Encoder;
4
5use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;
6use Symfony\Component\Security\Core\Exception\BadCredentialsException;
7
8/**
9 * This override just add en extra variable (username) to be able to salt the password
10 * the way Wallabag v1 does. It will avoid to break compatibility with Wallabag v1
11 *
12 */
13class WallabagPasswordEncoder extends BasePasswordEncoder
14{
15 private $algorithm;
16 private $encodeHashAsBase64;
17 private $iterations;
18 private $username = null;
19
20 /**
21 * Constructor.
22 *
23 * @param string $algorithm The digest algorithm to use
24 * @param bool $encodeHashAsBase64 Whether to base64 encode the password hash
25 * @param int $iterations The number of iterations to use to stretch the password hash
26 */
27 public function __construct($algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 5000)
28 {
29 $this->algorithm = $algorithm;
30 $this->encodeHashAsBase64 = $encodeHashAsBase64;
31 $this->iterations = $iterations;
32 }
33
34 public function setUsername($username)
35 {
36 $this->username = $username;
37 }
38
39 /**
40 * {@inheritdoc}
41 */
42 public function encodePassword($raw, $salt)
43 {
44 if (null === $this->username) {
45 throw new \LogicException('We can not check the password without a username.');
46 }
47
48 if ($this->isPasswordTooLong($raw)) {
49 throw new BadCredentialsException('Invalid password.');
50 }
51
52 if (!in_array($this->algorithm, hash_algos(), true)) {
53 throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
54 }
55
56 $salted = $this->mergePasswordAndSalt($raw, $salt);
57 $digest = hash($this->algorithm, $salted, true);
58
59 // "stretch" hash
60 for ($i = 1; $i < $this->iterations; $i++) {
61 $digest = hash($this->algorithm, $digest.$salted, true);
62 }
63
64 return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
65 }
66
67 /**
68 * {@inheritdoc}
69 *
70 * We inject the username inside the salted password
71 */
72 protected function mergePasswordAndSalt($password, $salt)
73 {
74 if (empty($salt)) {
75 return $password;
76 }
77
78 return $password.$this->username.$salt;
79 }
80
81 /**
82 * {@inheritdoc}
83 */
84 public function isPasswordValid($encoded, $raw, $salt)
85 {
86 return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
87 }
88}
diff --git a/src/Wallabag/CoreBundle/Security/Authentication/Provider/WallabagAuthenticationProvider.php b/src/Wallabag/CoreBundle/Security/Authentication/Provider/WallabagAuthenticationProvider.php
new file mode 100644
index 00000000..1c7c5fae
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Security/Authentication/Provider/WallabagAuthenticationProvider.php
@@ -0,0 +1,89 @@
1<?php
2
3namespace Wallabag\CoreBundle\Security\Authentication\Provider;
4
5use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
6use Symfony\Component\Security\Core\User\UserProviderInterface;
7use Symfony\Component\Security\Core\User\UserCheckerInterface;
8use Symfony\Component\Security\Core\User\UserInterface;
9use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
10use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
11use Symfony\Component\Security\Core\Exception\BadCredentialsException;
12use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
13use Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider;
14
15class WallabagAuthenticationProvider extends UserAuthenticationProvider
16{
17 private $encoderFactory;
18 private $userProvider;
19
20 /**
21 * Constructor.
22 *
23 * @param UserProviderInterface $userProvider An UserProviderInterface instance
24 * @param UserCheckerInterface $userChecker An UserCheckerInterface instance
25 * @param string $providerKey The provider key
26 * @param EncoderFactoryInterface $encoderFactory An EncoderFactoryInterface instance
27 * @param bool $hideUserNotFoundExceptions Whether to hide user not found exception or not
28 */
29 public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, EncoderFactoryInterface $encoderFactory, $hideUserNotFoundExceptions = true)
30 {
31 parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions);
32
33 $this->encoderFactory = $encoderFactory;
34 $this->userProvider = $userProvider;
35 }
36
37 /**
38 * {@inheritdoc}
39 */
40 protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token)
41 {
42 $currentUser = $token->getUser();
43 if ($currentUser instanceof UserInterface) {
44 if ($currentUser->getPassword() !== $user->getPassword()) {
45 throw new BadCredentialsException('The credentials were changed from another session.');
46 }
47 } else {
48 if ("" === ($presentedPassword = $token->getCredentials())) {
49 throw new BadCredentialsException('The presented password cannot be empty.');
50 }
51
52 // give username, it's used to hash the password
53 $encoder = $this->encoderFactory->getEncoder($user);
54 $encoder->setUsername($user->getUsername());
55
56 if (!$encoder->isPasswordValid($user->getPassword(), $presentedPassword, $user->getSalt())) {
57 throw new BadCredentialsException('The presented password is invalid.');
58 }
59 }
60 }
61
62 /**
63 * {@inheritdoc}
64 */
65 protected function retrieveUser($username, UsernamePasswordToken $token)
66 {
67 $user = $token->getUser();
68 if ($user instanceof UserInterface) {
69 return $user;
70 }
71
72 try {
73 $user = $this->userProvider->loadUserByUsername($username);
74
75 if (!$user instanceof UserInterface) {
76 throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
77 }
78
79 return $user;
80 } catch (UsernameNotFoundException $notFound) {
81 $notFound->setUsername($username);
82 throw $notFound;
83 } catch (\Exception $repositoryProblem) {
84 $ex = new AuthenticationServiceException($repositoryProblem->getMessage(), 0, $repositoryProblem);
85 $ex->setToken($token);
86 throw $ex;
87 }
88 }
89}
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php
index fde210c9..5d8daea3 100644
--- a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php
+++ b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php
@@ -2,13 +2,24 @@
2 2
3namespace Wallabag\CoreBundle\Tests\Controller; 3namespace Wallabag\CoreBundle\Tests\Controller;
4 4
5use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; 5use Wallabag\CoreBundle\Tests\WallabagTestCase;
6 6
7class EntryControllerTest extends WebTestCase 7class EntryControllerTest extends WallabagTestCase
8{ 8{
9 public function testLogin()
10 {
11 $client = $this->getClient();
12
13 $crawler = $client->request('GET', '/new');
14
15 $this->assertEquals(302, $client->getResponse()->getStatusCode());
16 $this->assertContains('login', $client->getResponse()->headers->get('location'));
17 }
18
9 public function testGetNew() 19 public function testGetNew()
10 { 20 {
11 $client = static::createClient(); 21 $this->logIn();
22 $client = $this->getClient();
12 23
13 $crawler = $client->request('GET', '/new'); 24 $crawler = $client->request('GET', '/new');
14 25
@@ -20,7 +31,8 @@ class EntryControllerTest extends WebTestCase
20 31
21 public function testPostNewEmpty() 32 public function testPostNewEmpty()
22 { 33 {
23 $client = static::createClient(); 34 $this->logIn();
35 $client = $this->getClient();
24 36
25 $crawler = $client->request('GET', '/new'); 37 $crawler = $client->request('GET', '/new');
26 38
@@ -37,7 +49,8 @@ class EntryControllerTest extends WebTestCase
37 49
38 public function testPostNewOk() 50 public function testPostNewOk()
39 { 51 {
40 $client = static::createClient(); 52 $this->logIn();
53 $client = $this->getClient();
41 54
42 $crawler = $client->request('GET', '/new'); 55 $crawler = $client->request('GET', '/new');
43 56
@@ -55,13 +68,14 @@ class EntryControllerTest extends WebTestCase
55 68
56 $crawler = $client->followRedirect(); 69 $crawler = $client->followRedirect();
57 70
58 $this->assertCount(1, $alert = $crawler->filter('h2 a')->extract(array('_text'))); 71 $this->assertGreaterThan(1, $alert = $crawler->filter('h2 a')->extract(array('_text')));
59 $this->assertContains('Mailjet', $alert[0]); 72 $this->assertContains('Mailjet', $alert[0]);
60 } 73 }
61 74
62 public function testArchive() 75 public function testArchive()
63 { 76 {
64 $client = static::createClient(); 77 $this->logIn();
78 $client = $this->getClient();
65 79
66 $crawler = $client->request('GET', '/archive'); 80 $crawler = $client->request('GET', '/archive');
67 81
@@ -70,7 +84,8 @@ class EntryControllerTest extends WebTestCase
70 84
71 public function testStarred() 85 public function testStarred()
72 { 86 {
73 $client = static::createClient(); 87 $this->logIn();
88 $client = $this->getClient();
74 89
75 $crawler = $client->request('GET', '/starred'); 90 $crawler = $client->request('GET', '/starred');
76 91
@@ -79,13 +94,18 @@ class EntryControllerTest extends WebTestCase
79 94
80 public function testView() 95 public function testView()
81 { 96 {
82 $client = static::createClient(); 97 $this->logIn();
98 $client = $this->getClient();
83 99
84 $content = $client->getContainer() 100 $content = $client->getContainer()
85 ->get('doctrine.orm.entity_manager') 101 ->get('doctrine.orm.entity_manager')
86 ->getRepository('WallabagCoreBundle:Entry') 102 ->getRepository('WallabagCoreBundle:Entry')
87 ->findOneByIsArchived(false); 103 ->findOneByIsArchived(false);
88 104
105 if (!$content) {
106 $this->markTestSkipped('No content found in db.');
107 }
108
89 $crawler = $client->request('GET', '/view/'.$content->getId()); 109 $crawler = $client->request('GET', '/view/'.$content->getId());
90 110
91 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 111 $this->assertEquals(200, $client->getResponse()->getStatusCode());
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php
new file mode 100644
index 00000000..54cf5073
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Tests/Controller/SecurityControllerTest.php
@@ -0,0 +1,40 @@
1<?php
2
3namespace Wallabag\CoreBundle\Tests\Controller;
4
5use Wallabag\CoreBundle\Tests\WallabagTestCase;
6
7class SecurityControllerTest extends WallabagTestCase
8{
9 public function testLogin()
10 {
11 $client = $this->getClient();
12
13 $crawler = $client->request('GET', '/new');
14
15 $this->assertEquals(302, $client->getResponse()->getStatusCode());
16 $this->assertContains('login', $client->getResponse()->headers->get('location'));
17 }
18
19 public function testLoginFail()
20 {
21 $client = $this->getClient();
22
23 $crawler = $client->request('GET', '/login');
24
25 $form = $crawler->filter('button[type=submit]')->form();
26 $data = array(
27 '_username' => 'admin',
28 '_password' => 'admin',
29 );
30
31 $client->submit($form, $data);
32
33 $this->assertEquals(302, $client->getResponse()->getStatusCode());
34 $this->assertContains('login', $client->getResponse()->headers->get('location'));
35
36 $crawler = $client->followRedirect();
37
38 $this->assertContains('Bad credentials', $client->getResponse()->getContent());
39 }
40}
diff --git a/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php b/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php
new file mode 100644
index 00000000..5f092318
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php
@@ -0,0 +1,34 @@
1<?php
2
3namespace Wallabag\CoreBundle\Tests;
4
5use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
6use Symfony\Component\BrowserKit\Cookie;
7use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
8
9class WallabagTestCase extends WebTestCase
10{
11 private $client = null;
12
13 public function getClient()
14 {
15 return $this->client;
16 }
17
18 public function setUp()
19 {
20 $this->client = static::createClient();
21 }
22
23 public function logIn()
24 {
25 $crawler = $this->client->request('GET', '/login');
26 $form = $crawler->filter('button[type=submit]')->form();
27 $data = array(
28 '_username' => 'admin',
29 '_password' => 'test',
30 );
31
32 $this->client->submit($form, $data);
33 }
34}