manager: search role with unaccent lookup (#87906)
gitea/authentic/pipeline/head This commit looks good Details

This commit is contained in:
Benjamin Dauvergne 2024-04-03 12:38:30 +02:00
parent 1d966eab30
commit 2b3d04a6d1
5 changed files with 59 additions and 3 deletions

View File

@ -0,0 +1,29 @@
# Generated by Django 3.2.23 on 2024-03-28 16:50
import django.contrib.postgres.indexes
import django.db.models.expressions
import django.db.models.functions.text
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('a2_rbac', '0039_set_user_view_permissions_by_ou'),
]
operations = [
migrations.AddIndex(
model_name='role',
index=django.contrib.postgres.indexes.GinIndex(
django.contrib.postgres.indexes.OpClass(
django.db.models.functions.text.Upper(
django.db.models.expressions.Func(
django.db.models.expressions.F('name'), function='public.immutable_unaccent'
)
),
'public.gin_trgm_ops',
),
name='name_idx',
),
),
]

View File

@ -23,10 +23,12 @@ from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres import indexes as postgresql_indexes
from django.contrib.postgres.fields import ArrayField
from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator
from django.db import models
from django.db.models.functions import Upper
from django.db.models.query import Prefetch, Q
from django.urls import reverse
from django.utils.text import slugify
@ -614,6 +616,15 @@ class Role(AbstractBase):
condition=models.Q(service__isnull=True, ou__isnull=True, admin_scope_ct__isnull=True),
),
]
indexes = [
postgresql_indexes.GinIndex(
postgresql_indexes.OpClass(
Upper(models.Func(models.F('name'), function='public.immutable_unaccent')),
'public.gin_trgm_ops',
),
name='name_idx',
),
]
def natural_key(self):
return [

View File

@ -405,7 +405,7 @@ class ServiceRoleSearchForm(CssClass, PrefixFormMixin, FormWithRequest):
for word in (w.strip() for w in self.cleaned_data.get('text').split(' ')):
if not word:
continue
qs = qs.filter(name__icontains=word)
qs = qs.filter(name__immutable_unaccent__icontains=word)
if not app_settings.SHOW_INTERNAL_ROLES and not self.cleaned_data.get('internals'):
qs = qs.exclude(slug__startswith='_')
return qs

View File

@ -1,10 +1,21 @@
from django.contrib.postgres.lookups import Unaccent as PGUnaccent
from django.db.models import CharField, TextField, Transform
from django.db.models.functions import Concat
from django.db.models.functions import ConcatPair as DjConcatPair
class Unaccent(PGUnaccent):
function = 'immutable_unaccent'
function = 'public.immutable_unaccent'
class UnaccentTransform(Transform):
bilateral = True
lookup_name = 'immutable_unaccent'
function = 'public.immutable_unaccent'
CharField.register_lookup(UnaccentTransform)
TextField.register_lookup(UnaccentTransform)
class ConcatPair(DjConcatPair):

View File

@ -390,7 +390,7 @@ def test_manager_role_csv_import(app, admin, ou1, ou2):
'role_names,search_text,expt_found',
[
(
['A random test role', 'Random test stuff', 'Some test role', 'Something else', 'SomeTest'],
['A random test rôle', 'Random test stuff', 'Some test role', 'Something else', 'SomeTest'],
' rand role',
[0],
),
@ -419,6 +419,11 @@ def test_manager_role_csv_import(app, admin, ou1, ou2):
' ',
[0, 1, 2, 3, 4],
),
(
['A random test role', 'Random test stuff', 'Some test role', 'Something else', 'SomeTest'],
'rôle',
[0, 2],
),
],
)
def test_manager_role_search(app, admin, role_names, search_text, expt_found):