def test_editing_view_retrieve_data(self): """Test constraint filter for editing API - SELECT""" client = APIClient() editing_layer = Layer.objects.get(name='editing_layer') self.assertTrue( client.login(username=self.test_user2.username, password=self.test_user2.username)) assign_perm('change_layer', self.test_user2, editing_layer) self.assertTrue( self.test_user2.has_perm('qdjango.change_layer', editing_layer)) response = client.post( '/vector/api/editing/qdjango/%s/%s/' % (editing_layer.project_id, editing_layer.qgs_layer_id), {}, format='json') self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) fids = [int(f['id']) for f in jcontent['vector']['data']['features']] # All fids should be here self.assertEqual(fids, [1, 2, 3, 4]) # Now add a constraint for user2 constraint_layer = Layer.objects.get(name=self.constraint_layer_name) constraint = GeoConstraint(layer=editing_layer, constraint_layer=constraint_layer, for_editing=True) constraint.save() rule = GeoConstraintRule(constraint=constraint, user=self.test_user2, rule='name=\'bagnolo\'') rule.save() response = client.post( '/vector/api/editing/qdjango/%s/%s/' % (editing_layer.project_id, editing_layer.qgs_layer_id), {}, format='json') self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) fids = [int(f['id']) for f in jcontent['vector']['data']['features']] # Only allowed fids self.assertEqual(fids, [1, 2]) # Test with inactive constraint constraint.active = False constraint.save() response = client.post( '/vector/api/editing/qdjango/%s/%s/' % (editing_layer.project_id, editing_layer.qgs_layer_id), {}, format='json') self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) fids = [int(f['id']) for f in jcontent['vector']['data']['features']] # All fids should be here self.assertEqual(fids, [1, 2, 3, 4]) # reset test db self.reset_db_data()
def validate_constraint(**kwargs): """Checks whether the instance validates the active constraints in commit mode kwargs: ["layer_metadata", "mode", "data", "user"] """ mode = kwargs['mode'] if mode not in (EDITING_POST_DATA_UPDATED, EDITING_POST_DATA_ADDED): return editing_layer = Layer.objects.get(pk=kwargs['layer_metadata'].layer_id) user = kwargs['user'] # check rule presence for layer rules = GeoConstraintRule.get_active_constraints_for_user(user, editing_layer, context='e') if len(rules) == 0: return coords = kwargs['data']['feature']['geometry']['coordinates'] geom_type = kwargs['data']['feature']['geometry']['type'] geom_class = getattr(geos, geom_type) # For multi geometry type if geom_type == 'MultiPolygon': Polygon = getattr(geos, 'Polygon') coords = [Polygon(p) for p in coords[0]] if geom_type == 'MultiLineString': LineString = getattr(geos, 'LineString') coords = [LineString(p) for p in coords] if geom_type == 'MultiPoint': Point = getattr(geos, 'Point') coords = [Point(p) for p in coords] # set spatial predicate for validation spatial_predicate = getattr(settings, 'EDITING_CONSTRAINT_SPATIAL_PREDICATE', 'contains') for rule in rules: allowed_geom, __ = rule.get_constraint_geometry() geom = geom_class(coords) geom.srid = allowed_geom.srid predicate_method = getattr(allowed_geom, spatial_predicate) if not predicate_method(geom): raise IntegrityError( _('Constraint validation failed for geometry: %s') % geom.wkt)
def apply_filter(self, request, metadata_layer, qgis_feature_request, view): qgis_layer = metadata_layer.qgis_layer rule_parts = [] rules = GeoConstraintRule.get_active_constraints_for_user(request.user, view.layer, context=getattr(view, 'context', 'v')) for rule in rules: expression = rule.get_qgis_expression() if expression: rule_parts.append(expression) if rule_parts: expression = ' AND '.join(rule_parts) qgis_feature_request.combineFilterExpression(expression)
def test_sql_validation(self): """Test SQL rule validation""" editing_layer = Layer.objects.get(name='editing_layer') constraint_layer = Layer.objects.get(name=self.constraint_layer_name) constraint = GeoConstraint( layer=editing_layer, constraint_layer=constraint_layer) constraint.save() rule = GeoConstraintRule(constraint=constraint, user=self.test_user1, rule='int_f=1') self.assertTrue(rule.validate_sql()[0], rule.validate_sql()[1]) rule.rule = 'dfs?Adfasdfs[đß+èèfsd+' self.assertFalse(rule.validate_sql()[0])
def layerFilterExpression(self, layer): """Retrieve and sets user layer constraints""" try: qdjango_layer = Layer.objects.get(project=QGS_SERVER.project, qgs_layer_id=layer.id()) except Layer.DoesNotExist: QgsMessageLog.logMessage( "SingleLayerExpressionAccessControlFilter for user %s: layer id %s does not exist!" % (QGS_SERVER.user, layer.id()), "", Qgis.Warning) return "" rule = GeoConstraintRule.get_rule_definition_for_user( QGS_SERVER.user, qdjango_layer) if rule: QgsMessageLog.logMessage( "SingleLayerExpressionAccessControlFilter rule for user %s and layer id %s: %s" % (QGS_SERVER.user, layer.id(), rule), "", Qgis.Info) return rule
def apply_filter(self, request, qgis_layer, qgis_feature_request, view): rule_parts = [] rules = GeoConstraintRule.get_active_constraints_for_user( request.user, view.layer, context=getattr(view, 'context', 'v')) for rule in rules: expression = rule.get_qgis_expression() if expression: rule_parts.append(expression) if rule_parts: expression = ' AND '.join(rule_parts) current_expression = qgis_feature_request.filterExpression() if current_expression: expression = f'({current_expression.expression()}) AND ({expression})' qgis_feature_request.setFilterExpression(expression)
def test_editing_view_insert_data(self): """Test constraint filter for editing API - INSERT""" client = APIClient() editing_layer = Layer.objects.get(name='editing_layer') self.assertTrue( client.login(username=self.test_user2.username, password=self.test_user2.username)) assign_perm('change_layer', self.test_user2, editing_layer) self.assertTrue( self.test_user2.has_perm('qdjango.change_layer', editing_layer)) # Now add a constraint for user2: strict for editing constraint_layer = Layer.objects.get(name=self.constraint_layer_name) constraint = GeoConstraint(layer=editing_layer, constraint_layer=constraint_layer, for_editing=True, for_view=False) constraint.save() rule = GeoConstraintRule(constraint=constraint, user=self.test_user2, rule='name=\'bagnolo\'') rule.save() # Retrieve the data response = client.post( '/vector/api/editing/qdjango/%s/%s/' % (editing_layer.project_id, editing_layer.qgs_layer_id), {}, format='json') self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) fids = [int(f['id']) for f in jcontent['vector']['data']['features']] # All fids should be here self.assertEqual(fids, [1, 2]) # Get lock id for fid 1 lock_id = [ l['lockid'] for l in jcontent['featurelocks'] if l['featureid'] == '1' ][0] # Add the geometry outside the allowed rule new_geom = [10, 55] payload = { "add": [{ "geometry": { "coordinates": new_geom, "type": "Point" }, "id": "_new_1564320704661", "properties": { "name": "constraint violation" }, "type": "Feature" }], "delete": [], "lockids": [{ "featureid": "1", "lockid": "%s" % lock_id }], "relations": {}, "update": [] } # Verify that the update has failed response = client.post( '/vector/api/commit/qdjango/%s/%s/' % (editing_layer.project_id, editing_layer.qgs_layer_id), payload, format='json') self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) self.assertEqual( jcontent["errors"], "Constraint validation failed for geometry: POINT (10 55)") # Test with inactive constraint constraint.active = False constraint.save() # Add the geometry outside the allowed rule new_geom = [10, 55] payload = { "add": [{ "geometry": { "coordinates": new_geom, "type": "Point" }, "id": "_new_1564320704661", "properties": { "name": "constraint violation" }, "type": "Feature" }], "delete": [], "lockids": [{ "featureid": "1", "lockid": "%s" % lock_id }], "relations": {}, "update": [] } # Verify that the update was successful response = client.post( '/vector/api/commit/qdjango/%s/%s/' % (editing_layer.project_id, editing_layer.qgs_layer_id), payload, format='json') self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) new_fid = int(jcontent['response']['new'][0]['id']) self.assertTrue(new_fid > 0) # Retrieve the data response = client.post( '/vector/api/editing/qdjango/%s/%s/' % (editing_layer.project_id, editing_layer.qgs_layer_id), {}, format='json') self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) geom = jcontent['vector']['data']['features'][-1]['geometry'][ 'coordinates'] self.assertEqual(geom, [10, 55]) self.assertEqual(jcontent['vector']['data']['features'][-1]['id'], str(new_fid)) # reset test db self.reset_db_data()
def test_unique(self): """Check unique together conditions""" editing_layer = Layer.objects.get(name='editing_layer') constraint_layer = Layer.objects.get(name=self.constraint_layer_name) constraint = GeoConstraint(layer=editing_layer, constraint_layer=constraint_layer) constraint.save() rule = GeoConstraintRule(constraint=constraint, user=self.test_user1, rule='int_f=1') rule.save() # Check unique_together with transaction.atomic(): with self.assertRaises(IntegrityError) as ex: rule_duplicate = GeoConstraintRule(constraint=constraint, user=self.test_user1, rule='int_f=1') rule_duplicate.save() rule3 = GeoConstraintRule(constraint=constraint, group=self.group, rule='int_f=1') rule3.save() with transaction.atomic(): with self.assertRaises(IntegrityError) as ex: rule3_duplicate = GeoConstraintRule(constraint=constraint, group=self.group, rule='int_f=1') rule3_duplicate.save()
def test_create_constraint(self): """Test constraints creation""" editing_layer = Layer.objects.get(name='editing_layer') constraint_layer = Layer.objects.get(name=self.constraint_layer_name) constraint = GeoConstraint(layer=editing_layer, constraint_layer=constraint_layer) # Test validation constraint.clean() constraint.save() # Check layer types (PG or SL) with self.assertRaises(ValidationError) as ex: GeoConstraint(layer=editing_layer, constraint_layer=Layer(layer_type='GDAL')).clean() with self.assertRaises(ValidationError) as ex: GeoConstraint(layer=Layer(layer_type='GDAL'), constraint_layer=constraint_layer).clean() # Check if constraints layer is polygon with self.assertRaises(ValidationError) as ex: GeoConstraint(layer=constraint_layer, constraint_layer=editing_layer).clean() # Check self constraint with self.assertRaises(ValidationError) as ex: GeoConstraint(layer=constraint_layer, constraint_layer=constraint_layer).clean() rule = GeoConstraintRule(constraint=constraint, user=self.test_user1, rule='int_f=1') rule.save() # Test validation with self.assertRaises(ValidationError) as ex: rule2 = GeoConstraintRule(constraint=constraint, user=self.test_user1, group=self.group, rule='int_f=1') rule2.clean() # Test constraints for user rules = GeoConstraintRule.get_constraints_for_user( self.test_user1, editing_layer) self.assertEqual(len(rules), 1) self.assertEqual(rules[0], rule) # Test the other path with group rule3 = GeoConstraintRule(constraint=constraint, group=self.group, rule='int_f=1') rule3.save() rules = GeoConstraintRule.get_constraints_for_user( self.test_user3, editing_layer) self.assertEqual(len(rules), 1) self.assertEqual(rules[0], rule3) # Test we need a user OR a group with self.assertRaises(ValidationError) as ex: rule4 = GeoConstraintRule(constraint=constraint, rule='int_f=1') rule4.clean() # Test we get nothing for the other layer and user rules = GeoConstraintRule.get_constraints_for_user( self.test_user2, constraint_layer) self.assertEqual(len(rules), 0) # Test inactive constraints for user constraint.active = False constraint.save() rules = GeoConstraintRule.get_constraints_for_user( self.test_user3, editing_layer) self.assertEqual(len(rules), 1) self.assertEqual(rules[0], rule3) rules = GeoConstraintRule.get_active_constraints_for_user( self.test_user3, editing_layer) self.assertEqual(len(rules), 0)
def test_trace_api(self): """/qplotly/api/trace API""" qplotlywidget_id = QplotlyWidget.objects.all()[0].pk qplotlywidget_3857_id = QplotlyWidget.objects.all()[1].pk response = self._testApiCall( 'qplotly-api-trace', args=[self.project.instance.pk, qplotlywidget_id]) jcontent = json.loads(response.content) trace_data = json.loads(response.content)['data'] self.assertEqual(len(trace_data), 1) self.assertEqual(trace_data[0]['type'], 'histogram') self.assertEqual(len(trace_data[0]['x']), 51) self.assertIn('Italia', trace_data[0]['x']) # for 3857 projetc response = self._testApiCall( 'qplotly-api-trace', args=[self.project_3857.instance.pk, qplotlywidget_3857_id]) jcontent = json.loads(response.content) trace_data = json.loads(response.content)['data'] self.assertEqual(len(trace_data), 1) self.assertEqual(trace_data[0]['type'], 'histogram') self.assertEqual(len(trace_data[0]['x']), 51) self.assertIn('Italia', trace_data[0]['x']) # With a session token filter # --------------------------- countries = Layer.objects.get( project_id=self.project.instance.pk, qgs_layer_id='countries_d53dfb9a_98e1_4196_a601_eed9a33f47c3') # create a token filter session_token = SessionTokenFilter.objects.create( user=self.test_user1) # as admin01 session_filter = session_token.stf_layers.create( layer=countries, qgs_expr="NAME_IT = 'Albania'") response = self._testApiCall( 'qplotly-api-trace', args=[self.project.instance.pk, qplotlywidget_id], kwargs={'filtertoken': session_token.token}) jcontent = json.loads(response.content) trace_data = json.loads(response.content)['data'] self.assertEqual(len(trace_data), 1) self.assertEqual(trace_data[0]['type'], 'histogram') self.assertEqual(len(trace_data[0]['x']), 1) self.assertNotIn('Italia', trace_data[0]['x']) # Geometry contraint layer # ------------------------ constraint = SingleLayerConstraint(layer=countries, active=True) constraint.save() rule = ConstraintExpressionRule( constraint=constraint, user=self.test_user1, rule= "intersects_bbox( $geometry, geom_from_wkt( 'POLYGON((8 51, 11 51, 11 52, 11 52, 8 51))') )" ) rule.save() response = self._testApiCall( 'qplotly-api-trace', args=[self.project.instance.pk, qplotlywidget_id]) jcontent = json.loads(response.content) trace_data = json.loads(response.content)['data'] self.assertEqual(len(trace_data), 1) self.assertEqual(trace_data[0]['type'], 'histogram') self.assertEqual(len(trace_data[0]['x']), 1) self.assertIn('Germania', trace_data[0]['x']) # add new plotly widget for cities layer # ====================================== cities = self.project.instance.layer_set.get( qgs_layer_id='cities10000eu_399beab0_e385_4ce1_9b59_688d02930517') widget = QplotlyWidget.objects.create( xml=self.cities_histogram_plot_xml, datasource=cities.datasource, type='histogram', title='', project=self.project.instance) widget.layers.add(cities) cities_3857 = self.project_3857.instance.layer_set.get( qgs_layer_id='cities10000eu_399beab0_e385_4ce1_9b59_688d02930517') widget_3857 = QplotlyWidget.objects.create( xml=self.cities_histogram_plot_xml, datasource=cities_3857.datasource, type='histogram', title='', project=self.project_3857.instance) widget_3857.layers.add(cities_3857) response = self._testApiCall( 'qplotly-api-trace', args=[self.project.instance.pk, widget.pk]) jcontent = json.loads(response.content) trace_data = json.loads(response.content)['data'] self.assertEqual(len(trace_data), 1) self.assertEqual(trace_data[0]['type'], 'histogram') self.assertEqual(len(trace_data[0]['x']), 8965) self.assertIn('IT', trace_data[0]['x']) self.assertIn('DE', trace_data[0]['x']) # check relation one to many response = self._testApiCall( 'qplotly-api-trace', args=[self.project.instance.pk, widget.pk], kwargs={ 'relationonetomany': 'cities1000_ISO2_CODE_countries__ISOCODE|18' }) jcontent = json.loads(response.content) trace_data = json.loads(response.content)['data'] self.assertEqual(len(trace_data), 1) self.assertEqual(trace_data[0]['type'], 'histogram') self.assertEqual(len(trace_data[0]['x']), 1124) self.assertIn('IT', trace_data[0]['x']) self.assertNotIn('DE', trace_data[0]['x']) # test in_bbox filter # ------------------------------------- response = self._testApiCall( 'qplotly-api-trace', args=[self.project.instance.pk, widget.pk], kwargs={'in_bbox': '9.7,41.4,13.0,45.6'}) jcontent = json.loads(response.content) trace_data = json.loads(response.content)['data'] self.assertEqual(len(trace_data), 1) self.assertEqual(trace_data[0]['type'], 'histogram') self.assertEqual(len(trace_data[0]['x']), 329) self.assertIn('IT', trace_data[0]['x']) self.assertNotIn('DE', trace_data[0]['x']) # for 3857 and reproject response = self._testApiCall( 'qplotly-api-trace', args=[self.project_3857.instance.pk, widget_3857.pk], kwargs={ 'in_bbox': '1079799.06069475435651839,5071521.81142560951411724,1447153.38031255709938705,5716479.01532683055847883' }) jcontent = json.loads(response.content) trace_data = json.loads(response.content)['data'] self.assertEqual(len(trace_data), 1) self.assertEqual(trace_data[0]['type'], 'histogram') self.assertEqual(len(trace_data[0]['x']), 329) self.assertIn('IT', trace_data[0]['x']) self.assertNotIn('DE', trace_data[0]['x']) # Geocontraint # ------------------------ constraint = GeoConstraint(layer=cities, constraint_layer=countries, active=True) constraint.save() rule = GeoConstraintRule(constraint=constraint, user=self.test_user1, rule="ISOCODE = 'IT'") rule.save() response = self._testApiCall( 'qplotly-api-trace', args=[self.project.instance.pk, widget.pk]) jcontent = json.loads(response.content) trace_data = json.loads(response.content)['data'] self.assertEqual(len(trace_data), 1) self.assertEqual(trace_data[0]['type'], 'histogram') self.assertEqual(len(trace_data[0]['x']), 1115) self.assertIn('IT', trace_data[0]['x']) self.assertNotIn('DE', trace_data[0]['x']) widget.delete()
def test_initconfig_plugin_start(self): """ Test initconfig api""" # activate editing plugins: set editing_layer as editing layer G3WEditingLayer.objects.create(app_name='qdjango', layer_id=self.editing_layer.pk) # api client instance client = APIClient() self.assertTrue( client.login(username=self.test_user_admin1.username, password=self.test_user_admin1.username)) url = reverse('group-map-config', args=[ self.project_group.slug, 'qdjango', self.project.instance.pk ]) response = client.get(url) self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) # check editing into plugins section self.assertTrue('editing' in jcontent['group']['plugins']) plugin = jcontent['group']['plugins']['editing'] # check gid and TYPES self.assertEqual(plugin['gid'], 'qdjango:{}'.format(self.project.instance.pk)) client.logout() # check for constraint # =================================== # add constraints editing_layer = Layer.objects.get(name='editing_layer') constraint_layer = Layer.objects.get(name='constraint_layer') constraint = GeoConstraint(layer=editing_layer, constraint_layer=constraint_layer) constraint.save() rule = GeoConstraintRule(constraint=constraint, user=self.test_user3, rule='name=\'bagnolo\'') rule.save() self.assertTrue( client.login(username=self.test_user3.username, password=self.test_user3.username)) response = client.get(url) self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) # check archiweb into plugins section self.assertTrue('editing' in jcontent['group']['plugins']) plugin = jcontent['group']['plugins']['editing'] # check gid and TYPES self.assertEqual(plugin['gid'], 'qdjango:{}'.format(self.project.instance.pk)) self.assertTrue('constraints' in plugin) self.assertEqual( plugin['constraints'][editing_layer.qgs_layer_id] ['geometry_api_url'], reverse('geoconstraint-api-geometry', kwargs={'layer_id': editing_layer.pk})) constraint.delete()
def test_constraintrule_api_permissions(self): """Test API constraint rule permissions""" client = APIClient() self.assertTrue( client.login(username=self.test_user1.username, password=self.test_user1.username)) editing_layer = Layer.objects.get(name='editing_layer') constraint_layer = Layer.objects.get(name='constraint_layer') constraint = GeoConstraint(layer=editing_layer, constraint_layer=constraint_layer) constraint.save() rule = GeoConstraintRule(constraint=constraint, user=self.test_user3, group=None, rule="name='pinerolo'") rule.save() # check 403 for rule list by constraint url = reverse('geoconstraintrule-api-filter-by-constraint', kwargs={'constraint_id': constraint.pk}) response = client.get(url, {}, format='json') self.assertEqual(response.status_code, 403) # check 403 for rule list by editing layer url = reverse('geoconstraintrule-api-filter-by-layer', kwargs={'layer_id': editing_layer.pk}) response = client.get(url, {}, format='json') self.assertEqual(response.status_code, 403) # check 403 for rule list by rule user url = reverse('geoconstraintrule-api-filter-by-user', kwargs={'user_id': self.test_user3.pk}) response = client.get(url, {}, format='json') self.assertEqual(response.status_code, 403) # check 403 for rule detail url = reverse('geoconstraintrule-api-detail', kwargs={'pk': rule.pk}) response = client.get(url, {}, format='json') self.assertEqual(response.status_code, 403) # check pass for rule list by constraint client.logout() self.assertTrue( client.login(username=self.test_user2.username, password=self.test_user2.username)) url = reverse('geoconstraintrule-api-filter-by-constraint', kwargs={'constraint_id': constraint.pk}) response = client.get(url, {}, format='json') self.assertEqual(response.status_code, 200) # check 200 for rule list by editing layer url = reverse('geoconstraintrule-api-filter-by-layer', kwargs={'layer_id': editing_layer.pk}) response = client.get(url, {}, format='json') self.assertEqual(response.status_code, 200) # check 403 for rule list by rule user (only admin can query rules by user) url = reverse('geoconstraintrule-api-filter-by-user', kwargs={'user_id': self.test_user3.pk}) response = client.get(url, {}, format='json') self.assertEqual(response.status_code, 403) # check 200 for rule detail url = reverse('geoconstraintrule-api-detail', kwargs={'pk': rule.pk}) response = client.get(url, {}, format='json') self.assertEqual(response.status_code, 200) client.logout() self.assertTrue( client.login(username=self.test_user3.username, password=self.test_user3.username)) # Test get Geometries constraint for request user url = reverse('geoconstraint-api-geometry', kwargs={'layer_id': editing_layer.pk}) response = client.get(url, {}, format='json') self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) self.assertTrue(len(jcontent['geometries']) == 1) self.assertEqual(jcontent['geometries'][0]['type'], 'MultiPolygon') client.logout() self.assertTrue( client.login(username=self.test_user_admin1.username, password=self.test_user_admin1.username)) response = client.get(url, {}, format='json') self.assertEqual(response.status_code, 200) jcontent = json.loads(response.content) self.assertTrue(len(jcontent['geometries']) == 0)
def set_initconfig_value(sender, **kwargs): """ Set base editing data for initconfig """ Project = apps.get_app_config(kwargs['projectType']).get_model('project') project_layers = { pl.pk: pl for pl in Project.objects.get(pk=kwargs['project']).layer_set.all() } # get every layer editable for the project, il list == 0 return layers_to_edit = G3WEditingLayer.objects.filter( app_name=kwargs['projectType']) editable_layers_id = [] editable_layers_constraints = {} for el in layers_to_edit: # check for permissions if el.layer_id in project_layers and sender.request.user.has_perm( 'change_layer', project_layers[el.layer_id]): editable_layers_id.append(el.layer_id) # check if layers has constraints constraints = GeoConstraintRule.get_constraints_for_user( sender.request.user, project_layers[el.layer_id]) envelope = [] for constraint in constraints: geom = constraint.get_constraint_geometry() if geom[1] > 0: env = geom[0].envelope xmin, ymin = env[0][0] xmax, ymax = env[0][2] if 'xmin' in envelope and xmin > envelope['xmin']: xmin = envelope['xmin'] if 'ymin' in envelope and ymin > envelope['ymin']: ymin = envelope['ymin'] if 'xmax' in envelope and xmax < envelope['xmax']: xmax = envelope['xmax'] if 'ymax' in envelope and ymax < envelope['ymax']: ymax = envelope['ymax'] envelope = [xmin, ymin, xmax, ymax] if len(envelope) > 0: # FIXME: if qgs_layer_id is not unique it shouldn't be used as a key here: editable_layers_constraints.update({ project_layers[el.layer_id].qgs_layer_id: { 'geometry_api_url': reverse('geoconstraint-api-geometry', kwargs={'layer_id': el.layer_id}), 'bbox': envelope } }) if len(editable_layers_id) == 0: return None toret = { 'editing': { 'gid': "{}:{}".format(kwargs['projectType'], kwargs['project']), }, } if len(editable_layers_constraints) > 0: toret['editing']['constraints'] = editable_layers_constraints return toret