Skip to content

Commit

Permalink
Merge branch 'dev' into nouvelle_classification_1
Browse files Browse the repository at this point in the history
  • Loading branch information
philippemilink authored Jul 19, 2022
2 parents 0e0a94f + 029e2e9 commit 23d38e6
Show file tree
Hide file tree
Showing 9 changed files with 279 additions and 211 deletions.
70 changes: 44 additions & 26 deletions zds/member/forms.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from django import forms
from django.conf import settings
from django.contrib.auth import authenticate
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User, Group
from django.core.exceptions import ValidationError
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _

from captcha.fields import ReCaptchaField
Expand All @@ -29,45 +32,60 @@
MIN_PASSWORD_LENGTH = 6


class LoginForm(forms.Form):
"""
The login form, including the "remember me" checkbox.
"""

username = forms.CharField(
label=_("Nom d'utilisateur"),
max_length=User._meta.get_field("username").max_length,
required=True,
widget=forms.TextInput(attrs={"autofocus": ""}),
)

password = forms.CharField(
label=_("Mot de passe"),
required=True,
widget=forms.PasswordInput,
)

class LoginForm(AuthenticationForm):
remember = forms.BooleanField(
label=_("Se souvenir de moi"),
initial=True,
required=False,
)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_action = reverse("member-login")
self.helper.form_method = "post"
self.helper.form_class = "content-wrapper"

self.helper.layout = Layout(
error_messages = {
"invalid_login": _(
"Merci de saisir un nom d'utilisateur et un mot de passe corrects. Faites attention aux majuscules et "
"minuscules !"
),
"inactive": _(
"Vous n’avez pas encore activé votre compte, vous devez le faire pour pouvoir vous connecter sur le site."
" <a href={}>Vous n’avez pas reçu le courriel d'activation ?</a>"
),
"banned": _("Vous n’êtes pas autorisé à vous connecter sur le site, vous avez été banni par un modérateur."),
}

def __init__(self, request=None, next="", *args, **kwargs):
super().__init__(request, *args, **kwargs)
self.helper = self.get_helper(next)
# Errors are displayed using info bars (see LoginView) instead of the form built-in error rendering
self.helper.form_show_errors = False

def get_helper(self, next):
"""Return the FormHelper expected by crispy."""
helper = FormHelper()
helper.form_action = reverse("member-login") + f"?next={next}"
helper.form_method = "post"
helper.form_class = "content-wrapper"
helper.layout = Layout(
Field("username"),
Field("password"),
Field("remember"),
ButtonHolder(
StrictButton(_("Se connecter"), type="submit"),
),
)
return helper

def confirm_login_allowed(self, user):
"""Override the parent method to change the error for inactive users and prevent login of banned users."""
if not user.is_active:
error_text = mark_safe(self.error_messages["inactive"].format(reverse("send-validation-email")))
raise ValidationError(
error_text,
code="inactive",
)
elif not user.profile.is_banned():
raise ValidationError(
self.error_messages["banned"],
code="banned",
)


class RegisterForm(forms.Form):
Expand Down
6 changes: 6 additions & 0 deletions zds/member/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,12 @@ def can_read_now(self):
return self.can_read
return False

def is_banned(self):
"""Return True if the user is permanently or temporarily banned."""
if self.end_ban_read:
return self.can_read or (self.end_ban_read < datetime.now())
return self.can_read

def can_write_now(self):
if self.user.is_active:
if self.end_ban_write:
Expand Down
25 changes: 0 additions & 25 deletions zds/member/tests/tests_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from zds.member.tests.factories import ProfileFactory, NonAsciiProfileFactory
from zds.member.forms import (
LoginForm,
RegisterForm,
MiniProfileForm,
ProfileForm,
Expand All @@ -29,30 +28,6 @@
stringof2001chars += "0123456789"
stringof2001chars += "12.jpg"

# This form is tricky to test as it needs a tuto to be done
# class OldTutoFormTest(TestCase):


class LoginFormTest(TestCase):
"""
Check the form to login.
"""

def test_valid_login_form(self):
data = {"username": "Tester", "password": "hostel77", "remember": True}
form = LoginForm(data=data)
self.assertTrue(form.is_valid())

def test_missing_username_form(self):
data = {"username": "", "password": "hostel77", "remember": True}
form = LoginForm(data=data)
self.assertFalse(form.is_valid())

def test_missing_password_form(self):
data = {"username": "Tester", "password": "", "remember": True}
form = LoginForm(data=data)
self.assertFalse(form.is_valid())


class RegisterFormTest(TestCase):
"""
Expand Down
16 changes: 8 additions & 8 deletions zds/member/tests/views/tests_admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.conf import settings
from django.contrib.auth.models import Group
from django.contrib.auth.models import Group, User
from django.urls import reverse
from django.test import TestCase

Expand Down Expand Up @@ -55,9 +55,8 @@ def test_promote_interface(self):

# LET THE TEST BEGIN !

# tester shouldn't be able to connect
login_check = self.client.login(username=tester.user.username, password="hostel77")
self.assertEqual(login_check, False)
# At this point, the user cannot log in because the account is inactive.
# This behavior is tested in the tests of LoginView.

# connect as staff (superuser)
self.client.force_login(staff.user)
Expand Down Expand Up @@ -87,7 +86,7 @@ def test_promote_interface(self):

self.assertEqual(len(TopicAnswerSubscription.objects.get_objects_followed_by(tester.user)), 3)

# retract all right, keep one group only and activate account
# retract all rights, keep one group only and activate account
result = self.client.post(
reverse("member-settings-promote", kwargs={"user_pk": tester.user.id}),
{"groups": [group.id], "activation": "on"},
Expand All @@ -108,9 +107,10 @@ def test_promote_interface(self):
tester = Profile.objects.get(id=tester.id) # refresh
self.assertEqual(len(TopicAnswerSubscription.objects.get_objects_followed_by(tester.user)), 1)

# Finally, check that user can connect and can not access the interface
login_check = self.client.login(username=tester.user.username, password="hostel77")
self.assertEqual(login_check, True)
# Finally, check that the user cannot access the interface.
tester_from_db = User.objects.get(username=tester.user.username)
self.assertTrue(tester_from_db.is_active)
self.client.force_login(tester.user)
result = self.client.post(
reverse("member-settings-promote", kwargs={"user_pk": staff.user.id}), {"activation": "on"}, follow=False
)
Expand Down
Loading

0 comments on commit 23d38e6

Please sign in to comment.