Skip to content
Snippets Groups Projects
Commit 113fedfc authored by Piotr Gawron's avatar Piotr Gawron
Browse files

validator for social security number added

parent e0f64f3b
No related branches found
No related tags found
1 merge request!114validator for social security number added
Pipeline #
import logging
from django import forms from django import forms
from django.forms import ModelForm from django.forms import ModelForm
...@@ -5,12 +7,94 @@ from web.forms.forms import DATEPICKER_DATE_ATTRS ...@@ -5,12 +7,94 @@ from web.forms.forms import DATEPICKER_DATE_ATTRS
from web.models import Subject from web.models import Subject
from web.models.constants import COUNTRY_OTHER_ID from web.models.constants import COUNTRY_OTHER_ID
logger = logging.getLogger(__name__)
def validate_subject_country(self, cleaned_data): def validate_subject_country(self, cleaned_data):
if cleaned_data['country'].id == COUNTRY_OTHER_ID: if cleaned_data['country'].id == COUNTRY_OTHER_ID:
self.add_error('country', "Select valid country") self.add_error('country', "Select valid country")
def validate_social_security_number(self, number):
if not is_valid_social_security_number(number):
self.add_error('social_security_number', "Social security number is invalid")
def is_valid_social_security_number(number):
if number is not None and number != '':
if len(number) != 13:
return False
if not number.isdigit():
return False
if not is_luhn_valid(number[:12]):
return False
if not is_valid_verhoeff(number[:11] + number[12]):
return False
return True
def luhn_checksum(card_number):
def digits_of(n):
return [int(d) for d in str(n)]
digits = digits_of(card_number)
odd_digits = digits[-1::-2]
even_digits = digits[-2::-2]
checksum = 0
checksum += sum(odd_digits)
for d in even_digits:
checksum += sum(digits_of(d * 2))
return checksum % 10
def is_luhn_valid(card_number):
return luhn_checksum(card_number) == 0
verhoeff_multiplication_table = (
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
(1, 2, 3, 4, 0, 6, 7, 8, 9, 5),
(2, 3, 4, 0, 1, 7, 8, 9, 5, 6),
(3, 4, 0, 1, 2, 8, 9, 5, 6, 7),
(4, 0, 1, 2, 3, 9, 5, 6, 7, 8),
(5, 9, 8, 7, 6, 0, 4, 3, 2, 1),
(6, 5, 9, 8, 7, 1, 0, 4, 3, 2),
(7, 6, 5, 9, 8, 2, 1, 0, 4, 3),
(8, 7, 6, 5, 9, 3, 2, 1, 0, 4),
(9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
verhoeff_permutation_table = (
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
(1, 5, 7, 6, 2, 8, 3, 0, 9, 4),
(5, 8, 0, 3, 7, 9, 6, 1, 4, 2),
(8, 9, 1, 6, 0, 4, 3, 5, 2, 7),
(9, 4, 5, 3, 1, 2, 6, 8, 7, 0),
(4, 2, 8, 6, 5, 7, 3, 9, 0, 1),
(2, 7, 9, 3, 8, 0, 6, 4, 1, 5),
(7, 0, 4, 6, 9, 1, 3, 2, 5, 8))
def verhoeff_checksum(number):
"""Calculate the Verhoeff checksum over the provided number. The checksum
is returned as an int. Valid numbers should have a checksum of 0."""
# transform number list
number = tuple(int(n) for n in reversed(str(number)))
# calculate checksum
check = 0
for i, n in enumerate(number):
check = verhoeff_multiplication_table[check][verhoeff_permutation_table[i % 8][n]]
return check
def is_valid_verhoeff(number):
return verhoeff_checksum(number) == 0
def calculate_verhoeff_check_sum(number):
return str(verhoeff_multiplication_table[verhoeff_checksum(str(number) + '0')].index(0))
FIELD_ORDER = ["first_name", "last_name", "sex", "date_born", "social_security_number", FIELD_ORDER = ["first_name", "last_name", "sex", "date_born", "social_security_number",
"default_written_communication_language", "languages", "phone_number", "phone_number_2", "default_written_communication_language", "languages", "phone_number", "phone_number_2",
"phone_number_3", "address", "city", "postal_code", "country"] "phone_number_3", "address", "city", "postal_code", "country"]
...@@ -32,6 +116,7 @@ class SubjectAddForm(ModelForm): ...@@ -32,6 +116,7 @@ class SubjectAddForm(ModelForm):
def clean(self): def clean(self):
cleaned_data = super(SubjectAddForm, self).clean() cleaned_data = super(SubjectAddForm, self).clean()
validate_subject_country(self, cleaned_data) validate_subject_country(self, cleaned_data)
validate_social_security_number(self, cleaned_data["social_security_number"])
return cleaned_data return cleaned_data
...@@ -53,6 +138,7 @@ class SubjectEditForm(ModelForm): ...@@ -53,6 +138,7 @@ class SubjectEditForm(ModelForm):
def clean(self): def clean(self):
validate_subject_country(self, self.cleaned_data) validate_subject_country(self, self.cleaned_data)
validate_social_security_number(self, self.cleaned_data["social_security_number"])
class Meta: class Meta:
model = Subject model = Subject
......
import logging
from web.forms.subject_forms import is_valid_social_security_number
from web.tests import LoggedInWithWorkerTestCase
from web.tests.functions import create_subject
logger = logging.getLogger(__name__)
class StudySubjectAddFormTests(LoggedInWithWorkerTestCase):
def setUp(self):
super(LoggedInWithWorkerTestCase, self).setUp()
self.subject = create_subject()
def test_is_valid_social_security_number_too_short(self):
self.assertFalse(is_valid_social_security_number("123"))
def test_is_valid_social_security_number_not_a_number(self):
# noinspection SpellCheckingInspection
self.assertFalse(is_valid_social_security_number("ABCDEFGHIJKLM"))
def test_is_valid_social_security_number_invalid(self):
self.assertFalse(is_valid_social_security_number("1234567890123"))
def test_is_valid_social_security_number(self):
self.assertTrue(is_valid_social_security_number("1893120105732"))
def test_is_valid_social_security_number_empty(self):
self.assertTrue(is_valid_social_security_number(""))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment