Projet

Général

Profil

0001-api-update-phone-drf-field-to-handle-E164-format-694.patch

Paul Marillonnet, 23 septembre 2022 09:43

Télécharger (5,16 ko)

Voir les différences:

Subject: [PATCH] api: update phone drf field to handle E164 format (#69430)

 src/authentic2/attribute_kinds.py | 37 ++++++++++++++++++++++++++-----
 tests/api/test_all.py             | 33 ++++++++++++++++++++++++++-
 2 files changed, 64 insertions(+), 6 deletions(-)
src/authentic2/attribute_kinds.py
24 24
import uuid
25 25
from itertools import chain
26 26

  
27
import phonenumbers
27 28
from django import forms
28 29
from django.conf import settings
29 30
from django.core.exceptions import ValidationError
......
146 147
    return app_settings.A2_ATTRIBUTE_KIND_TITLE_CHOICES or DEFAULT_TITLE_CHOICES
147 148

  
148 149

  
149
validate_phone_number = RegexValidator(
150
    r'^\+?\d{,20}$', message=_('Phone number can start with a + and must contain only digits.')
151
)
150
def validate_phone_number(value):
151
    default_country = settings.PHONE_COUNTRY_CODES[settings.DEFAULT_COUNTRY_CODE]
152
    try:
153
        phonenumbers.parse(value)
154
    except phonenumbers.NumberParseException:
155
        try:
156
            phonenumbers.parse(
157
                value,
158
                default_country,
159
            )
160
        except phonenumbers.NumberParseException:
161
            raise ValidationError(
162
                _(
163
                    f'Phone number must be either in E.164 globally unique format or dialable from'
164
                    ' {settings.DEFAULT_COUNTRY_CODE} country code ({default_country}).'
165
                )
166
            )
167

  
152 168

  
153 169
french_validate_phone_number = RegexValidator(
154 170
    r'^[0][0-9]{9}$', message=_('A french phone number must start with a zero then another nine digits.')
......
180 196
    default_validators = [validate_phone_number]
181 197

  
182 198
    def to_internal_value(self, data):
183
        return clean_number(super().to_internal_value(data))
199
        if isinstance(data, (list, tuple)):
200
            data = data[0]
201
        data = super().to_internal_value(clean_number(data))
202
        default_country = settings.PHONE_COUNTRY_CODES[settings.DEFAULT_COUNTRY_CODE]
203
        try:
204
            pn = phonenumbers.parse(data)
205
        except phonenumbers.NumberParseException:
206
            pn = phonenumbers.parse(data, default_country)
207
        return phonenumbers.format_number(pn, phonenumbers.PhoneNumberFormat.E164)
184 208

  
185 209

  
186
class FrenchPhoneNumberDRFField(PhoneNumberDRFField):
210
class FrenchPhoneNumberDRFField(serializers.CharField):
187 211
    default_validators = [french_validate_phone_number]
188 212

  
213
    def to_internal_value(self, data):
214
        return super().to_internal_value(clean_number(data))
215

  
189 216

  
190 217
validate_fr_postcode = RegexValidator(r'^\d{5}$', message=_('The value must be a valid french postcode'))
191 218

  
tests/api/test_all.py
2402 2402
    }
2403 2403
    resp = app.post_json('/api/users/', headers=headers, params=payload, status=201)
2404 2404
    assert resp.json['extra_phone'] == '+33499985643'
2405
    assert User.objects.get(username='janedoe').attributes.extra_phone == '+33499985643'
2405
    user = User.objects.get(username='janedoe')
2406
    assert user.attributes.extra_phone == '+33499985643'
2407

  
2408
    user.delete()
2409
    payload['extra_phone'] = ' + 334-99 98.56/433 '
2410
    resp = app.post_json('/api/users/', headers=headers, params=payload, status=201)
2411
    assert resp.json['extra_phone'] == '+334999856433'
2412
    user = User.objects.get(username='janedoe')
2413
    assert user.attributes.extra_phone == '+334999856433'
2414

  
2415
    user.delete()
2416
    payload['extra_phone'] = ' 04-99 98.56/433 '
2417
    resp = app.post_json('/api/users/', headers=headers, params=payload, status=201)
2418
    assert resp.json['extra_phone'] == '+334999856433'
2419
    user = User.objects.get(username='janedoe')
2420
    assert user.attributes.extra_phone == '+334999856433'
2421

  
2422
    user.delete()
2423
    payload['extra_phone'] = ''
2424
    resp = app.post_json('/api/users/', headers=headers, params=payload, status=201)
2425
    assert resp.json['extra_phone'] == ''
2426
    user = User.objects.get(username='janedoe')
2427
    assert user.attributes.extra_phone == ''
2406 2428

  
2407 2429

  
2408 2430
def test_phone_normalization_nok(settings, app, admin):
......
2419 2441
    payload['extra_phone'] = '1#2'
2420 2442
    app.post_json('/api/users/', headers=headers, params=payload, status=400)
2421 2443

  
2444
    payload['extra_phone'] = '+33499985643343434343'
2445
    app.post_json('/api/users/', headers=headers, params=payload, status=400)
2446

  
2447
    payload['extra_phone'] = '+334-99 98\\56/43'
2448
    app.post_json('/api/users/', headers=headers, params=payload, status=400)
2449

  
2450
    payload['extra_phone'] = '+334'
2451
    app.post_json('/api/users/', headers=headers, params=payload, status=400)
2452

  
2422 2453

  
2423 2454
def test_fr_phone_normalization_ok(settings, app, admin):
2424 2455
    headers = basic_authorization_header(admin)
2425
-