aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag/UserBundle
diff options
context:
space:
mode:
Diffstat (limited to 'src/Wallabag/UserBundle')
-rw-r--r--src/Wallabag/UserBundle/Controller/ManageController.php48
-rw-r--r--src/Wallabag/UserBundle/DataFixtures/UserFixtures.php (renamed from src/Wallabag/UserBundle/DataFixtures/ORM/LoadUserData.php)15
-rw-r--r--src/Wallabag/UserBundle/Entity/User.php152
-rw-r--r--src/Wallabag/UserBundle/EventListener/CreateConfigListener.php13
-rw-r--r--src/Wallabag/UserBundle/Form/UserType.php16
-rw-r--r--src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php21
-rw-r--r--src/Wallabag/UserBundle/Repository/UserRepository.php8
-rw-r--r--src/Wallabag/UserBundle/Resources/config/services.yml3
-rw-r--r--src/Wallabag/UserBundle/Resources/views/Authentication/form.html.twig20
-rw-r--r--src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig11
-rw-r--r--src/Wallabag/UserBundle/Resources/views/Registration/register_content.html.twig1
-rw-r--r--src/Wallabag/UserBundle/Resources/views/TwoFactor/email_auth_code.html.twig2
-rw-r--r--src/Wallabag/UserBundle/Resources/views/layout.html.twig5
13 files changed, 210 insertions, 105 deletions
diff --git a/src/Wallabag/UserBundle/Controller/ManageController.php b/src/Wallabag/UserBundle/Controller/ManageController.php
index f3de656f..1122f8f0 100644
--- a/src/Wallabag/UserBundle/Controller/ManageController.php
+++ b/src/Wallabag/UserBundle/Controller/ManageController.php
@@ -7,10 +7,9 @@ use FOS\UserBundle\FOSUserEvents;
7use Pagerfanta\Adapter\DoctrineORMAdapter; 7use Pagerfanta\Adapter\DoctrineORMAdapter;
8use Pagerfanta\Exception\OutOfRangeCurrentPageException; 8use Pagerfanta\Exception\OutOfRangeCurrentPageException;
9use Pagerfanta\Pagerfanta; 9use Pagerfanta\Pagerfanta;
10use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
11use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
12use Symfony\Bundle\FrameworkBundle\Controller\Controller; 10use Symfony\Bundle\FrameworkBundle\Controller\Controller;
13use Symfony\Component\HttpFoundation\Request; 11use Symfony\Component\HttpFoundation\Request;
12use Symfony\Component\Routing\Annotation\Route;
14use Wallabag\UserBundle\Entity\User; 13use Wallabag\UserBundle\Entity\User;
15use Wallabag\UserBundle\Form\SearchUserType; 14use Wallabag\UserBundle\Form\SearchUserType;
16 15
@@ -22,8 +21,7 @@ class ManageController extends Controller
22 /** 21 /**
23 * Creates a new User entity. 22 * Creates a new User entity.
24 * 23 *
25 * @Route("/new", name="user_new") 24 * @Route("/new", name="user_new", methods={"GET", "POST"})
26 * @Method({"GET", "POST"})
27 */ 25 */
28 public function newAction(Request $request) 26 public function newAction(Request $request)
29 { 27 {
@@ -60,19 +58,33 @@ class ManageController extends Controller
60 /** 58 /**
61 * Displays a form to edit an existing User entity. 59 * Displays a form to edit an existing User entity.
62 * 60 *
63 * @Route("/{id}/edit", name="user_edit") 61 * @Route("/{id}/edit", name="user_edit", methods={"GET", "POST"})
64 * @Method({"GET", "POST"})
65 */ 62 */
66 public function editAction(Request $request, User $user) 63 public function editAction(Request $request, User $user)
67 { 64 {
65 $userManager = $this->container->get('fos_user.user_manager');
66
68 $deleteForm = $this->createDeleteForm($user); 67 $deleteForm = $this->createDeleteForm($user);
69 $editForm = $this->createForm('Wallabag\UserBundle\Form\UserType', $user); 68 $form = $this->createForm('Wallabag\UserBundle\Form\UserType', $user);
70 $editForm->handleRequest($request); 69 $form->handleRequest($request);
71 70
72 if ($editForm->isSubmitted() && $editForm->isValid()) { 71 // `googleTwoFactor` isn't a field within the User entity, we need to define it's value in a different way
73 $em = $this->getDoctrine()->getManager(); 72 if ($this->getParameter('twofactor_auth') && true === $user->isGoogleAuthenticatorEnabled() && false === $form->isSubmitted()) {
74 $em->persist($user); 73 $form->get('googleTwoFactor')->setData(true);
75 $em->flush(); 74 }
75
76 if ($form->isSubmitted() && $form->isValid()) {
77 // handle creation / reset of the OTP secret if checkbox changed from the previous state
78 if ($this->getParameter('twofactor_auth')) {
79 if (true === $form->get('googleTwoFactor')->getData() && false === $user->isGoogleAuthenticatorEnabled()) {
80 $user->setGoogleAuthenticatorSecret($this->get('scheb_two_factor.security.google_authenticator')->generateSecret());
81 $user->setEmailTwoFactor(false);
82 } elseif (false === $form->get('googleTwoFactor')->getData() && true === $user->isGoogleAuthenticatorEnabled()) {
83 $user->setGoogleAuthenticatorSecret(null);
84 }
85 }
86
87 $userManager->updateUser($user);
76 88
77 $this->get('session')->getFlashBag()->add( 89 $this->get('session')->getFlashBag()->add(
78 'notice', 90 'notice',
@@ -84,7 +96,7 @@ class ManageController extends Controller
84 96
85 return $this->render('WallabagUserBundle:Manage:edit.html.twig', [ 97 return $this->render('WallabagUserBundle:Manage:edit.html.twig', [
86 'user' => $user, 98 'user' => $user,
87 'edit_form' => $editForm->createView(), 99 'edit_form' => $form->createView(),
88 'delete_form' => $deleteForm->createView(), 100 'delete_form' => $deleteForm->createView(),
89 'twofactor_auth' => $this->getParameter('twofactor_auth'), 101 'twofactor_auth' => $this->getParameter('twofactor_auth'),
90 ]); 102 ]);
@@ -93,8 +105,7 @@ class ManageController extends Controller
93 /** 105 /**
94 * Deletes a User entity. 106 * Deletes a User entity.
95 * 107 *
96 * @Route("/{id}", name="user_delete") 108 * @Route("/{id}", name="user_delete", methods={"DELETE"})
97 * @Method("DELETE")
98 */ 109 */
99 public function deleteAction(Request $request, User $user) 110 public function deleteAction(Request $request, User $user)
100 { 111 {
@@ -116,8 +127,7 @@ class ManageController extends Controller
116 } 127 }
117 128
118 /** 129 /**
119 * @param Request $request 130 * @param int $page
120 * @param int $page
121 * 131 *
122 * @Route("/list/{page}", name="user_index", defaults={"page" = 1}) 132 * @Route("/list/{page}", name="user_index", defaults={"page" = 1})
123 * 133 *
@@ -135,8 +145,6 @@ class ManageController extends Controller
135 $form->handleRequest($request); 145 $form->handleRequest($request);
136 146
137 if ($form->isSubmitted() && $form->isValid()) { 147 if ($form->isSubmitted() && $form->isValid()) {
138 $this->get('logger')->info('searching users');
139
140 $searchTerm = (isset($request->get('search_user')['term']) ? $request->get('search_user')['term'] : ''); 148 $searchTerm = (isset($request->get('search_user')['term']) ? $request->get('search_user')['term'] : '');
141 149
142 $qb = $em->getRepository('WallabagUserBundle:User')->getQueryBuilderForSearch($searchTerm); 150 $qb = $em->getRepository('WallabagUserBundle:User')->getQueryBuilderForSearch($searchTerm);
@@ -161,7 +169,7 @@ class ManageController extends Controller
161 } 169 }
162 170
163 /** 171 /**
164 * Creates a form to delete a User entity. 172 * Create a form to delete a User entity.
165 * 173 *
166 * @param User $user The User entity 174 * @param User $user The User entity
167 * 175 *
diff --git a/src/Wallabag/UserBundle/DataFixtures/ORM/LoadUserData.php b/src/Wallabag/UserBundle/DataFixtures/UserFixtures.php
index 26dbda3b..1e375e09 100644
--- a/src/Wallabag/UserBundle/DataFixtures/ORM/LoadUserData.php
+++ b/src/Wallabag/UserBundle/DataFixtures/UserFixtures.php
@@ -1,13 +1,12 @@
1<?php 1<?php
2 2
3namespace Wallabag\UserBundle\DataFixtures\ORM; 3namespace Wallabag\UserBundle\DataFixtures;
4 4
5use Doctrine\Common\DataFixtures\AbstractFixture; 5use Doctrine\Bundle\FixturesBundle\Fixture;
6use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
7use Doctrine\Common\Persistence\ObjectManager; 6use Doctrine\Common\Persistence\ObjectManager;
8use Wallabag\UserBundle\Entity\User; 7use Wallabag\UserBundle\Entity\User;
9 8
10class LoadUserData extends AbstractFixture implements OrderedFixtureInterface 9class UserFixtures extends Fixture
11{ 10{
12 /** 11 /**
13 * {@inheritdoc} 12 * {@inheritdoc}
@@ -50,12 +49,4 @@ class LoadUserData extends AbstractFixture implements OrderedFixtureInterface
50 49
51 $manager->flush(); 50 $manager->flush();
52 } 51 }
53
54 /**
55 * {@inheritdoc}
56 */
57 public function getOrder()
58 {
59 return 10;
60 }
61} 52}
diff --git a/src/Wallabag/UserBundle/Entity/User.php b/src/Wallabag/UserBundle/Entity/User.php
index 48446e3c..aeab761d 100644
--- a/src/Wallabag/UserBundle/Entity/User.php
+++ b/src/Wallabag/UserBundle/Entity/User.php
@@ -8,8 +8,9 @@ use FOS\UserBundle\Model\User as BaseUser;
8use JMS\Serializer\Annotation\Accessor; 8use JMS\Serializer\Annotation\Accessor;
9use JMS\Serializer\Annotation\Groups; 9use JMS\Serializer\Annotation\Groups;
10use JMS\Serializer\Annotation\XmlRoot; 10use JMS\Serializer\Annotation\XmlRoot;
11use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface; 11use Scheb\TwoFactorBundle\Model\BackupCodeInterface;
12use Scheb\TwoFactorBundle\Model\TrustedComputerInterface; 12use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface as EmailTwoFactorInterface;
13use Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface as GoogleTwoFactorInterface;
13use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; 14use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
14use Symfony\Component\Security\Core\User\UserInterface; 15use Symfony\Component\Security\Core\User\UserInterface;
15use Wallabag\ApiBundle\Entity\Client; 16use Wallabag\ApiBundle\Entity\Client;
@@ -28,7 +29,7 @@ use Wallabag\CoreBundle\Helper\EntityTimestampsTrait;
28 * @UniqueEntity("email") 29 * @UniqueEntity("email")
29 * @UniqueEntity("username") 30 * @UniqueEntity("username")
30 */ 31 */
31class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface 32class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorInterface, BackupCodeInterface
32{ 33{
33 use EntityTimestampsTrait; 34 use EntityTimestampsTrait;
34 35
@@ -123,16 +124,21 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
123 private $authCode; 124 private $authCode;
124 125
125 /** 126 /**
126 * @var bool 127 * @ORM\Column(name="googleAuthenticatorSecret", type="string", nullable=true)
127 *
128 * @ORM\Column(type="boolean")
129 */ 128 */
130 private $twoFactorAuthentication = false; 129 private $googleAuthenticatorSecret;
131 130
132 /** 131 /**
133 * @ORM\Column(type="json_array", nullable=true) 132 * @ORM\Column(type="json_array", nullable=true)
134 */ 133 */
135 private $trusted; 134 private $backupCodes;
135
136 /**
137 * @var bool
138 *
139 * @ORM\Column(type="boolean")
140 */
141 private $emailTwoFactor = false;
136 142
137 public function __construct() 143 public function __construct()
138 { 144 {
@@ -182,8 +188,6 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
182 } 188 }
183 189
184 /** 190 /**
185 * @param Entry $entry
186 *
187 * @return User 191 * @return User
188 */ 192 */
189 public function addEntry(Entry $entry) 193 public function addEntry(Entry $entry)
@@ -233,54 +237,122 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
233 /** 237 /**
234 * @return bool 238 * @return bool
235 */ 239 */
236 public function isTwoFactorAuthentication() 240 public function isEmailTwoFactor()
237 { 241 {
238 return $this->twoFactorAuthentication; 242 return $this->emailTwoFactor;
239 } 243 }
240 244
241 /** 245 /**
242 * @param bool $twoFactorAuthentication 246 * @param bool $emailTwoFactor
243 */ 247 */
244 public function setTwoFactorAuthentication($twoFactorAuthentication) 248 public function setEmailTwoFactor($emailTwoFactor)
245 { 249 {
246 $this->twoFactorAuthentication = $twoFactorAuthentication; 250 $this->emailTwoFactor = $emailTwoFactor;
247 } 251 }
248 252
249 public function isEmailAuthEnabled() 253 /**
254 * Used in the user config form to be "like" the email option.
255 */
256 public function isGoogleTwoFactor()
250 { 257 {
251 return $this->twoFactorAuthentication; 258 return $this->isGoogleAuthenticatorEnabled();
252 } 259 }
253 260
254 public function getEmailAuthCode() 261 /**
262 * {@inheritdoc}
263 */
264 public function isEmailAuthEnabled(): bool
265 {
266 return $this->emailTwoFactor;
267 }
268
269 /**
270 * {@inheritdoc}
271 */
272 public function getEmailAuthCode(): string
255 { 273 {
256 return $this->authCode; 274 return $this->authCode;
257 } 275 }
258 276
259 public function setEmailAuthCode($authCode) 277 /**
278 * {@inheritdoc}
279 */
280 public function setEmailAuthCode(string $authCode): void
260 { 281 {
261 $this->authCode = $authCode; 282 $this->authCode = $authCode;
262 } 283 }
263 284
264 public function addTrustedComputer($token, \DateTime $validUntil) 285 /**
286 * {@inheritdoc}
287 */
288 public function getEmailAuthRecipient(): string
265 { 289 {
266 $this->trusted[$token] = $validUntil->format('r'); 290 return $this->email;
267 } 291 }
268 292
269 public function isTrustedComputer($token) 293 /**
294 * {@inheritdoc}
295 */
296 public function isGoogleAuthenticatorEnabled(): bool
270 { 297 {
271 if (isset($this->trusted[$token])) { 298 return $this->googleAuthenticatorSecret ? true : false;
272 $now = new \DateTime(); 299 }
273 $validUntil = new \DateTime($this->trusted[$token]);
274 300
275 return $now < $validUntil; 301 /**
276 } 302 * {@inheritdoc}
303 */
304 public function getGoogleAuthenticatorUsername(): string
305 {
306 return $this->username;
307 }
277 308
278 return false; 309 /**
310 * {@inheritdoc}
311 */
312 public function getGoogleAuthenticatorSecret(): string
313 {
314 return $this->googleAuthenticatorSecret;
315 }
316
317 /**
318 * {@inheritdoc}
319 */
320 public function setGoogleAuthenticatorSecret(?string $googleAuthenticatorSecret): void
321 {
322 $this->googleAuthenticatorSecret = $googleAuthenticatorSecret;
323 }
324
325 public function setBackupCodes(array $codes = null)
326 {
327 $this->backupCodes = $codes;
328 }
329
330 public function getBackupCodes()
331 {
332 return $this->backupCodes;
333 }
334
335 /**
336 * {@inheritdoc}
337 */
338 public function isBackupCode(string $code): bool
339 {
340 return false === $this->findBackupCode($code) ? false : true;
341 }
342
343 /**
344 * {@inheritdoc}
345 */
346 public function invalidateBackupCode(string $code): void
347 {
348 $key = $this->findBackupCode($code);
349
350 if (false !== $key) {
351 unset($this->backupCodes[$key]);
352 }
279 } 353 }
280 354
281 /** 355 /**
282 * @param Client $client
283 *
284 * @return User 356 * @return User
285 */ 357 */
286 public function addClient(Client $client) 358 public function addClient(Client $client)
@@ -309,4 +381,24 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
309 return $this->clients->first(); 381 return $this->clients->first();
310 } 382 }
311 } 383 }
384
385 /**
386 * Try to find a backup code from the list of backup codes of the current user.
387 *
388 * @param string $code Given code from the user
389 *
390 * @return string|false
391 */
392 private function findBackupCode(string $code)
393 {
394 foreach ($this->backupCodes as $key => $backupCode) {
395 // backup code are hashed using `password_hash`
396 // see ConfigController->otpAppAction
397 if (password_verify($code, $backupCode)) {
398 return $key;
399 }
400 }
401
402 return false;
403 }
312} 404}
diff --git a/src/Wallabag/UserBundle/EventListener/CreateConfigListener.php b/src/Wallabag/UserBundle/EventListener/CreateConfigListener.php
index e4d55c19..81954213 100644
--- a/src/Wallabag/UserBundle/EventListener/CreateConfigListener.php
+++ b/src/Wallabag/UserBundle/EventListener/CreateConfigListener.php
@@ -6,6 +6,7 @@ use Doctrine\ORM\EntityManager;
6use FOS\UserBundle\Event\UserEvent; 6use FOS\UserBundle\Event\UserEvent;
7use FOS\UserBundle\FOSUserEvents; 7use FOS\UserBundle\FOSUserEvents;
8use Symfony\Component\EventDispatcher\EventSubscriberInterface; 8use Symfony\Component\EventDispatcher\EventSubscriberInterface;
9use Symfony\Component\HttpFoundation\Session\Session;
9use Wallabag\CoreBundle\Entity\Config; 10use Wallabag\CoreBundle\Entity\Config;
10 11
11/** 12/**
@@ -17,22 +18,24 @@ class CreateConfigListener implements EventSubscriberInterface
17 private $em; 18 private $em;
18 private $theme; 19 private $theme;
19 private $itemsOnPage; 20 private $itemsOnPage;
20 private $rssLimit; 21 private $feedLimit;
21 private $language; 22 private $language;
22 private $readingSpeed; 23 private $readingSpeed;
23 private $actionMarkAsRead; 24 private $actionMarkAsRead;
24 private $listMode; 25 private $listMode;
26 private $session;
25 27
26 public function __construct(EntityManager $em, $theme, $itemsOnPage, $rssLimit, $language, $readingSpeed, $actionMarkAsRead, $listMode) 28 public function __construct(EntityManager $em, $theme, $itemsOnPage, $feedLimit, $language, $readingSpeed, $actionMarkAsRead, $listMode, Session $session)
27 { 29 {
28 $this->em = $em; 30 $this->em = $em;
29 $this->theme = $theme; 31 $this->theme = $theme;
30 $this->itemsOnPage = $itemsOnPage; 32 $this->itemsOnPage = $itemsOnPage;
31 $this->rssLimit = $rssLimit; 33 $this->feedLimit = $feedLimit;
32 $this->language = $language; 34 $this->language = $language;
33 $this->readingSpeed = $readingSpeed; 35 $this->readingSpeed = $readingSpeed;
34 $this->actionMarkAsRead = $actionMarkAsRead; 36 $this->actionMarkAsRead = $actionMarkAsRead;
35 $this->listMode = $listMode; 37 $this->listMode = $listMode;
38 $this->session = $session;
36 } 39 }
37 40
38 public static function getSubscribedEvents() 41 public static function getSubscribedEvents()
@@ -51,8 +54,8 @@ class CreateConfigListener implements EventSubscriberInterface
51 $config = new Config($event->getUser()); 54 $config = new Config($event->getUser());
52 $config->setTheme($this->theme); 55 $config->setTheme($this->theme);
53 $config->setItemsPerPage($this->itemsOnPage); 56 $config->setItemsPerPage($this->itemsOnPage);
54 $config->setRssLimit($this->rssLimit); 57 $config->setFeedLimit($this->feedLimit);
55 $config->setLanguage($this->language); 58 $config->setLanguage($this->session->get('_locale', $this->language));
56 $config->setReadingSpeed($this->readingSpeed); 59 $config->setReadingSpeed($this->readingSpeed);
57 $config->setActionMarkAsRead($this->actionMarkAsRead); 60 $config->setActionMarkAsRead($this->actionMarkAsRead);
58 $config->setListMode($this->listMode); 61 $config->setListMode($this->listMode);
diff --git a/src/Wallabag/UserBundle/Form/UserType.php b/src/Wallabag/UserBundle/Form/UserType.php
index 56fea640..03fad971 100644
--- a/src/Wallabag/UserBundle/Form/UserType.php
+++ b/src/Wallabag/UserBundle/Form/UserType.php
@@ -12,10 +12,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
12 12
13class UserType extends AbstractType 13class UserType extends AbstractType
14{ 14{
15 /**
16 * @param FormBuilderInterface $builder
17 * @param array $options
18 */
19 public function buildForm(FormBuilderInterface $builder, array $options) 15 public function buildForm(FormBuilderInterface $builder, array $options)
20 { 16 {
21 $builder 17 $builder
@@ -35,9 +31,14 @@ class UserType extends AbstractType
35 'required' => false, 31 'required' => false,
36 'label' => 'user.form.enabled_label', 32 'label' => 'user.form.enabled_label',
37 ]) 33 ])
38 ->add('twoFactorAuthentication', CheckboxType::class, [ 34 ->add('emailTwoFactor', CheckboxType::class, [
39 'required' => false, 35 'required' => false,
40 'label' => 'user.form.twofactor_label', 36 'label' => 'user.form.twofactor_email_label',
37 ])
38 ->add('googleTwoFactor', CheckboxType::class, [
39 'required' => false,
40 'label' => 'user.form.twofactor_google_label',
41 'mapped' => false,
41 ]) 42 ])
42 ->add('save', SubmitType::class, [ 43 ->add('save', SubmitType::class, [
43 'label' => 'user.form.save', 44 'label' => 'user.form.save',
@@ -45,9 +46,6 @@ class UserType extends AbstractType
45 ; 46 ;
46 } 47 }
47 48
48 /**
49 * @param OptionsResolver $resolver
50 */
51 public function configureOptions(OptionsResolver $resolver) 49 public function configureOptions(OptionsResolver $resolver)
52 { 50 {
53 $resolver->setDefaults([ 51 $resolver->setDefaults([
diff --git a/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php b/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php
index aed805c9..4eea444f 100644
--- a/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php
+++ b/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php
@@ -4,6 +4,7 @@ namespace Wallabag\UserBundle\Mailer;
4 4
5use Scheb\TwoFactorBundle\Mailer\AuthCodeMailerInterface; 5use Scheb\TwoFactorBundle\Mailer\AuthCodeMailerInterface;
6use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface; 6use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface;
7use Twig\Environment;
7 8
8/** 9/**
9 * Custom mailer for TwoFactorBundle email. 10 * Custom mailer for TwoFactorBundle email.
@@ -21,7 +22,7 @@ class AuthCodeMailer implements AuthCodeMailerInterface
21 /** 22 /**
22 * Twig to render the html's email. 23 * Twig to render the html's email.
23 * 24 *
24 * @var \Twig_Environment 25 * @var Environment
25 */ 26 */
26 private $twig; 27 private $twig;
27 28
@@ -56,14 +57,12 @@ class AuthCodeMailer implements AuthCodeMailerInterface
56 /** 57 /**
57 * Initialize the auth code mailer with the SwiftMailer object. 58 * Initialize the auth code mailer with the SwiftMailer object.
58 * 59 *
59 * @param \Swift_Mailer $mailer 60 * @param string $senderEmail
60 * @param \Twig_Environment $twig 61 * @param string $senderName
61 * @param string $senderEmail 62 * @param string $supportUrl wallabag support url
62 * @param string $senderName 63 * @param string $wallabagUrl wallabag instance url
63 * @param string $supportUrl wallabag support url
64 * @param string $wallabagUrl wallabag instance url
65 */ 64 */
66 public function __construct(\Swift_Mailer $mailer, \Twig_Environment $twig, $senderEmail, $senderName, $supportUrl, $wallabagUrl) 65 public function __construct(\Swift_Mailer $mailer, Environment $twig, $senderEmail, $senderName, $supportUrl, $wallabagUrl)
67 { 66 {
68 $this->mailer = $mailer; 67 $this->mailer = $mailer;
69 $this->twig = $twig; 68 $this->twig = $twig;
@@ -75,10 +74,8 @@ class AuthCodeMailer implements AuthCodeMailerInterface
75 74
76 /** 75 /**
77 * Send the auth code to the user via email. 76 * Send the auth code to the user via email.
78 *
79 * @param TwoFactorInterface $user
80 */ 77 */
81 public function sendAuthCode(TwoFactorInterface $user) 78 public function sendAuthCode(TwoFactorInterface $user): void
82 { 79 {
83 $template = $this->twig->loadTemplate('WallabagUserBundle:TwoFactor:email_auth_code.html.twig'); 80 $template = $this->twig->loadTemplate('WallabagUserBundle:TwoFactor:email_auth_code.html.twig');
84 81
@@ -97,7 +94,7 @@ class AuthCodeMailer implements AuthCodeMailerInterface
97 94
98 $message = new \Swift_Message(); 95 $message = new \Swift_Message();
99 $message 96 $message
100 ->setTo($user->getEmail()) 97 ->setTo($user->getEmailAuthRecipient())
101 ->setFrom($this->senderEmail, $this->senderName) 98 ->setFrom($this->senderEmail, $this->senderName)
102 ->setSubject($subject) 99 ->setSubject($subject)
103 ->setBody($bodyText, 'text/plain') 100 ->setBody($bodyText, 'text/plain')
diff --git a/src/Wallabag/UserBundle/Repository/UserRepository.php b/src/Wallabag/UserBundle/Repository/UserRepository.php
index be693d3b..4abd55f1 100644
--- a/src/Wallabag/UserBundle/Repository/UserRepository.php
+++ b/src/Wallabag/UserBundle/Repository/UserRepository.php
@@ -9,18 +9,18 @@ use Wallabag\UserBundle\Entity\User;
9class UserRepository extends EntityRepository 9class UserRepository extends EntityRepository
10{ 10{
11 /** 11 /**
12 * Find a user by its username and rss roken. 12 * Find a user by its username and Feed token.
13 * 13 *
14 * @param string $username 14 * @param string $username
15 * @param string $rssToken 15 * @param string $feedToken
16 * 16 *
17 * @return User|null 17 * @return User|null
18 */ 18 */
19 public function findOneByUsernameAndRsstoken($username, $rssToken) 19 public function findOneByUsernameAndFeedtoken($username, $feedToken)
20 { 20 {
21 return $this->createQueryBuilder('u') 21 return $this->createQueryBuilder('u')
22 ->leftJoin('u.config', 'c') 22 ->leftJoin('u.config', 'c')
23 ->where('c.rssToken = :rss_token')->setParameter('rss_token', $rssToken) 23 ->where('c.feedToken = :feed_token')->setParameter('feed_token', $feedToken)
24 ->andWhere('u.username = :username')->setParameter('username', $username) 24 ->andWhere('u.username = :username')->setParameter('username', $username)
25 ->getQuery() 25 ->getQuery()
26 ->getOneOrNullResult(); 26 ->getOneOrNullResult();
diff --git a/src/Wallabag/UserBundle/Resources/config/services.yml b/src/Wallabag/UserBundle/Resources/config/services.yml
index d3925de3..2dcf3011 100644
--- a/src/Wallabag/UserBundle/Resources/config/services.yml
+++ b/src/Wallabag/UserBundle/Resources/config/services.yml
@@ -28,11 +28,12 @@ services:
28 - "@doctrine.orm.entity_manager" 28 - "@doctrine.orm.entity_manager"
29 - "%wallabag_core.theme%" 29 - "%wallabag_core.theme%"
30 - "%wallabag_core.items_on_page%" 30 - "%wallabag_core.items_on_page%"
31 - "%wallabag_core.rss_limit%" 31 - "%wallabag_core.feed_limit%"
32 - "%wallabag_core.language%" 32 - "%wallabag_core.language%"
33 - "%wallabag_core.reading_speed%" 33 - "%wallabag_core.reading_speed%"
34 - "%wallabag_core.action_mark_as_read%" 34 - "%wallabag_core.action_mark_as_read%"
35 - "%wallabag_core.list_mode%" 35 - "%wallabag_core.list_mode%"
36 - "@session"
36 tags: 37 tags:
37 - { name: kernel.event_subscriber } 38 - { name: kernel.event_subscriber }
38 39
diff --git a/src/Wallabag/UserBundle/Resources/views/Authentication/form.html.twig b/src/Wallabag/UserBundle/Resources/views/Authentication/form.html.twig
index c8471bdd..e15ed255 100644
--- a/src/Wallabag/UserBundle/Resources/views/Authentication/form.html.twig
+++ b/src/Wallabag/UserBundle/Resources/views/Authentication/form.html.twig
@@ -1,7 +1,8 @@
1{# Override `vendor/scheb/two-factor-bundle/Resources/views/Authentication/form.html.twig` #}
1{% extends "WallabagUserBundle::layout.html.twig" %} 2{% extends "WallabagUserBundle::layout.html.twig" %}
2 3
3{% block fos_user_content %} 4{% block fos_user_content %}
4<form class="form" action="" method="post"> 5<form class="form" action="{{ path("2fa_login_check") }}" method="post">
5 <div class="card-content"> 6 <div class="card-content">
6 <div class="row"> 7 <div class="row">
7 8
@@ -9,15 +10,20 @@
9 <p class="error">{{ flashMessage|trans }}</p> 10 <p class="error">{{ flashMessage|trans }}</p>
10 {% endfor %} 11 {% endfor %}
11 12
13 {# Authentication errors #}
14 {% if authenticationError %}
15 <p class="error">{{ authenticationError|trans(authenticationErrorData, 'SchebTwoFactorBundle') }}</p>
16 {% endif %}
17
12 <div class="input-field col s12"> 18 <div class="input-field col s12">
13 <label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label> 19 <label for="_auth_code">{{ "auth_code"|trans({}, 'SchebTwoFactorBundle') }}</label>
14 <input id="_auth_code" type="text" autocomplete="off" name="_auth_code" /> 20 <input id="_auth_code" type="text" autocomplete="off" name="{{ authCodeParameterName }}" />
15 </div> 21 </div>
16 22
17 {% if useTrustedOption %} 23 {% if displayTrustedOption %}
18 <div class="input-field col s12"> 24 <div class="input-field col s12">
19 <input id="_trusted" type="checkbox" name="_trusted" /> 25 <input id="_trusted" type="checkbox" name="{{ trustedParameterName }}" />
20 <label for="_trusted">{{ "scheb_two_factor.trusted"|trans }}</label> 26 <label for="_trusted">{{ "trusted"|trans({}, 'SchebTwoFactorBundle') }}</label>
21 </div> 27 </div>
22 {% endif %} 28 {% endif %}
23 </div> 29 </div>
@@ -25,7 +31,7 @@
25 <div class="card-action center"> 31 <div class="card-action center">
26 <a href="{{ path('fos_user_security_logout') }}" class="waves-effect waves-light grey btn">{{ 'security.login.cancel'|trans }}</a> 32 <a href="{{ path('fos_user_security_logout') }}" class="waves-effect waves-light grey btn">{{ 'security.login.cancel'|trans }}</a>
27 <button class="btn waves-effect waves-light" type="submit" name="send"> 33 <button class="btn waves-effect waves-light" type="submit" name="send">
28 {{ "scheb_two_factor.login"|trans }} 34 {{ "login"|trans({}, 'SchebTwoFactorBundle') }}
29 <i class="material-icons right">send</i> 35 <i class="material-icons right">send</i>
30 </button> 36 </button>
31 </div> 37 </div>
diff --git a/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig b/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig
index 3ffd15f5..2de8f3a5 100644
--- a/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig
+++ b/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig
@@ -50,9 +50,14 @@
50 {% if twofactor_auth %} 50 {% if twofactor_auth %}
51 <div class="row"> 51 <div class="row">
52 <div class="input-field col s12"> 52 <div class="input-field col s12">
53 {{ form_widget(edit_form.twoFactorAuthentication) }} 53 {{ form_widget(edit_form.emailTwoFactor) }}
54 {{ form_label(edit_form.twoFactorAuthentication) }} 54 {{ form_label(edit_form.emailTwoFactor) }}
55 {{ form_errors(edit_form.twoFactorAuthentication) }} 55 {{ form_errors(edit_form.emailTwoFactor) }}
56 </div>
57 <div class="input-field col s12">
58 {{ form_widget(edit_form.googleTwoFactor) }}
59 {{ form_label(edit_form.googleTwoFactor) }}
60 {{ form_errors(edit_form.googleTwoFactor) }}
56 </div> 61 </div>
57 </div> 62 </div>
58 {% endif %} 63 {% endif %}
diff --git a/src/Wallabag/UserBundle/Resources/views/Registration/register_content.html.twig b/src/Wallabag/UserBundle/Resources/views/Registration/register_content.html.twig
index d0a85fc7..85cd4f0d 100644
--- a/src/Wallabag/UserBundle/Resources/views/Registration/register_content.html.twig
+++ b/src/Wallabag/UserBundle/Resources/views/Registration/register_content.html.twig
@@ -3,7 +3,6 @@
3{{ form_start(form, {'method': 'post', 'action': path('fos_user_registration_register'), 'attr': {'class': 'fos_user_registration_register'}}) }} 3{{ form_start(form, {'method': 'post', 'action': path('fos_user_registration_register'), 'attr': {'class': 'fos_user_registration_register'}}) }}
4 <div class="card-content"> 4 <div class="card-content">
5 <div class="row"> 5 <div class="row">
6
7 {{ form_widget(form._token) }} 6 {{ form_widget(form._token) }}
8 7
9 {% for flashMessage in app.session.flashbag.get('notice') %} 8 {% for flashMessage in app.session.flashbag.get('notice') %}
diff --git a/src/Wallabag/UserBundle/Resources/views/TwoFactor/email_auth_code.html.twig b/src/Wallabag/UserBundle/Resources/views/TwoFactor/email_auth_code.html.twig
index ecc1d79a..cd5aaf40 100644
--- a/src/Wallabag/UserBundle/Resources/views/TwoFactor/email_auth_code.html.twig
+++ b/src/Wallabag/UserBundle/Resources/views/TwoFactor/email_auth_code.html.twig
@@ -74,7 +74,7 @@
74 74
75 <table cellpadding="0" cellspacing="0" border="0" align="center" id="card"> 75 <table cellpadding="0" cellspacing="0" border="0" align="center" id="card">
76 <tr> 76 <tr>
77 <td style="padding: 20px;" width="96px" valign="top"><img class="image_fix" src="{{ absolute_url(asset('wallassets/themes/_global/img/logo-other_themes.png')) }}" alt="logo" title="{{ wallabag_url }}" style="width: 96px; height: 96px;" /></td> 77 <td style="padding: 20px;" width="96px" valign="top"><img class="image_fix" src="{{ absolute_url(asset('wallassets/themes/_global/img/logo-square.svg')) }}" alt="logo" title="{{ wallabag_url }}" style="width: 96px; height: 96px;" /></td>
78 <td style="padding: 20px; padding-left: 0;" valign="top" id="cell_desc"> 78 <td style="padding: 20px; padding-left: 0;" valign="top" id="cell_desc">
79 <h1>wallabag</h1> 79 <h1>wallabag</h1>
80 <h5>{{ "auth_code.on"|trans({}, 'wallabag_user') }} {{ wallabag_url }}</h5> 80 <h5>{{ "auth_code.on"|trans({}, 'wallabag_user') }} {{ wallabag_url }}</h5>
diff --git a/src/Wallabag/UserBundle/Resources/views/layout.html.twig b/src/Wallabag/UserBundle/Resources/views/layout.html.twig
index f97e9870..a47b31d0 100644
--- a/src/Wallabag/UserBundle/Resources/views/layout.html.twig
+++ b/src/Wallabag/UserBundle/Resources/views/layout.html.twig
@@ -15,6 +15,11 @@
15 {% block fos_user_content %} 15 {% block fos_user_content %}
16 {% endblock fos_user_content %} 16 {% endblock fos_user_content %}
17 </div> 17 </div>
18 <div class="center">
19 <a href="{{ path('changeLocale', {'language': 'de'}) }}">Deutsch</a> –
20 <a href="{{ path('changeLocale', {'language': 'en'}) }}">English</a> –
21 <a href="{{ path('changeLocale', {'language': 'fr'}) }}">Français</a>
22 </div>
18 </div> 23 </div>
19</main> 24</main>
20{% endblock %} 25{% endblock %}