diff --git a/modoboa/admin/handlers.py b/modoboa/admin/handlers.py index a3f402e4b..f2c7a686e 100644 --- a/modoboa/admin/handlers.py +++ b/modoboa/admin/handlers.py @@ -319,10 +319,10 @@ def user_menu(sender, location, user, **kwargs): @receiver(core_signals.user_login) -def user_logged_in(sender, username, password, **kwargs): +def user_logged_in(sender, user, password, **kwargs): """Store user password in session.""" request = lib_signals.get_request() - if hasattr(request.user, "mailbox"): + if hasattr(user, "mailbox"): request.session["password"] = encrypt(password) diff --git a/modoboa/core/signals.py b/modoboa/core/signals.py index ca5118f35..7fd8f7063 100644 --- a/modoboa/core/signals.py +++ b/modoboa/core/signals.py @@ -24,5 +24,5 @@ get_top_notifications = django.dispatch.Signal() # Provides include_all initial_data_loaded = django.dispatch.Signal() # Provides extname register_postfix_maps = django.dispatch.Signal() user_can_set_role = django.dispatch.Signal() # Provides user, role, account -user_login = django.dispatch.Signal() # Provides username, password +user_login = django.dispatch.Signal() # Provides user, password user_logout = django.dispatch.Signal() diff --git a/modoboa/core/tests/test_authentication.py b/modoboa/core/tests/test_authentication.py index 621650e77..9b0e4e306 100644 --- a/modoboa/core/tests/test_authentication.py +++ b/modoboa/core/tests/test_authentication.py @@ -39,9 +39,15 @@ class AuthenticationTestCase(ModoTestCase): def setUpTestData(cls): # NOQA:N802 """Create test data.""" super(AuthenticationTestCase, cls).setUpTestData() - cls.account = factories.UserFactory( - username="user@test.com", groups=("SimpleUsers",) + from modoboa.admin.factories import MailboxFactory + + mailbox = MailboxFactory( + address="user", + domain__name="test.com", + user__username="user@test.com", + user__groups=("SimpleUsers",), ) + cls.account = mailbox.user def test_authentication(self): """Validate simple case.""" @@ -50,6 +56,8 @@ class AuthenticationTestCase(ModoTestCase): response = self.client.post(reverse("core:login"), data) self.assertEqual(response.status_code, 302) self.assertTrue(response.url.endswith(reverse("core:user_index"))) + session = self.client.session + self.assertIn("password", session) response = self.client.post(reverse("core:logout"), {}) self.assertEqual(response.status_code, 302) @@ -58,6 +66,8 @@ class AuthenticationTestCase(ModoTestCase): response = self.client.post(reverse("core:login"), data) self.assertEqual(response.status_code, 302) self.assertTrue(response.url.endswith(reverse("core:dashboard"))) + session = self.client.session + self.assertNotIn("password", session) @mock.patch("django_otp.match_token") @mock.patch("django_otp.login") @@ -77,6 +87,8 @@ class AuthenticationTestCase(ModoTestCase): self.assertContains(response, "This code is invalid") response = self.client.post(url, data) self.assertEqual(response.status_code, 302) + session = self.client.session + self.assertIn("password", session) def test_open_redirect(self): """Check that open redirect is not allowed.""" diff --git a/modoboa/core/views/auth.py b/modoboa/core/views/auth.py index 9b6fb0198..058603293 100644 --- a/modoboa/core/views/auth.py +++ b/modoboa/core/views/auth.py @@ -57,7 +57,11 @@ class LoginViewMixin: return None def login(self, user, rememberme): + encrypted_password = self.request.session.pop("password", None) login(self.request, user) + # FIXME: remove ASAP + if encrypted_password: + self.request.session["password"] = encrypted_password if not rememberme: self.request.session.set_expiry(0) @@ -119,8 +123,8 @@ class LoginView(LoginViewMixin, auth_views.LoginView): self.check_password_hash(user, form) # FIXME: remove ASAP signals.user_login.send( - sender="dologin", - username=user.username, + sender="LoginView", + user=user, password=form.cleaned_data["password"], ) if user.tfa_enabled: