Skip to content

Commit 10dab8e

Browse files
committed
Attribute filter - Allow multiple values for PostgreSQL layers and active option
1 parent 7087ac9 commit 10dab8e

File tree

2 files changed

+55
-15
lines changed

2 files changed

+55
-15
lines changed

lizmap_server/lizmap_accesscontrol.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -391,19 +391,25 @@ def get_lizmap_layer_filter(self, layer: QgsVectorLayer, filter_type: FilterType
391391

392392
return login_filter
393393

394-
login_filter = self._filter_by_login(cfg_layer_login_filter, groups, user_login)
394+
login_filter = self._filter_by_login(
395+
cfg_layer_login_filter,
396+
groups,
397+
user_login,
398+
layer.dataProvider().name(),
399+
)
395400
if polygon_filter:
396401
return f'{polygon_filter} AND {login_filter}'
397402

398403
return login_filter
399404

400405
@staticmethod
401-
def _filter_by_login(cfg_layer_login_filter: dict, groups: tuple, login: str) -> str:
406+
def _filter_by_login(cfg_layer_login_filter: dict, groups: tuple, login: str, provider: str) -> str:
402407
""" Build the string according to the filter by login configuration.
403408
404409
:param cfg_layer_login_filter: The Lizmap Filter by login configuration.
405410
:param groups: List of groups for the current user
406411
:param login: The current user
412+
:param provider: The layer data provider ('postgres' for example)
407413
"""
408414
# List of values for expression
409415
values = []
@@ -420,7 +426,9 @@ def _filter_by_login(cfg_layer_login_filter: dict, groups: tuple, login: str) ->
420426

421427
# Since LWC 3.8, we allow to have a list of groups (or logins)
422428
# separated by comma, with NO SPACES
423-
# e.g. field "filter_field" can contain 'group_a,group_b,group_c'
429+
# only for PostgreSQL layers and if the option allow_multiple_acl_values
430+
# is set to True
431+
# For example the field can contain 'group_a,group_b,group_c'
424432
# To use only pure SQL allowed by QGIS, we can use LIKE items
425433
# For big dataset, a GIN index with pg_trgm must be used for the
426434
# filter field to improve performance
@@ -442,17 +450,19 @@ def _filter_by_login(cfg_layer_login_filter: dict, groups: tuple, login: str) ->
442450
# equality
443451
filters.append(f'{quoted_field} = {quoted_value}')
444452

445-
# begins with value & comma
446-
quoted_like_value = QgsExpression.quotedString(f'{value},%')
447-
filters.append(f'{quoted_field} LIKE {quoted_like_value}')
453+
# Add LIKE statements to manage multiple values separated by comma
454+
if provider == 'postgres' and cfg_layer_login_filter.get('allow_multiple_acl_values'):
455+
# begins with value & comma
456+
quoted_like_value = QgsExpression.quotedString(f'{value},%')
457+
filters.append(f'{quoted_field} LIKE {quoted_like_value}')
448458

449-
# ends with comma & value
450-
quoted_like_value = QgsExpression.quotedString(f'%,{value}')
451-
filters.append(f'{quoted_field} LIKE {quoted_like_value}')
459+
# ends with comma & value
460+
quoted_like_value = QgsExpression.quotedString(f'%,{value}')
461+
filters.append(f'{quoted_field} LIKE {quoted_like_value}')
452462

453-
# value between two commas
454-
quoted_like_value = QgsExpression.quotedString(f'%,{value},%')
455-
filters.append(f'{quoted_field} LIKE {quoted_like_value}')
463+
# value between two commas
464+
quoted_like_value = QgsExpression.quotedString(f'%,{value},%')
465+
filters.append(f'{quoted_field} LIKE {quoted_like_value}')
456466

457467
# Build the filter for this value
458468
value_filters.append(' OR '.join(filters))

test/test_lizmap_accesscontrol.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -595,14 +595,44 @@ def test_tos_strict_layers_true(client):
595595
assert "bing-satellite" not in content
596596

597597

598-
def test_filter_by_login():
599-
""" Test about comma separated list of values with the current user."""
598+
def test_filter_by_login_simple_values():
599+
""" Test filter with simple values in field with the current user."""
600600
config = {
601601
'filterPrivate': ['a', 'b'],
602602
'filterAttribute': 'f',
603+
'allow_multiple_acl_values': False,
603604
}
604-
output = LizmapAccessControlFilter._filter_by_login(config, ('grp_1', 'grp_2'), 'a')
605+
output = LizmapAccessControlFilter._filter_by_login(config, ('grp_1', 'grp_2'), 'a', 'other_provider')
606+
assert (
607+
"\"f\" = 'a' OR \"f\" = 'all'"
608+
) == output, output
609+
610+
611+
def test_filter_by_login_postgres_multiple_values():
612+
""" Test filter with comma separated list of values with the current user."""
613+
config = {
614+
'filterPrivate': ['a', 'b'],
615+
'filterAttribute': 'f',
616+
'allow_multiple_acl_values': True,
617+
}
618+
output = LizmapAccessControlFilter._filter_by_login(config, ('grp_1', 'grp_2'), 'a', 'postgres')
605619
assert (
606620
"\"f\" = 'a' OR \"f\" LIKE 'a,%' OR \"f\" LIKE '%,a' OR \"f\" LIKE '%,a,%' OR \"f\" = 'all' "
607621
"OR \"f\" LIKE 'all,%' OR \"f\" LIKE '%,all' OR \"f\" LIKE '%,all,%'"
608622
) == output, output
623+
624+
625+
def test_filter_by_login_postgres_multiple_values_deactivated():
626+
"""
627+
Test filter with comma separated list of values with the current user
628+
but with option disabled
629+
"""
630+
config = {
631+
'filterPrivate': ['a', 'b'],
632+
'filterAttribute': 'f',
633+
'allow_multiple_acl_values': False,
634+
}
635+
output = LizmapAccessControlFilter._filter_by_login(config, ('grp_1', 'grp_2'), 'a', 'postgres')
636+
assert (
637+
"\"f\" = 'a' OR \"f\" = 'all'"
638+
) == output, output

0 commit comments

Comments
 (0)