From 64ca18891e177b5ee21f3c8486c08aaf790c1c90 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 16 Nov 2015 14:12:16 +0100 Subject: [PATCH 1/3] Redirect user to profile on first login. see #596 --- .../migrations/0007_auto_20151116_1349.py | 31 +++++++++++++++++++ modoboa/core/models.py | 2 +- modoboa/core/views/auth.py | 17 ++++++---- 3 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 modoboa/core/migrations/0007_auto_20151116_1349.py diff --git a/modoboa/core/migrations/0007_auto_20151116_1349.py b/modoboa/core/migrations/0007_auto_20151116_1349.py new file mode 100644 index 000000000..b7d45d14d --- /dev/null +++ b/modoboa/core/migrations/0007_auto_20151116_1349.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.contrib.auth.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0006_auto_20151114_1518'), + ] + + operations = [ + migrations.AlterModelManagers( + name='user', + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.AlterField( + model_name='user', + name='groups', + field=models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Group', blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', verbose_name='groups'), + ), + migrations.AlterField( + model_name='user', + name='last_login', + field=models.DateTimeField(null=True, verbose_name='last login', blank=True), + ), + ] diff --git a/modoboa/core/models.py b/modoboa/core/models.py index 69684d9fe..2a787369e 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -59,7 +59,7 @@ class User(PermissionsMixin): ) password = models.CharField(ugettext_lazy('password'), max_length=256) last_login = models.DateTimeField( - ugettext_lazy('last login'), default=timezone.now + ugettext_lazy('last login'), blank=True, null=True ) language = models.CharField( diff --git a/modoboa/core/views/auth.py b/modoboa/core/views/auth.py index 2fe6a4062..ad115044f 100644 --- a/modoboa/core/views/auth.py +++ b/modoboa/core/views/auth.py @@ -23,6 +23,10 @@ def dologin(request): user = authenticate(username=form.cleaned_data["username"], password=form.cleaned_data["password"]) if user and user.is_active: + nextlocation = None + if not user.last_login: + # Redirect to profile on first login + nextlocation = reverse("core:user_index") login(request, user) if not form.cleaned_data["rememberme"]: request.session.set_expiry(0) @@ -38,12 +42,13 @@ def dologin(request): form.cleaned_data["username"], form.cleaned_data["password"]) - nextlocation = request.POST.get("next", None) - if nextlocation is None or nextlocation == "None": - if user.group == "SimpleUsers": - nextlocation = reverse("topredirection") - else: - nextlocation = reverse("admin:domain_list") + if nextlocation is None: + nextlocation = request.POST.get("next", None) + if nextlocation is None or nextlocation == "None": + if user.group == "SimpleUsers": + nextlocation = reverse("topredirection") + else: + nextlocation = reverse("admin:domain_list") return HttpResponseRedirect(nextlocation) error = _( "Your username and password didn't match. Please try again.") From 63b7fabb08f9da2bbd4b8f2b31ae0738b966d455 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 16 Nov 2015 14:51:05 +0100 Subject: [PATCH 2/3] New unit test. see #596 --- modoboa/core/forms.py | 3 +++ modoboa/core/tests.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/modoboa/core/forms.py b/modoboa/core/forms.py index 8779ec0ac..719badc5a 100644 --- a/modoboa/core/forms.py +++ b/modoboa/core/forms.py @@ -12,6 +12,9 @@ from modoboa.lib import parameters class LoginForm(forms.Form): + + """User login form.""" + username = forms.CharField( label=ugettext_lazy("Username"), widget=forms.TextInput(attrs={"class": "form-control"}) diff --git a/modoboa/core/tests.py b/modoboa/core/tests.py index af5794290..23e8df7f2 100644 --- a/modoboa/core/tests.py +++ b/modoboa/core/tests.py @@ -6,6 +6,27 @@ from modoboa.lib.tests import ModoTestCase from . import factories +class AuthenticationTestCase(ModoTestCase): + + """Validate authentication scenarios.""" + + @classmethod + def setUpTestData(cls): + """Create test data.""" + super(AuthenticationTestCase, cls).setUpTestData() + cls.account = factories.UserFactory( + username="user@test.com", groups=('SimpleUsers',) + ) + + def test_authentication(self): + """Validate simple case.""" + self.clt.logout() + data = {"username": "user@test.com", "password": "toto"} + response = self.clt.post(reverse("core:login"), data) + self.assertEqual(response.status_code, 302) + self.assertTrue(response.url.endswith(reverse("core:user_index"))) + + class ProfileTestCase(ModoTestCase): @classmethod From 4f48bc5ed084c05c309251ab57dbe0b9ae53cb2f Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 16 Nov 2015 15:29:19 +0100 Subject: [PATCH 3/3] Complete unit test. see #596 --- modoboa/core/tests.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modoboa/core/tests.py b/modoboa/core/tests.py index 23e8df7f2..0c27dd593 100644 --- a/modoboa/core/tests.py +++ b/modoboa/core/tests.py @@ -26,6 +26,14 @@ class AuthenticationTestCase(ModoTestCase): self.assertEqual(response.status_code, 302) self.assertTrue(response.url.endswith(reverse("core:user_index"))) + response = self.clt.post(reverse("core:logout"), {}) + self.assertEqual(response.status_code, 302) + + data = {"username": "admin", "password": "password"} + response = self.clt.post(reverse("core:login"), data) + self.assertEqual(response.status_code, 302) + self.assertTrue(response.url.endswith(reverse("admin:domain_list"))) + class ProfileTestCase(ModoTestCase):