Skip to content

Commit d2777bd

Browse files
committed
Implicitly grant read permissions for data/wfs_layer if any create/update/delete permissions is granted
1 parent afa4df5 commit d2777bd

File tree

4 files changed

+75
-7
lines changed

4 files changed

+75
-7
lines changed

src/config_generator/data_service_config.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,14 @@ def dataset_permissions(self, role, session):
273273
for layer_name in datasets:
274274

275275
# lookup permissions (dataset restricted by default)
276-
dataset_restricted_for_public = layer_name not in \
277-
public_permissions['data'].get(map_name, {})
278-
dataset_permitted_for_role = layer_name in \
279-
role_permissions['data'].get(map_name, {})
276+
# NOTE: dataset readable is implicit if any of 'data_create', data_update', 'data_delete' is permitted
277+
dataset_restricted_for_public = True
278+
dataset_permitted_for_role = False
279+
for resource_type in ['data', 'data_create', 'data_update', 'data_delete']:
280+
dataset_restricted_for_public &= layer_name not in \
281+
public_permissions[resource_type].get(map_name, {})
282+
dataset_permitted_for_role |= layer_name in \
283+
role_permissions[resource_type].get(map_name, {})
280284
if dataset_restricted_for_public and not dataset_permitted_for_role:
281285
# dataset not permitted
282286
continue

src/config_generator/ogc_service_config.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,10 +772,27 @@ def collect_wfs_layer_permissions(self, service_name, cap, is_public_role,
772772
layer_permitted_for_role = layer['name'] in \
773773
role_permissions['wfs_layer'].get(service_name, {})
774774

775-
layer_or_service_restricted = layer_restricted_for_public or service_restricted_for_public
775+
# lookup permissions
776+
if self.permissions_default_allow:
777+
# NOTE: restricted if wfs_layer is restricted
778+
layer_restricted_for_public = layer['name'] in \
779+
public_restrictions['wfs_layer'].get(service_name, {})
780+
else:
781+
# NOTE: restricted by default, permitted also if any of 'wfs_layer_create', wfs_layer_update', 'wfs_layer_delete' are permitted
782+
layer_restricted_for_public = True
783+
for resource_type in ['wfs_layer', 'wfs_layer_create', 'wfs_layer_update', 'wfs_layer_delete']:
784+
layer_restricted_for_public &= layer['name'] not in \
785+
public_permissions[resource_type].get(service_name, {})
786+
787+
layer_permitted_for_role = False
788+
for resource_type in ['wfs_layer', 'wfs_layer_create', 'wfs_layer_update', 'wfs_layer_delete']:
789+
layer_permitted_for_role |= layer['name'] in \
790+
role_permissions[resource_type].get(service_name, {})
791+
776792
if layer_restricted_for_public and not layer_permitted_for_role:
777793
# wfs_layer not permitted at least for reading
778794
continue
795+
layer_or_service_restricted = layer_restricted_for_public or service_restricted_for_public
779796

780797
layer_permissions = OrderedDict()
781798
layer_permissions['name'] = layer['name']

src/config_generator/theme_reader.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ def __get_edit_datasets(self, service_name):
173173
# map not found
174174
return []
175175

176-
# query writable data permissions
177-
resource_types = ['data']
176+
# query data permissions
177+
resource_types = ['data', 'data_create', 'data_update', 'data_delete']
178178
datasets_query = session.query(Permission) \
179179
.join(Permission.resource) \
180180
.filter(Resource.parent_id == map_obj.id) \

tests/permissions_tests.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,30 @@ def test_data_permissions(self):
314314
self.assertEqual(len(parse("$.roles[?(@.role=='admin')].permissions.data_datasets[?(@.name=='qwc_demo.edit_polygons' & @.deletable)]").find(perm)), 0)
315315
self.assertEqual(len(parse("$.roles[?(@.role=='admin')].permissions.data_datasets[?(@.name=='qwc_demo.edit_polygons')].attributes[?(@=='description')]").find(perm)), 1)
316316

317+
318+
# Check that dataset is readable/creatable if only data_create is set
319+
self.cursor.execute(f"""
320+
DELETE FROM qwc_config.permissions;
321+
DELETE FROM qwc_config.resources;
322+
INSERT INTO qwc_config.resources (id, parent_id, type, name)
323+
VALUES
324+
(1, NULL, 'map', 'qwc_demo'),
325+
(2, 1, 'data_create', 'edit_points');
326+
INSERT INTO qwc_config.permissions (id, role_id, resource_id, priority, write)
327+
VALUES
328+
(1, {ROLE_PUBLIC}, 1, 0, FALSE),
329+
(2, {ROLE_PUBLIC}, 2, 0, FALSE);
330+
""")
331+
PermissionsTests.conn.commit()
332+
333+
perm = self.__run_config_generator({})
334+
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.data_datasets[?(@.name=='qwc_demo.edit_points' & @.writable==false)]").find(perm)), 1)
335+
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.data_datasets[?(@.name=='qwc_demo.edit_points' & @.creatable==true)]").find(perm)), 1)
336+
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.data_datasets[?(@.name=='qwc_demo.edit_points' & @.readable==true)]").find(perm)), 1)
337+
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.data_datasets[?(@.name=='qwc_demo.edit_points' & @.updatable==false)]").find(perm)), 1)
338+
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.data_datasets[?(@.name=='qwc_demo.edit_points' & @.deletable==false)]").find(perm)), 1)
339+
340+
317341
def test_wfs_permissions(self):
318342
""" Test WFS permissions. """
319343

@@ -386,6 +410,29 @@ def test_wfs_permissions(self):
386410
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.wfs_services[?(@.name=='scan/wfs_test')].layers[?(@.name=='ÖV-_Linien')].attributes[?(@=='beschreibung')]").find(perm)), 0)
387411
self.assertEqual(len(parse("$.roles[?(@.role=='admin')].permissions.wfs_services[?(@.name=='scan/wfs_test')].layers[?(@.name=='ÖV-_Linien')].attributes[?(@=='beschreibung')]").find(perm)), 1)
388412

413+
# Check that wfs_layer is readable/creatable if only data_create is set
414+
self.cursor.execute(f"""
415+
DELETE FROM qwc_config.permissions;
416+
DELETE FROM qwc_config.resources;
417+
INSERT INTO qwc_config.resources (id, parent_id, type, name)
418+
VALUES
419+
(1, NULL, 'wfs_service', 'scan/wfs_test'),
420+
(2, 1, 'wfs_layer_create', 'ÖV: Haltestellen');
421+
INSERT INTO qwc_config.permissions (id, role_id, resource_id, priority, write)
422+
VALUES
423+
(1, {ROLE_PUBLIC}, 1, 0, FALSE),
424+
(2, {ROLE_PUBLIC}, 2, 0, FALSE);
425+
""")
426+
PermissionsTests.conn.commit()
427+
428+
perm = self.__run_config_generator({})
429+
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.wfs_services[?(@.name=='scan/wfs_test')].layers[?(@.name=='ÖV-_Haltestellen' & @.writable==false)]").find(perm)), 1)
430+
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.wfs_services[?(@.name=='scan/wfs_test')].layers[?(@.name=='ÖV-_Haltestellen' & @.creatable==true)]").find(perm)), 1)
431+
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.wfs_services[?(@.name=='scan/wfs_test')].layers[?(@.name=='ÖV-_Haltestellen' & @.readable==true)]").find(perm)), 1)
432+
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.wfs_services[?(@.name=='scan/wfs_test')].layers[?(@.name=='ÖV-_Haltestellen' & @.updatable==false)]").find(perm)), 1)
433+
self.assertEqual(len(parse("$.roles[?(@.role=='public')].permissions.wfs_services[?(@.name=='scan/wfs_test')].layers[?(@.name=='ÖV-_Haltestellen' & @.deletable==false)]").find(perm)), 1)
434+
435+
389436
def test_public_permissions_default_restrict_no_permissions(self):
390437
""" Test permissions_default_allow=false and no permissions. """
391438

0 commit comments

Comments
 (0)