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][0-9]{9}$', message=_('A french phone number must start with a zero then another nine 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['validators'] = (french_validate_phone_number,) |
|
184 |
kwargs.setdefault('help_text', _('ex.: 0699999999, 01 23 45 67 89, 09.87.65.43.21')) |
|
185 |
super().__init__(*args, **kwargs) |
|
186 | ||
187 |
def clean(self, value): |
|
188 |
if value not in self.empty_values: |
|
189 |
value = clean_number(value) |
|
190 |
value = super().clean(value) |
|
191 |
return value |
|
192 | ||
193 | ||
175 | 194 |
class PhoneNumberDRFField(serializers.CharField): |
176 | 195 |
default_validators = [validate_phone_number] |
177 | 196 | |
... | ... | |
179 | 198 |
return clean_number(super().to_internal_value(data)) |
180 | 199 | |
181 | 200 | |
201 |
class FrenchPhoneNumberDRFField(PhoneNumberDRFField): |
|
202 |
default_validators = [french_validate_phone_number] |
|
203 | ||
204 | ||
182 | 205 |
validate_fr_postcode = RegexValidator(r'^\d{5}$', message=_('The value must be a valid french postcode')) |
183 | 206 | |
184 | 207 | |
... | ... | |
340 | 363 |
'field_class': PhoneNumberField, |
341 | 364 |
'rest_framework_field_class': PhoneNumberDRFField, |
342 | 365 |
}, |
366 |
{ |
|
367 |
'label': _('french phone number'), |
|
368 |
'name': 'fr_phone_number', |
|
369 |
'field_class': FrenchPhoneNumberField, |
|
370 |
'rest_framework_field_class': FrenchPhoneNumberDRFField, |
|
371 |
}, |
|
343 | 372 |
{ |
344 | 373 |
'label': _('profile image'), |
345 | 374 |
'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 |
form.set('phone_number', '1234512345' * 10) |
|
299 |
form.set('password1', '12345abcdA') |
|
300 |
form.set('password2', '12345abcdA') |
|
301 |
response = form.submit() |
|
302 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
303 | ||
304 |
form = response.form |
|
305 |
form.set('phone_number', '12345') |
|
306 |
form.set('password1', '12345abcdA') |
|
307 |
form.set('password2', '12345abcdA') |
|
308 |
response = form.submit() |
|
309 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
310 | ||
311 |
form = response.form |
|
312 |
form.set('first_name', 'John') |
|
313 |
form.set('last_name', 'Doe') |
|
314 |
form.set('phone_number', '+12345') |
|
315 |
form.set('password1', '12345abcdA') |
|
316 |
form.set('password2', '12345abcdA') |
|
317 |
response = form.submit() |
|
318 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
319 | ||
320 |
form = response.form |
|
321 |
form.set('phone_number', ' + 1.2-3 4 5 ') |
|
322 |
form.set('password1', '12345abcdA') |
|
323 |
form.set('password2', '12345abcdA') |
|
324 |
response = form.submit() |
|
325 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
326 | ||
327 |
form = response.form |
|
328 |
form.set('phone_number', '1234567890') |
|
329 |
form.set('password1', '12345abcdA') |
|
330 |
form.set('password2', '12345abcdA') |
|
331 |
response = form.submit() |
|
332 |
assert response.pyquery.find('.form-field-error #id_phone_number') |
|
333 | ||
334 |
form = response.form |
|
335 |
form.set('phone_number', '') |
|
336 |
form.set('password1', '12345abcdA') |
|
337 |
form.set('password2', '12345abcdA') |
|
338 |
response = form.submit().follow() |
|
339 |
assert qs.get().attributes.phone_number == '' |
|
340 |
qs.delete() |
|
341 | ||
342 |
url = register_john() |
|
343 |
response = app.get(url) |
|
344 |
form = response.form |
|
345 |
form.set('first_name', 'John') |
|
346 |
form.set('last_name', 'Doe') |
|
347 |
form.set('phone_number', '0123456789') |
|
348 |
form.set('password1', '12345abcdA') |
|
349 |
form.set('password2', '12345abcdA') |
|
350 |
response = form.submit().follow() |
|
351 |
assert qs.get().attributes.phone_number == '0123456789' |
|
352 |
qs.delete() |
|
353 | ||
354 |
url = register_john() |
|
355 |
response = app.get(url) |
|
356 |
form = response.form |
|
357 |
form.set('first_name', 'John') |
|
358 |
form.set('last_name', 'Doe') |
|
359 |
form.set('phone_number', '01 23 45 67 89') |
|
360 |
form.set('password1', '12345abcdA') |
|
361 |
form.set('password2', '12345abcdA') |
|
362 |
response = form.submit().follow() |
|
363 |
assert qs.get().attributes.phone_number == '0123456789' |
|
364 |
qs.delete() |
|
365 | ||
366 |
url = register_john() |
|
367 |
response = app.get(url) |
|
368 |
form = response.form |
|
369 |
form.set('first_name', 'John') |
|
370 |
form.set('last_name', 'Doe') |
|
371 |
form.set('phone_number', '01-23-45-67-89') |
|
372 |
form.set('password1', '12345abcdA') |
|
373 |
form.set('password2', '12345abcdA') |
|
374 |
response = form.submit().follow() |
|
375 |
assert qs.get().attributes.phone_number == '0123456789' |
|
376 |
qs.delete() |
|
377 | ||
378 |
url = register_john() |
|
379 |
response = app.get(url) |
|
380 |
form = response.form |
|
381 |
form.set('first_name', 'John') |
|
382 |
form.set('last_name', 'Doe') |
|
383 |
form.set('phone_number', '06.99.99.99.99') |
|
384 |
form.set('password1', '12345abcdA') |
|
385 |
form.set('password2', '12345abcdA') |
|
386 |
response = form.submit().follow() |
|
387 |
assert qs.get().attributes.phone_number == '0699999999' |
|
388 |
qs.delete() |
|
389 | ||
390 |
url = register_john() |
|
391 |
response = app.get(url) |
|
392 |
form = response.form |
|
393 |
form.set('first_name', 'John') |
|
394 |
form.set('last_name', 'Doe') |
|
395 |
form.set('phone_number', '0699999999') |
|
396 |
form.set('password1', '12345abcdA') |
|
397 |
form.set('password2', '12345abcdA') |
|
398 |
response = form.submit().follow() |
|
399 |
assert qs.get().attributes.phone_number == '0699999999' |
|
400 |
qs.delete() |
|
401 | ||
402 | ||
270 | 403 |
def test_birthdate(db, app, admin, mailoutbox, freezer): |
271 | 404 |
def register_john(): |
272 | 405 |
response = app.get('/accounts/register/') |
273 |
- |