Skip to content

Commit

Permalink
[#964] Added first-last name validation
Browse files Browse the repository at this point in the history
  • Loading branch information
vaszig committed Dec 13, 2022
1 parent 286f061 commit b0b5ad5
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 7 deletions.
5 changes: 3 additions & 2 deletions src/open_inwoner/accounts/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from open_inwoner.pdc.models.category import Category
from open_inwoner.utils.forms import LimitedUploadFileField, PrivateFileWidget
from open_inwoner.utils.validators import validate_charfield_entry

from .choices import EmptyContactTypeChoices, EmptyStatusChoices, LoginTypeChoices
from .models import Action, Document, Invite, Message, User
Expand Down Expand Up @@ -122,8 +123,8 @@ class ContactFilterForm(forms.Form):


class ContactCreateForm(forms.Form):
first_name = forms.CharField(max_length=255)
last_name = forms.CharField(max_length=255)
first_name = forms.CharField(max_length=255, validators=[validate_charfield_entry])
last_name = forms.CharField(max_length=255, validators=[validate_charfield_entry])
email = forms.EmailField()

def __init__(self, user, *args, **kwargs):
Expand Down
56 changes: 56 additions & 0 deletions src/open_inwoner/accounts/migrations/0052_auto_20221213_0758.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Generated by Django 3.2.15 on 2022-12-13 06:58

from django.db import migrations, models
import open_inwoner.utils.validators


class Migration(migrations.Migration):

dependencies = [
("accounts", "0051_merge_20221207_0918"),
]

operations = [
migrations.AlterField(
model_name="invite",
name="invitee_first_name",
field=models.CharField(
help_text="The first name of the invitee.",
max_length=250,
validators=[open_inwoner.utils.validators.validate_charfield_entry],
verbose_name="First name",
),
),
migrations.AlterField(
model_name="invite",
name="invitee_last_name",
field=models.CharField(
help_text="The last name of the invitee",
max_length=250,
validators=[open_inwoner.utils.validators.validate_charfield_entry],
verbose_name="Last name",
),
),
migrations.AlterField(
model_name="user",
name="first_name",
field=models.CharField(
blank=True,
default="",
max_length=255,
validators=[open_inwoner.utils.validators.validate_charfield_entry],
verbose_name="First name",
),
),
migrations.AlterField(
model_name="user",
name="last_name",
field=models.CharField(
blank=True,
default="",
max_length=255,
validators=[open_inwoner.utils.validators.validate_charfield_entry],
verbose_name="Last name",
),
),
]
19 changes: 16 additions & 3 deletions src/open_inwoner/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
from privates.storages import PrivateMediaFileSystemStorage
from timeline_logger.models import TimelineLog

from open_inwoner.utils.validators import validate_phone_number
from open_inwoner.utils.validators import (
validate_charfield_entry,
validate_phone_number,
)

from .choices import ContactTypeChoices, LoginTypeChoices, StatusChoices, TypeChoices
from .managers import ActionQueryset, DigidManager, UserManager, eHerkenningManager
Expand All @@ -35,10 +38,18 @@ class User(AbstractBaseUser, PermissionsMixin):
help_text=_("Unique identifier."),
)
first_name = models.CharField(
verbose_name=_("First name"), max_length=255, blank=True, default=""
verbose_name=_("First name"),
max_length=255,
blank=True,
default="",
validators=[validate_charfield_entry],
)
last_name = models.CharField(
verbose_name=_("Last name"), max_length=255, blank=True, default=""
verbose_name=_("Last name"),
max_length=255,
blank=True,
default="",
validators=[validate_charfield_entry],
)
email = models.EmailField(verbose_name=_("Email address"), unique=True)
phonenumber = models.CharField(
Expand Down Expand Up @@ -562,11 +573,13 @@ class Invite(models.Model):
verbose_name=_("First name"),
max_length=250,
help_text=_("The first name of the invitee."),
validators=[validate_charfield_entry],
)
invitee_last_name = models.CharField(
verbose_name=_("Last name"),
max_length=250,
help_text=_("The last name of the invitee"),
validators=[validate_charfield_entry],
)
invitee_email = models.EmailField(
verbose_name=_("Invitee email"),
Expand Down
96 changes: 96 additions & 0 deletions src/open_inwoner/accounts/tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,50 @@ def test_registration_fails_without_filling_out_last_name(self):
user_query = User.objects.filter(email=self.user.email)
self.assertEqual(user_query.count(), 0)

def test_registration_fails_with_invalid_first_name_characters(self):
invalid_characters = "/\"\\,.:;'"

for char in invalid_characters:
with self.subTest(char=char):
register_page = self.app.get(reverse("django_registration_register"))
form = register_page.forms["registration-form"]
form["email"] = self.user.email
form["first_name"] = char
form["last_name"] = self.user.last_name
form["password1"] = self.user.password
form["password2"] = self.user.password
response = form.submit()
expected_errors = {
"first_name": [
_("Uw invoer bevat een ongeldig teken: {char}").format(
char=char
)
]
}
self.assertEqual(response.context["form"].errors, expected_errors)

def test_registration_fails_with_invalid_last_name_characters(self):
invalid_characters = "/\"\\,.:;'"

for char in invalid_characters:
with self.subTest(char=char):
register_page = self.app.get(reverse("django_registration_register"))
form = register_page.forms["registration-form"]
form["email"] = self.user.email
form["first_name"] = self.user.first_name
form["last_name"] = char
form["password1"] = self.user.password
form["password2"] = self.user.password
response = form.submit()
expected_errors = {
"last_name": [
_("Uw invoer bevat een ongeldig teken: {char}").format(
char=char
)
]
}
self.assertEqual(response.context["form"].errors, expected_errors)

def test_registration_inactive_user(self):
inactive_user = UserFactory.create(is_active=False)

Expand Down Expand Up @@ -319,6 +363,58 @@ def test_submit_not_unique_email_different_case(self):
"* Een gebruiker met dit e-mailadres bestaat al",
)

def test_submit_invalid_first_name_chars_fails(self):
UserFactory.create(email="[email protected]")
user = UserFactory.create(
first_name="",
last_name="",
login_type=LoginTypeChoices.digid,
)
invalid_characters = "/\"\\,.:;'"

for char in invalid_characters:
with self.subTest(char=char):
get_response = self.app.get(self.url, user=user)
form = get_response.forms["necessary-form"]
form["email"] = "[email protected]"
form["first_name"] = char
form["last_name"] = "Smith"
response = form.submit()
expected_errors = {
"first_name": [
_("Uw invoer bevat een ongeldig teken: {char}").format(
char=char
)
]
}
self.assertEqual(response.context["form"].errors, expected_errors)

def test_submit_invalid_last_name_chars_fails(self):
UserFactory.create(email="[email protected]")
user = UserFactory.create(
first_name="",
last_name="",
login_type=LoginTypeChoices.digid,
)
invalid_characters = "/\"\\,.:;'"

for char in invalid_characters:
with self.subTest(char=char):
get_response = self.app.get(self.url, user=user)
form = get_response.forms["necessary-form"]
form["email"] = "[email protected]"
form["first_name"] = "John"
form["last_name"] = char
response = form.submit()
expected_errors = {
"last_name": [
_("Uw invoer bevat een ongeldig teken: {char}").format(
char=char
)
]
}
self.assertEqual(response.context["form"].errors, expected_errors)


class TestLoginLogoutFunctionality(WebTest):
def setUp(self):
Expand Down
40 changes: 40 additions & 0 deletions src/open_inwoner/accounts/tests/test_contact_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,46 @@ def test_adding_inactive_contact_fails(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context["form"].errors, expected_errors)

def test_adding_contact_with_invalid_first_name_chars_fails(self):
invalid_characters = "/\"\\,.:;'"

for char in invalid_characters:
with self.subTest(char=char):
response = self.app.get(self.create_url, user=self.user)
form = response.forms["contact-form"]
form["first_name"] = char
form["last_name"] = "Smith"
form["email"] = "[email protected]"
response = form.submit()
expected_errors = {
"first_name": [
_("Uw invoer bevat een ongeldig teken: {char}").format(
char=char
)
]
}
self.assertEqual(response.context["form"].errors, expected_errors)

def test_adding_contact_with_invalid_last_name_chars_fails(self):
invalid_characters = "/\"\\,.:;'"

for char in invalid_characters:
with self.subTest(char=char):
response = self.app.get(self.create_url, user=self.user)
form = response.forms["contact-form"]
form["first_name"] = "John"
form["last_name"] = char
form["email"] = "[email protected]"
response = form.submit()
expected_errors = {
"last_name": [
_("Uw invoer bevat een ongeldig teken: {char}").format(
char=char
)
]
}
self.assertEqual(response.context["form"].errors, expected_errors)

def test_email_required(self):
response = self.app.get(self.create_url, user=self.user)
form = response.forms["contact-form"]
Expand Down
52 changes: 52 additions & 0 deletions src/open_inwoner/accounts/tests/test_profile_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,58 @@ def test_save_filled_form(self):
self.assertEquals(self.user.postcode, "1013 RM")
self.assertEquals(self.user.city, "Amsterdam")

def test_save_with_invalid_first_name_chars_fails(self):
invalid_characters = "/\"\\,.:;'"

for char in invalid_characters:
with self.subTest(char=char):
response = self.app.get(self.url, user=self.user)
self.assertEquals(response.status_code, 200)
form = response.forms["profile-edit"]
form["first_name"] = char
form["last_name"] = "Last name"
form["phonenumber"] = "06987878787"
form["birthday"] = "21-01-1992"
form["street"] = "Keizersgracht"
form["housenumber"] = "17 d"
form["postcode"] = "1013 RM"
form["city"] = "Amsterdam"
response = form.submit()
expected_errors = {
"first_name": [
_("Uw invoer bevat een ongeldig teken: {char}").format(
char=char
)
]
}
self.assertEqual(response.context["form"].errors, expected_errors)

def test_save_with_invalid_last_name_chars_fails(self):
invalid_characters = "/\"\\,.:;'"

for char in invalid_characters:
with self.subTest(char=char):
response = self.app.get(self.url, user=self.user)
self.assertEquals(response.status_code, 200)
form = response.forms["profile-edit"]
form["first_name"] = "John"
form["last_name"] = char
form["phonenumber"] = "06987878787"
form["birthday"] = "21-01-1992"
form["street"] = "Keizersgracht"
form["housenumber"] = "17 d"
form["postcode"] = "1013 RM"
form["city"] = "Amsterdam"
response = form.submit()
expected_errors = {
"last_name": [
_("Uw invoer bevat een ongeldig teken: {char}").format(
char=char
)
]
}
self.assertEqual(response.context["form"].errors, expected_errors)


class EditIntrestsTests(WebTest):
def setUp(self):
Expand Down
4 changes: 2 additions & 2 deletions src/open_inwoner/utils/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

def validate_charfield_entry(value, allow_apostrophe=False):
"""
Validates a charfield entry according with Belastingdienst requirements.
Validates a charfield entry according with requirements.
:param value: The input value string to be validated.
:param allow_apostrophe: Boolean to add the apostrophe character to the
Expand All @@ -15,7 +15,7 @@ def validate_charfield_entry(value, allow_apostrophe=False):
:return: The input value if validation passed. Otherwise, raises a
``ValidationError`` exception.
"""
invalid_chars = '/"\\,;' if allow_apostrophe else "/\"\\,;'"
invalid_chars = '/"\\,;' if allow_apostrophe else "/\"\\,.:;'"

for char in invalid_chars:
if char in value:
Expand Down

0 comments on commit b0b5ad5

Please sign in to comment.