Ensure language is valid

- Do not override locale if user has choosen a locale from the login screen.
- Add some tests about locale url
This commit is contained in:
Jeremy Benoist 2018-10-13 09:24:39 +02:00
parent be417ef236
commit 4d4147b228
No known key found for this signature in database
GPG key ID: BCA73962457ACC3C
6 changed files with 76 additions and 9 deletions

View file

@ -8,6 +8,7 @@ use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Validator\Constraints\Locale as LocaleConstraint;
use Wallabag\CoreBundle\Entity\Config; use Wallabag\CoreBundle\Entity\Config;
use Wallabag\CoreBundle\Entity\TaggingRule; use Wallabag\CoreBundle\Entity\TaggingRule;
use Wallabag\CoreBundle\Form\Type\ChangePasswordType; use Wallabag\CoreBundle\Form\Type\ChangePasswordType;
@ -341,11 +342,13 @@ class ConfigController extends Controller
*/ */
public function setLocaleAction(Request $request, $language = null) public function setLocaleAction(Request $request, $language = null)
{ {
if (null !== $language) { $errors = $this->get('validator')->validate($language, (new LocaleConstraint()));
$this->get('session')->set('_locale', $language);
if (0 === \count($errors)) {
$request->getSession()->set('_locale', $language);
} }
return $this->redirect($request->headers->get('referer')); return $this->redirect($request->headers->get('referer', $this->generateUrl('homepage')));
} }
/** /**

View file

@ -6,8 +6,10 @@ use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
/** /**
* Stores the locale of the user in the session after the * Stores the locale of the user in the session after the login.
* login. This can be used by the LocaleListener afterwards. * If no locale are defined (if user doesn't change it from the login screen), override it with the user's config one.
*
* This can be used by the LocaleListener afterwards.
* *
* @see http://symfony.com/doc/master/cookbook/session/locale_sticky_session.html * @see http://symfony.com/doc/master/cookbook/session/locale_sticky_session.html
*/ */
@ -30,7 +32,7 @@ class UserLocaleListener
{ {
$user = $event->getAuthenticationToken()->getUser(); $user = $event->getAuthenticationToken()->getUser();
if (null !== $user->getConfig()->getLanguage()) { if (null !== $user->getConfig()->getLanguage() && null === $this->session->get('_locale')) {
$this->session->set('_locale', $user->getConfig()->getLanguage()); $this->session->set('_locale', $user->getConfig()->getLanguage());
} }
} }

View file

@ -16,8 +16,8 @@
{% endblock fos_user_content %} {% endblock fos_user_content %}
</div> </div>
<div class="center"> <div class="center">
<a href="{{ path('changeLocale', {'language': 'de'}) }}">Deutsch</a> <a href="{{ path('changeLocale', {'language': 'de'}) }}">Deutsch</a>
<a href="{{ path('changeLocale', {'language': 'en'}) }}">English</a> <a href="{{ path('changeLocale', {'language': 'en'}) }}">English</a>
<a href="{{ path('changeLocale', {'language': 'fr'}) }}">Français</a> <a href="{{ path('changeLocale', {'language': 'fr'}) }}">Français</a>
</div> </div>
</div> </div>

View file

@ -965,4 +965,39 @@ class ConfigControllerTest extends WallabagCoreTestCase
$client->request('GET', '/config/view-mode'); $client->request('GET', '/config/view-mode');
} }
public function testChangeLocaleWithoutReferer()
{
$client = $this->getClient();
$client->request('GET', '/locale/de');
$client->followRedirect();
$this->assertSame('de', $client->getRequest()->getLocale());
$this->assertSame('de', $client->getContainer()->get('session')->get('_locale'));
}
public function testChangeLocaleWithReferer()
{
$client = $this->getClient();
$client->request('GET', '/login');
$client->request('GET', '/locale/de');
$client->followRedirect();
$this->assertSame('de', $client->getRequest()->getLocale());
$this->assertSame('de', $client->getContainer()->get('session')->get('_locale'));
}
public function testChangeLocaleToBadLocale()
{
$client = $this->getClient();
$client->request('GET', '/login');
$client->request('GET', '/locale/yuyuyuyu');
$client->followRedirect();
$this->assertNotSame('yuyuyuyu', $client->getRequest()->getLocale());
$this->assertNotSame('yuyuyuyu', $client->getContainer()->get('session')->get('_locale'));
}
} }

View file

@ -56,4 +56,27 @@ class UserLocaleListenerTest extends TestCase
$this->assertNull($session->get('_locale')); $this->assertNull($session->get('_locale'));
} }
public function testWithLanguageFromSession()
{
$session = new Session(new MockArraySessionStorage());
$listener = new UserLocaleListener($session);
$session->set('_locale', 'de');
$user = new User();
$user->setEnabled(true);
$config = new Config($user);
$config->setLanguage('fr');
$user->setConfig($config);
$userToken = new UsernamePasswordToken($user, '', 'test');
$request = Request::create('/');
$event = new InteractiveLoginEvent($request, $userToken);
$listener->onInteractiveLogin($event);
$this->assertSame('de', $session->get('_locale'));
}
} }

View file

@ -8,6 +8,8 @@ use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Wallabag\CoreBundle\Entity\Config; use Wallabag\CoreBundle\Entity\Config;
use Wallabag\UserBundle\Entity\User; use Wallabag\UserBundle\Entity\User;
use Wallabag\UserBundle\EventListener\CreateConfigListener; use Wallabag\UserBundle\EventListener\CreateConfigListener;
@ -22,6 +24,7 @@ class CreateConfigListenerTest extends TestCase
protected function setUp() protected function setUp()
{ {
$session = new Session(new MockArraySessionStorage());
$this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager') $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
@ -34,7 +37,8 @@ class CreateConfigListenerTest extends TestCase
'fr', 'fr',
1, 1,
1, 1,
1 1,
$session
); );
$this->dispatcher = new EventDispatcher(); $this->dispatcher = new EventDispatcher();