api: let free text search accept local phone numbers (#69906)
gitea/authentic/pipeline/head Something is wrong with the build of this commit Details

This commit is contained in:
Paul Marillonnet 2022-10-17 14:42:20 +02:00
parent 8ee074f6ed
commit 3e53e2ecf8
2 changed files with 51 additions and 4 deletions

View File

@ -17,6 +17,8 @@
import unicodedata
import uuid
import phonenumbers
from django.conf import settings
from django.contrib.auth.models import BaseUserManager
from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.search import SearchQuery, TrigramDistance
@ -68,13 +70,30 @@ class UserQuerySet(models.QuerySet):
else:
return wrap_qs(self.filter(uuid=guid.hex))
default_country = settings.PHONE_COUNTRY_CODES[settings.DEFAULT_COUNTRY_CODE]['lang']
phone_number = None
formatted_phone_number = None
try:
phone_number = clean_number(search)
except ValidationError:
pass
phone_number = phonenumbers.parse(search)
except phonenumbers.NumberParseException:
try:
phone_number = phonenumbers.parse(search, default_country)
except phonenumbers.NumberParseException:
pass
if phone_number:
formatted_phone_number = phonenumbers.format_number(
phone_number, phonenumbers.PhoneNumberFormat.E164
)
else:
try:
formatted_phone_number = clean_number(search)
except ValidationError:
pass
if formatted_phone_number:
attribute_values = AttributeValue.objects.filter(
search_vector=SearchQuery(phone_number), attribute__kind='phone_number'
search_vector=SearchQuery(formatted_phone_number), attribute__kind='phone_number'
)
qs = self.filter(attribute_values__in=attribute_values).order_by('last_name', 'first_name')
if qs.exists():

View File

@ -2102,6 +2102,34 @@ def test_free_text_search(app, admin, settings):
assert resp.json['results'][0]['id'] == user.id
def test_free_text_search_local_phone(app, admin, simple_user, settings):
app.authorization = ('Basic', (admin.username, admin.username))
settings.DEFAULT_COUNTRY_CODE = '33'
Attribute.objects.create(
kind='phone_number', name='phone', label='Phone', required=False, searchable=True
)
simple_user.attributes.phone = '+33612345678'
simple_user.save()
resp = app.get('/api/users/?q=+33612345678')
assert len(resp.json['results']) == 1
assert resp.json['results'][0]['id'] == simple_user.id
# non globally-unique phone number still resolvable from DEFAULT_COUNTRY_CODE prefix
resp = app.get('/api/users/?q=0612345678')
assert len(resp.json['results']) == 1
assert resp.json['results'][0]['id'] == simple_user.id
# additionnaly, erroneous data must still be searchable
simple_user.attributes.phone = '0xf00d'
simple_user.save()
resp = app.get('/api/users/?q=0xf00d')
assert len(resp.json['results']) == 1
assert resp.json['results'][0]['id'] == simple_user.id
def test_find_duplicates(app, admin, settings):
settings.LANGUAGE_CODE = 'fr'
app.authorization = ('Basic', (admin.username, admin.username))