0001-attribute_kinds-add-french-phone-number-type-45422.patch
src/authentic2/attribute_kinds.py | ||
---|---|---|
151 | 151 |
r'^\+?\d{,20}$', message=_('Phone number can start with a + and must contain only digits.') |
152 | 152 |
) |
153 | 153 | |
154 |
french_validate_phone_number = RegexValidator( |
|
155 |
r'^[0]\d{9}$', message=_('Phone number must start with a zero and contain nine other digits.') |
|
156 |
) |
|
157 | ||
154 | 158 | |
155 | 159 |
def clean_number(number): |
156 | 160 |
cleaned_number = re.sub(r'[-.\s/]', '', number) |
... | ... | |
172 | 176 |
return value |
173 | 177 | |
174 | 178 | |
179 |
class FrenchPhoneNumberField(forms.CharField): |
|
180 |
widget = widgets.PhoneNumberInput |
|
181 | ||
182 |
def __init__(self, *args, **kwargs): |
|
183 |
kwargs['max_length'] = 30 |
|
184 |
kwargs['min_length'] = 10 |
|
185 |
kwargs.setdefault('help_text', _('ex.: 0699999999, 01 23 45 67 89, 09.87.65.43.21')) |
|
186 |
super().__init__(*args, **kwargs) |
|
187 | ||
188 |
def clean(self, value): |
|
189 |
if value not in self.empty_values: |
|
190 |
value = clean_number(value) |
|
191 |
value = super().clean(value) |
|
192 |
return value |
|
193 | ||
194 |
def validate(self, value): |
|
195 |
super().validate(value) |
|
196 |
if not value.startswith('0'): |
|
197 |
raise ValidationError(_('French phone number starts with \'0\'')) |
|
198 |
if not len(value) == 10: |
|
199 |
raise ValidationError(_('French phone number is 10-digit long')) |
|
200 | ||
201 | ||
175 | 202 |
class PhoneNumberDRFField(serializers.CharField): |
176 | 203 |
default_validators = [validate_phone_number] |
177 | 204 | |
... | ... | |
179 | 206 |
return clean_number(super().to_internal_value(data)) |
180 | 207 | |
181 | 208 | |
209 |
class FrenchPhoneNumberDRFField(PhoneNumberDRFField): |
|
210 |
default_validators = [french_validate_phone_number] |
|
211 | ||
212 | ||
182 | 213 |
validate_fr_postcode = RegexValidator(r'^\d{5}$', message=_('The value must be a valid french postcode')) |
183 | 214 | |
184 | 215 | |
... | ... | |
340 | 371 |
'field_class': PhoneNumberField, |
341 | 372 |
'rest_framework_field_class': PhoneNumberDRFField, |
342 | 373 |
}, |
374 |
{ |
|
375 |
'label': _('french phone number'), |
|
376 |
'name': 'fr_phone_number', |
|
377 |
'field_class': FrenchPhoneNumberField, |
|
378 |
'rest_framework_field_class': FrenchPhoneNumberDRFField, |
|
379 |
}, |
|
343 | 380 |
{ |
344 | 381 |
'label': _('profile image'), |
345 | 382 |
'name': 'profile_image', |
tests/test_api.py | ||
---|---|---|
2211 | 2211 |
app.post_json('/api/users/', headers=headers, params=payload, status=400) |
2212 | 2212 | |
2213 | 2213 | |
2214 |
def test_fr_phone_normalization_ok(settings, app, admin): |
|
2215 |
headers = basic_authorization_header(admin) |
|
2216 |
Attribute.objects.create(name='phone', label='phone', kind='fr_phone_number') |
|
2217 |
payload = { |
|
2218 |
'username': 'janedoe', |
|
2219 |
'phone': ' 04-99 98.56/43', |
|
2220 |
'first_name': 'Jane', |
|
2221 |
'last_name': 'Doe', |
|
2222 |
} |
|
2223 |
resp = app.post_json('/api/users/', headers=headers, params=payload, status=201) |
|
2224 |
assert resp.json['phone'] == '0499985643' |
|
2225 |
assert User.objects.get(username='janedoe').attributes.phone == '0499985643' |
|
2226 | ||
2227 | ||
2228 |
def test_fr_phone_normalization_nok(settings, app, admin): |
|
2229 |
headers = basic_authorization_header(admin) |
|
2230 |
Attribute.objects.create(name='phone', label='phone', kind='fr_phone_number') |
|
2231 |
payload = { |
|
2232 |
'username': 'janedoe', |
|
2233 |
'phone': '+33499985643', |
|
2234 |
'first_name': 'Jane', |
|
2235 |
'last_name': 'Doe', |
|
2236 |
} |
|
2237 |
app.post_json('/api/users/', headers=headers, params=payload, status=400) |
|
2238 | ||
2239 |
payload['phone'] = '1#2' |
|
2240 |
app.post_json('/api/users/', headers=headers, params=payload, status=400) |
|
2241 | ||
2242 | ||
2214 | 2243 |
def test_api_users_create_user_delete(app, settings, admin): |
2215 | 2244 |
email = 'foo@example.net' |
2216 | 2245 |
user1 = User.objects.create(username='foo', email=email) |
tests/test_attribute_kinds.py | ||
---|---|---|
267 | 267 |
qs.delete() |
268 | 268 | |
269 | 269 | |
270 |
def test_french_phone_number(db, app, admin, mailoutbox, settings): |
|
271 |
settings.A2_EMAILS_ADDRESS_RATELIMIT = None |
|
272 | ||
273 |
def register_john(): |
|
274 |
response = app.get('/accounts/register/') |
|
275 |
form = response.form |
|
276 |
form.set('email', 'john.doe@example.com') |
|
277 |
response = form.submit().follow() |
|
278 |
assert 'john.doe@example.com' in response |
|
279 |
return get_link_from_mail(mailoutbox[-1]) |
|
280 | ||
281 |
Attribute.objects.create( |
|
282 |
name='phone_number', label='phone', kind='fr_phone_number', asked_on_registration=True |
|
283 |
) |
|
284 |
qs = User.objects.filter(first_name='John') |
|
285 | ||
286 |
url = register_john() |
|
287 |
response = app.get(url) |
|
288 |
form = response.form |
|
289 |
form.set('first_name', 'John') |
|
290 |
form.set('last_name', 'Doe') |
|
291 |
form.set('phone_number', 'abc') |
|
292 |
form.set('password1', '12345abcdA') |
|
293 |
form.set('password2', '12345abcdA') |
|
294 |
response = form.submit() |
|
295 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
296 | ||
297 |
form = response.form |
|
298 |
assert response.pyquery('#id_phone_number').attr('maxlength') == '30' |
|
299 |
assert response.pyquery('#id_phone_number').attr('minlength') == '10' |
|
300 |
form.set('phone_number', '1234512345' * 10) |
|
301 |
form.set('password1', '12345abcdA') |
|
302 |
form.set('password2', '12345abcdA') |
|
303 |
response = form.submit() |
|
304 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
305 | ||
306 |
form = response.form |
|
307 |
form.set('phone_number', '12345') |
|
308 |
form.set('password1', '12345abcdA') |
|
309 |
form.set('password2', '12345abcdA') |
|
310 |
response = form.submit() |
|
311 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
312 | ||
313 |
form = response.form |
|
314 |
form.set('first_name', 'John') |
|
315 |
form.set('last_name', 'Doe') |
|
316 |
form.set('phone_number', '+12345') |
|
317 |
form.set('password1', '12345abcdA') |
|
318 |
form.set('password2', '12345abcdA') |
|
319 |
response = form.submit() |
|
320 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
321 | ||
322 |
form = response.form |
|
323 |
form.set('first_name', 'John') |
|
324 |
form.set('last_name', 'Doe') |
|
325 |
form.set('phone_number', '') |
|
326 |
form.set('password1', '12345abcdA') |
|
327 |
form.set('password2', '12345abcdA') |
|
328 |
response = form.submit() |
|
329 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
330 | ||
331 |
form = response.form |
|
332 |
form.set('phone_number', ' + 1.2-3 4 5 ') |
|
333 |
form.set('password1', '12345abcdA') |
|
334 |
form.set('password2', '12345abcdA') |
|
335 |
response = form.submit() |
|
336 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
337 | ||
338 |
form = response.form |
|
339 |
form.set('phone_number', '1234567890') |
|
340 |
form.set('password1', '12345abcdA') |
|
341 |
form.set('password2', '12345abcdA') |
|
342 |
response = form.submit() |
|
343 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
344 | ||
345 |
form = response.form |
|
346 |
form.set('phone_number', '') |
|
347 |
form.set('password1', '12345abcdA') |
|
348 |
form.set('password2', '12345abcdA') |
|
349 |
response = form.submit() |
|
350 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
351 | ||
352 |
form = response.form |
|
353 |
form.set('phone_number', '0123456789') |
|
354 |
form.set('password1', '12345abcdA') |
|
355 |
form.set('password2', '12345abcdA') |
|
356 |
response = form.submit().follow() |
|
357 |
assert qs.get().attributes.phone_number == '0123456789' |
|
358 |
qs.delete() |
|
359 | ||
360 |
url = register_john() |
|
361 |
response = app.get(url) |
|
362 |
form = response.form |
|
363 |
form.set('first_name', 'John') |
|
364 |
form.set('last_name', 'Doe') |
|
365 |
form.set('phone_number', '01 23 45 67 89') |
|
366 |
form.set('password1', '12345abcdA') |
|
367 |
form.set('password2', '12345abcdA') |
|
368 |
response = form.submit().follow() |
|
369 |
assert qs.get().attributes.phone_number == '0123456789' |
|
370 |
qs.delete() |
|
371 | ||
372 |
url = register_john() |
|
373 |
response = app.get(url) |
|
374 |
form = response.form |
|
375 |
form.set('first_name', 'John') |
|
376 |
form.set('last_name', 'Doe') |
|
377 |
form.set('phone_number', '01-23-45-67-89') |
|
378 |
form.set('password1', '12345abcdA') |
|
379 |
form.set('password2', '12345abcdA') |
|
380 |
response = form.submit().follow() |
|
381 |
assert qs.get().attributes.phone_number == '0123456789' |
|
382 |
qs.delete() |
|
383 | ||
384 |
url = register_john() |
|
385 |
response = app.get(url) |
|
386 |
form = response.form |
|
387 |
form.set('first_name', 'John') |
|
388 |
form.set('last_name', 'Doe') |
|
389 |
form.set('phone_number', '06.99.99.99.99') |
|
390 |
form.set('password1', '12345abcdA') |
|
391 |
form.set('password2', '12345abcdA') |
|
392 |
response = form.submit().follow() |
|
393 |
assert qs.get().attributes.phone_number == '0699999999' |
|
394 |
qs.delete() |
|
395 | ||
396 |
url = register_john() |
|
397 |
response = app.get(url) |
|
398 |
form = response.form |
|
399 |
form.set('first_name', 'John') |
|
400 |
form.set('last_name', 'Doe') |
|
401 |
form.set('phone_number', '0699999999') |
|
402 |
form.set('password1', '12345abcdA') |
|
403 |
form.set('password2', '12345abcdA') |
|
404 |
response = form.submit().follow() |
|
405 |
assert qs.get().attributes.phone_number == '0699999999' |
|
406 |
qs.delete() |
|
407 | ||
408 | ||
270 | 409 |
def test_birthdate(db, app, admin, mailoutbox, freezer): |
271 | 410 |
def register_john(): |
272 | 411 |
response = app.get('/accounts/register/') |
273 |
- |