Skip to content

Commit 402d303

Browse files
authoredFeb 27, 2023
Merge pull request #51745 from rldhont/backport-51713-to-release-3_28
[Backport release-3_28][Server] Fix WFS GetFeature featureid && exp access control
2 parents 896bb9f + 6b1f86d commit 402d303

File tree

2 files changed

+525
-8
lines changed

2 files changed

+525
-8
lines changed
 

‎src/server/services/wfs/qgswfsgetfeature.cpp

+27-1
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,28 @@ namespace QgsWfs
340340

341341
// subset of attributes
342342
featureRequest.setSubsetOfAttributes( attrIndexes );
343+
// Access control expression could not be combined with feature ids filter
344+
// This request will store the access control expression if the feature request
345+
// filter type is feature ids
346+
QgsFeatureRequest accessControlRequest;
343347
#ifdef HAVE_SERVER_PYTHON_PLUGINS
344348
if ( accessControl )
345349
{
346-
accessControl->filterFeatures( vlayer, featureRequest );
350+
// Access control expression could not be combined with feature ids filter
351+
if ( featureRequest.filterType() == QgsFeatureRequest::FilterFid || featureRequest.filterType() == QgsFeatureRequest::FilterFids )
352+
{
353+
// expression context for access control filter
354+
QgsExpressionContext accessControlContext;
355+
accessControlContext << QgsExpressionContextUtils::globalScope()
356+
<< QgsExpressionContextUtils::projectScope( project )
357+
<< QgsExpressionContextUtils::layerScope( vlayer );
358+
accessControlRequest.setExpressionContext( accessControlContext );
359+
accessControl->filterFeatures( vlayer, accessControlRequest );
360+
}
361+
else
362+
{
363+
accessControl->filterFeatures( vlayer, featureRequest );
364+
}
347365

348366
QStringList attributes = QStringList();
349367
for ( int idx : std::as_const( attrIndexes ) )
@@ -428,6 +446,10 @@ namespace QgsWfs
428446
{
429447
while ( fit.nextFeature( feature ) && ( aRequest.maxFeatures == -1 || sentFeatures < aRequest.maxFeatures ) )
430448
{
449+
if ( accessControlRequest.filterType() != QgsFeatureRequest::FilterNone && !accessControlRequest.acceptFeature( feature ) )
450+
{
451+
continue;
452+
}
431453
if ( iteratedFeatures >= aRequest.startIndex )
432454
{
433455
++sentFeatures;
@@ -457,6 +479,10 @@ namespace QgsWfs
457479
};
458480
while ( fit.nextFeature( feature ) && ( aRequest.maxFeatures == -1 || sentFeatures < aRequest.maxFeatures ) )
459481
{
482+
if ( accessControlRequest.filterType() != QgsFeatureRequest::FilterNone && !accessControlRequest.acceptFeature( feature ) )
483+
{
484+
continue;
485+
}
460486
if ( iteratedFeatures == aRequest.startIndex )
461487
startGetFeature( request, response, project, aRequest.outputFormat, requestPrecision, requestCrs, &requestRect, typeNameList, serverIface->serverSettings() );
462488

‎tests/src/python/test_qgsserver_accesscontrol_wfs.py

+498-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
__date__ = '28/08/2015'
1212
__copyright__ = 'Copyright 2015, The QGIS Project'
1313

14+
import os
1415
import urllib.error
1516
import urllib.parse
1617
import urllib.request
@@ -45,11 +46,18 @@ def test_wfs_getcapabilities(self):
4546
self.assertTrue(
4647
str(response).find("<Name>Hello</Name>") != -1,
4748
"No Hello layer in WFS/GetCapabilities\n%s" % response)
49+
self.assertFalse(
50+
str(response).find("<Name>Hello_OnOff</Name>") != -1,
51+
"No Hello_OnOff layer in WFS/GetCapabilities\n%s" % response)
4852
self.assertFalse(
4953
str(response).find("<Name>Country</Name>") != -1,
5054
"Unexpected Country layer in WFS/GetCapabilities\n%s" % response)
5155

5256
def test_wfs_describefeaturetype_hello(self):
57+
"""Tests WFS DescribeFeatureType Request on 'Hello' with access control
58+
The restricted access to 'Hello' is the expression `$id = 1`
59+
The field 'color' has restricted access
60+
"""
5361
query_string = "&".join(["%s=%s" % i for i in list({
5462
"MAP": urllib.parse.quote(self.projectPath),
5563
"SERVICE": "WFS",
@@ -69,6 +77,9 @@ def test_wfs_describefeaturetype_hello(self):
6977
"No Hello layer in DescribeFeatureType\n%s" % response)
7078

7179
def test_wfs_describefeaturetype_country(self):
80+
"""Tests WFS DescribeFeatureType Request on 'Country' with access control
81+
The layer 'Country'has restricted access
82+
"""
7283
query_string = "&".join(["%s=%s" % i for i in list({
7384
"MAP": urllib.parse.quote(self.projectPath),
7485
"SERVICE": "WFS",
@@ -88,6 +99,49 @@ def test_wfs_describefeaturetype_country(self):
8899
"Unexpected Country layer in DescribeFeatureType\n%s" % response)
89100

90101
def test_wfs_getfeature_hello(self):
102+
"""Tests WFS GetFeature Request on 'Hello' with access control
103+
The restricted access to 'Hello' is the expression `$id = 1`
104+
The field 'color' has restricted access
105+
"""
106+
data = """<?xml version="1.0" encoding="UTF-8"?>
107+
<wfs:GetFeature {xml_ns}>
108+
<wfs:Query typeName="Hello" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
109+
</wfs:Query></wfs:GetFeature>""".format(xml_ns=XML_NS)
110+
111+
response, headers = self._post_fullaccess(data)
112+
# The feature with `pk = 1` is in the response with the field 'color'
113+
self.assertTrue(
114+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
115+
"No result in GetFeature\n%s" % response)
116+
self.assertTrue(
117+
str(response).find("<qgs:color>red</qgs:color>") != -1, # spellok
118+
"No color in result of GetFeature\n%s" % response)
119+
# The feature with `pk = 2` is in the response (no filter, no access control)
120+
self.assertTrue(
121+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
122+
"Unexpected result in GetFeature\n%s" % response)
123+
124+
response, headers = self._post_restricted(data)
125+
# The feature with `pk = 1` is in the response without the field 'color'
126+
self.assertTrue(
127+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
128+
"No result in GetFeature\n%s" % response)
129+
self.assertFalse(
130+
str(response).find("<qgs:color>red</qgs:color>") != -1, # spellok
131+
"Unexpected color in result of GetFeature\n%s" % response)
132+
self.assertFalse(
133+
str(response).find("<qgs:color>NULL</qgs:color>") != -1, # spellok
134+
"Unexpected color NULL in result of GetFeature\n%s" % response)
135+
# The feature with `pk = 2` is not in the response: access control
136+
self.assertFalse(
137+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
138+
"Unexpected result in GetFeature\n%s" % response)
139+
140+
def test_wfs_getfeature_ogc_filter_hello(self):
141+
"""Tests WFS GetFeature Request on 'Hello' with OGC Filter `pkuid = 1` and access control
142+
The restricted access to 'Hello' is the expression `$id = 1`
143+
The field 'color' has restricted access
144+
"""
91145
data = """<?xml version="1.0" encoding="UTF-8"?>
92146
<wfs:GetFeature {xml_ns}>
93147
<wfs:Query typeName="Hello" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
@@ -97,14 +151,20 @@ def test_wfs_getfeature_hello(self):
97151
</ogc:PropertyIsEqualTo></ogc:Filter></wfs:Query></wfs:GetFeature>""".format(xml_ns=XML_NS)
98152

99153
response, headers = self._post_fullaccess(data)
154+
# The feature with `pk = 1` is in the response with the field 'color'
100155
self.assertTrue(
101156
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
102157
"No result in GetFeature\n%s" % response)
103158
self.assertTrue(
104159
str(response).find("<qgs:color>red</qgs:color>") != -1, # spellok
105160
"No color in result of GetFeature\n%s" % response)
161+
# The feature with `pk = 2` is not in the response
162+
self.assertFalse(
163+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
164+
"Unexpected result in GetFeature\n%s" % response)
106165

107166
response, headers = self._post_restricted(data)
167+
# The feature with `pk = 1` is in the response without the field 'color'
108168
self.assertTrue(
109169
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
110170
"No result in GetFeature\n%s" % response)
@@ -114,8 +174,15 @@ def test_wfs_getfeature_hello(self):
114174
self.assertFalse(
115175
str(response).find("<qgs:color>NULL</qgs:color>") != -1, # spellok
116176
"Unexpected color NULL in result of GetFeature\n%s" % response)
177+
# The feature with `pk = 2` is still not in the response
178+
self.assertFalse(
179+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
180+
"Unexpected result in GetFeature\n%s" % response)
117181

118-
def test_wfs_getfeature_hello2(self):
182+
def test_wfs_getfeature_ogc_filter_hello2(self):
183+
"""Tests WFS GetFeature Request on 'Hello' with OGC Filter `pkuid = 2` and access control
184+
The restricted access to 'Hello' is the expression `$id = 1`
185+
"""
119186
data = """<?xml version="1.0" encoding="UTF-8"?>
120187
<wfs:GetFeature {xml_ns}>
121188
<wfs:Query typeName="Hello" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
@@ -125,22 +192,66 @@ def test_wfs_getfeature_hello2(self):
125192
</ogc:PropertyIsEqualTo></ogc:Filter></wfs:Query></wfs:GetFeature>""".format(xml_ns=XML_NS)
126193

127194
response, headers = self._post_fullaccess(data)
195+
# The feature with `pk = 2` is in the response
128196
self.assertTrue(
129197
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
130198
"No result in GetFeature\n%s" % response)
199+
# The feature with `pk = 1` is not in the response
131200
self.assertFalse(
132201
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
133202
"Unexpected result in GetFeature\n%s" % response)
134203

135204
response, headers = self._post_restricted(data)
205+
# The feature with `pk = 2` is not in the response
136206
self.assertFalse(
137207
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
138208
"Unexpected result in GetFeature\n%s" % response)
209+
# The feature with `pk = 1` is still not in the response
139210
self.assertFalse(
140211
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
141212
"Unexpected result in GetFeature\n%s" % response)
142213

143-
def test_wfs_getfeature_filter(self):
214+
def test_wfs_getfeature_hello_filter(self):
215+
"""Tests WFS GetFeature Request on 'Hello_Filter' with access control
216+
The restricted access to 'Hello_Filter is the expression `pkuid = 6 or pkuid = 7`
217+
"""
218+
data = """<?xml version="1.0" encoding="UTF-8"?>
219+
<wfs:GetFeature {xml_ns}>
220+
<wfs:Query typeName="Hello_Filter" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
221+
</wfs:Query></wfs:GetFeature>""".format(xml_ns=XML_NS)
222+
223+
response, headers = self._post_fullaccess(data)
224+
# The feature with `pk = 1` is in the response (no filter, no access control)
225+
self.assertTrue(
226+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
227+
"No result in GetFeature\n%s" % response)
228+
# The feature with `pk = 6` is in the response (no filter, no access control)
229+
self.assertTrue(
230+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
231+
"Unexpected result in GetFeature\n%s" % response)
232+
# The feature with `pk = 7` is in the response (no filter, no access control)
233+
self.assertTrue(
234+
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
235+
"Unexpected result in GetFeature\n%s" % response)
236+
237+
response, headers = self._post_restricted(data)
238+
# The feature with `pk = 1` is not in the response: access control
239+
self.assertFalse(
240+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
241+
"Unexpected result in GetFeature\n%s" % response)
242+
# The feature with `pk = 6` is in the response: access control
243+
self.assertTrue(
244+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
245+
"Unexpected result in GetFeature\n%s" % response)
246+
# The feature with `pk = 7` is in the response: access control
247+
self.assertTrue(
248+
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
249+
"Unexpected result in GetFeature\n%s" % response)
250+
251+
def test_wfs_getfeature_ogc_filter_hello_filter(self):
252+
"""Tests WFS GetFeature Request on 'Hello_Filter' with OGC Filter `pkuid = 1` and access control
253+
The restricted access to 'Hello_Filter is the expression `pkuid = 6 or pkuid = 7`
254+
"""
144255
data = """<?xml version="1.0" encoding="UTF-8"?>
145256
<wfs:GetFeature {xml_ns}>
146257
<wfs:Query typeName="Hello_Filter" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
@@ -150,22 +261,29 @@ def test_wfs_getfeature_filter(self):
150261
</ogc:PropertyIsEqualTo></ogc:Filter></wfs:Query></wfs:GetFeature>""".format(xml_ns=XML_NS)
151262

152263
response, headers = self._post_fullaccess(data)
264+
# The feature with `pk = 1` is in the response
153265
self.assertTrue(
154266
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
155267
"No result in GetFeature\n%s" % response)
268+
# The feature with `pk = 6` is not in the response
156269
self.assertFalse(
157270
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
158271
"Unexpected result in GetFeature\n%s" % response)
159272

160273
response, headers = self._post_restricted(data)
274+
# The feature with `pk = 1` is not in the response
161275
self.assertFalse(
162276
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
163277
"Unexpected result in GetFeature\n%s" % response)
278+
# The feature with `pk = 6` is still not in the response
164279
self.assertFalse(
165280
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
166281
"Unexpected result in GetFeature\n%s" % response)
167282

168-
def test_wfs_getfeature_filter2(self):
283+
def test_wfs_getfeature_ogc_filter_hello_filter2(self):
284+
"""Tests WFS GetFeature Request on 'Hello_Filter' with OGC Filter `pkuid = 6` and access control
285+
The restricted access to 'Hello_Filter is the expression `pkuid = 6 or pkuid = 7`
286+
"""
169287
data = """<?xml version="1.0" encoding="UTF-8"?>
170288
<wfs:GetFeature {xml_ns}>
171289
<wfs:Query typeName="Hello_Filter" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
@@ -175,22 +293,66 @@ def test_wfs_getfeature_filter2(self):
175293
</ogc:PropertyIsEqualTo></ogc:Filter></wfs:Query></wfs:GetFeature>""".format(xml_ns=XML_NS)
176294

177295
response, headers = self._post_fullaccess(data)
296+
# The feature with `pk = 6` is in the response
178297
self.assertTrue(
179298
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
180299
"No result in GetFeature\n%s" % response)
300+
# The feature with `pk = 7` is not in the response
181301
self.assertFalse(
182302
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
183303
"Unexpected result in GetFeature\n%s" % response)
184304

185305
response, headers = self._post_restricted(data)
306+
# The feature with `pk = 6` is still in the response
186307
self.assertTrue(
187308
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
188309
"No result in GetFeature\n%s" % response)
310+
# The feature with `pk = 7` is still not in the response
189311
self.assertFalse(
190312
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
191313
"Unexpected result in GetFeature\n%s" % response)
192314

193-
def test_wfs_getfeature_country(self):
315+
def test_wfs_getfeature_hello_onoff(self):
316+
"""Tests WFS GetFeature Request on 'Hello_OnOff' with access control
317+
The restricted access to 'Hello_OnOff is cannot be read
318+
"""
319+
data = """<?xml version="1.0" encoding="UTF-8"?>
320+
<wfs:GetFeature {xml_ns}>
321+
<wfs:Query typeName="Hello_OnOff" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
322+
</wfs:Query></wfs:GetFeature>""".format(xml_ns=XML_NS)
323+
324+
response, headers = self._post_fullaccess(data)
325+
# Some qgs feature Hello_OnOff element
326+
self.assertTrue(
327+
str(response).find("<qgs:Hello_OnOff ") != -1,
328+
"No result in GetFeature\n%s" % response)
329+
# The feature with `pk = 1` is in the response
330+
self.assertTrue(
331+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
332+
"No result in GetFeature\n%s" % response)
333+
# The feature with `pk = 6` is in the response
334+
self.assertTrue(
335+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
336+
"No result in GetFeature\n%s" % response)
337+
338+
response, headers = self._post_restricted(data)
339+
# The feature with `pk = 1` is not in the response
340+
self.assertFalse(
341+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
342+
"Unexpected result in GetFeature\n%s" % response)
343+
# The feature with `pk = 6` is not in the response
344+
self.assertFalse(
345+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
346+
"Unexpected result in GetFeature\n%s" % response)
347+
# No qgs feature Hello_OnOff element
348+
self.assertFalse(
349+
str(response).find("<qgs:Hello_OnOff ") != -1,
350+
"Unexpected result in GetFeature\n%s" % response)
351+
352+
def test_wfs_getfeature_ogc_filter_hello_onoff(self):
353+
"""Tests WFS GetFeature Request on 'Hello_OnOff' with OGC Filter `pkuid = 1` access control
354+
The restricted access to 'Hello_OnOff is cannot be read
355+
"""
194356
data = """<?xml version="1.0" encoding="UTF-8"?>
195357
<wfs:GetFeature {xml_ns}>
196358
<wfs:Query typeName="Hello_OnOff" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
@@ -200,14 +362,32 @@ def test_wfs_getfeature_country(self):
200362
</ogc:PropertyIsEqualTo></ogc:Filter></wfs:Query></wfs:GetFeature>""".format(xml_ns=XML_NS)
201363

202364
response, headers = self._post_fullaccess(data)
365+
# Some qgs feature Hello_OnOff element
366+
self.assertTrue(
367+
str(response).find("<qgs:Hello_OnOff ") != -1,
368+
"No result in GetFeature\n%s" % response)
369+
# The feature with `pk = 1` is in the response
203370
self.assertTrue(
204371
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
205372
"No result in GetFeature\n%s" % response)
373+
# The feature with `pk = 6` is not in the response
374+
self.assertFalse(
375+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
376+
"Unexpected result in GetFeature\n%s" % response)
206377

207378
response, headers = self._post_restricted(data)
379+
# The feature with `pk = 1` is not in the response
208380
self.assertFalse(
209381
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
210-
"Unexpected result in GetFeature\n%s" % response) # spellok
382+
"Unexpected result in GetFeature\n%s" % response)
383+
# The feature with `pk = 6` is still not in the response
384+
self.assertFalse(
385+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
386+
"Unexpected result in GetFeature\n%s" % response)
387+
# No qgs feature Hello_OnOff element
388+
self.assertFalse(
389+
str(response).find("<qgs:Hello_OnOff ") != -1,
390+
"Unexpected result in GetFeature\n%s" % response)
211391

212392
# # Subset String # #
213393

@@ -340,7 +520,13 @@ def test_wfs_getfeature_project_subsetstring3(self):
340520
str(response).find("<qgs:pk>") != -1,
341521
"Project based layer subsetString not respected in GetFeature with restricted access\n%s" % response)
342522

523+
# # KVP request instead of XML request # #
524+
343525
def test_wfs_getfeature_exp_filter_hello(self):
526+
"""Tests WFS GetFeature Request on 'Hello' with Expression Filter `pkuid = 1` and access control
527+
The restricted access to 'Hello' is the expression `$id = 1`
528+
The field 'color' has restricted access
529+
"""
344530
query_string = "&".join(["%s=%s" % i for i in list({
345531
"MAP": urllib.parse.quote(self.projectPath),
346532
"SERVICE": "WFS",
@@ -351,14 +537,20 @@ def test_wfs_getfeature_exp_filter_hello(self):
351537
}.items())])
352538

353539
response, headers = self._get_fullaccess(query_string)
540+
# The feature with `pk = 1` is in the response with the field 'color'
354541
self.assertTrue(
355542
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
356543
"No result in GetFeature\n%s" % response)
357544
self.assertTrue(
358545
str(response).find("<qgs:color>red</qgs:color>") != -1, # spellok
359546
"No color in result of GetFeature\n%s" % response)
547+
# The feature with `pk = 2` is not in the response
548+
self.assertFalse(
549+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
550+
"Unexpected color in result of GetFeature\n%s" % response)
360551

361552
response, headers = self._get_restricted(query_string)
553+
# The feature with `pk = 1` is in the response without the field 'color'
362554
self.assertTrue(
363555
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
364556
"No result in GetFeature\n%s" % response)
@@ -368,8 +560,15 @@ def test_wfs_getfeature_exp_filter_hello(self):
368560
self.assertFalse(
369561
str(response).find("<qgs:color>NULL</qgs:color>") != -1, # spellok
370562
"Unexpected color NULL in result of GetFeature\n%s" % response)
563+
# The feature with `pk = 2` is still not in the response
564+
self.assertFalse(
565+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
566+
"Unexpected color in result of GetFeature\n%s" % response)
371567

372568
def test_wfs_getfeature_exp_filter_hello2(self):
569+
"""Tests WFS GetFeature Request on 'Hello' with Expression Filter `pkuid = 2` and access control
570+
The restricted access to 'Hello' is the expression `$id = 1`
571+
"""
373572
query_string = "&".join(["%s=%s" % i for i in list({
374573
"MAP": urllib.parse.quote(self.projectPath),
375574
"SERVICE": "WFS",
@@ -380,22 +579,36 @@ def test_wfs_getfeature_exp_filter_hello2(self):
380579
}.items())])
381580

382581
response, headers = self._get_fullaccess(query_string)
582+
# The feature with `pk = 2` is in the response
383583
self.assertTrue(
384584
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
385585
"No result in GetFeature\n%s" % response)
586+
# The feature with `pk = 1` is not in the response
386587
self.assertFalse(
387588
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
388589
"Unexpected result in GetFeature\n%s" % response)
389590

390591
response, headers = self._get_restricted(query_string)
592+
# The feature with `pk = 2` is not in the response
391593
self.assertFalse(
392594
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
393595
"Unexpected result in GetFeature\n%s" % response)
394596
self.assertFalse(
395597
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
396598
"Unexpected result in GetFeature\n%s" % response)
599+
# The feature with `pk = 1` is still not in the response
600+
self.assertFalse(
601+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
602+
"Unexpected result in GetFeature\n%s" % response)
603+
# No qgs feature Hello element
604+
self.assertFalse(
605+
str(response).find("<qgs:Hello ") != -1,
606+
"Unexpected result in GetFeature\n%s" % response)
397607

398608
def test_wfs_getfeature_exp_filter_hello_filter(self):
609+
"""Tests WFS GetFeature Request on 'Hello_Filter' with Expression Filter `pkuid = 1` and access control
610+
The restricted access to 'Hello_Filter is the expression `pkuid = 6 or pkuid = 7`
611+
"""
399612
query_string = "&".join(["%s=%s" % i for i in list({
400613
"MAP": urllib.parse.quote(self.projectPath),
401614
"SERVICE": "WFS",
@@ -406,22 +619,47 @@ def test_wfs_getfeature_exp_filter_hello_filter(self):
406619
}.items())])
407620

408621
response, headers = self._get_fullaccess(query_string)
622+
# The feature with `pk = 1` is in the response
409623
self.assertTrue(
410624
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
411625
"No result in GetFeature\n%s" % response)
412626
self.assertFalse(
413627
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
414628
"Unexpected result in GetFeature\n%s" % response)
629+
# The feature with `pk = 6` is not in the response
630+
self.assertFalse(
631+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
632+
"Unexpected result in GetFeature\n%s" % response)
633+
# The feature with `pk = 7` is not in the response
634+
self.assertFalse(
635+
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
636+
"Unexpected result in GetFeature\n%s" % response)
415637

416638
response, headers = self._get_restricted(query_string)
639+
# The feature with `pk = 1` is not in the response
417640
self.assertFalse(
418641
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
419642
"Unexpected result in GetFeature\n%s" % response)
420643
self.assertFalse(
421644
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
422645
"Unexpected result in GetFeature\n%s" % response)
646+
# The feature with `pk = 6` is still not in the response
647+
self.assertFalse(
648+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
649+
"Unexpected result in GetFeature\n%s" % response)
650+
# The feature with `pk = 7` is still not in the response
651+
self.assertFalse(
652+
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
653+
"Unexpected result in GetFeature\n%s" % response)
654+
# No qgs feature Hello_Filter element
655+
self.assertFalse(
656+
str(response).find("<qgs:Hello_Filter ") != -1,
657+
"Unexpected result in GetFeature\n%s" % response)
423658

424659
def test_wfs_getfeature_exp_filter_hello_filter2(self):
660+
"""Tests WFS GetFeature Request on 'Hello_Filter' with Expression Filter `pkuid = 6` and access control
661+
The restricted access to 'Hello_Filter is the expression `pkuid = 6 or pkuid = 7`
662+
"""
425663
query_string = "&".join(["%s=%s" % i for i in list({
426664
"MAP": urllib.parse.quote(self.projectPath),
427665
"SERVICE": "WFS",
@@ -432,9 +670,15 @@ def test_wfs_getfeature_exp_filter_hello_filter2(self):
432670
}.items())])
433671

434672
response, headers = self._get_fullaccess(query_string)
673+
# The feature with `pk = 6` is in the response
435674
self.assertTrue(
436675
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
437676
"No result in GetFeature\n%s" % response)
677+
# The feature with `pk = 1` is not in the response
678+
self.assertFalse(
679+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
680+
"Unexpected result in GetFeature\n%s" % response)
681+
# The feature with `pk = 7` is not in the response
438682
self.assertFalse(
439683
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
440684
"Unexpected result in GetFeature\n%s" % response)
@@ -443,11 +687,20 @@ def test_wfs_getfeature_exp_filter_hello_filter2(self):
443687
self.assertTrue(
444688
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
445689
"No result in GetFeature\n%s" % response)
690+
# The feature with `pk = 1` is still not in the response
691+
self.assertFalse(
692+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
693+
"Unexpected result in GetFeature\n%s" % response)
694+
# The feature with `pk = 7` is not in the response
446695
self.assertFalse(
447696
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
448697
"Unexpected result in GetFeature\n%s" % response)
449698

450-
def test_wfs_getfeature_featureid_hello_1(self):
699+
def test_wfs_getfeature_featureid_hello(self):
700+
"""Tests WFS GetFeature Request on 'Hello' with FeatureId `Hello.1` and access control
701+
The restricted access to 'Hello' is the expression `$id = 1`
702+
The field 'color' has restricted access
703+
"""
451704
query_string = "&".join(["%s=%s" % i for i in list({
452705
"MAP": urllib.parse.quote(self.projectPath),
453706
"SERVICE": "WFS",
@@ -458,14 +711,20 @@ def test_wfs_getfeature_featureid_hello_1(self):
458711
}.items())])
459712

460713
response, headers = self._get_fullaccess(query_string)
714+
# The feature with `pk = 1` is in the response with the field 'color'
461715
self.assertTrue(
462716
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
463717
"No result in GetFeature\n%s" % response)
464718
self.assertTrue(
465719
str(response).find("<qgs:color>red</qgs:color>") != -1, # spellok
466720
"No color in result of GetFeature\n%s" % response)
721+
# The feature with `pk = 2` is not in the response
722+
self.assertFalse(
723+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
724+
"Unexpected result in GetFeature\n%s" % response)
467725

468726
response, headers = self._get_restricted(query_string)
727+
# The feature with `pk = 1` is in the response without the field 'color'
469728
self.assertTrue(
470729
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
471730
"No result in GetFeature\n%s" % response)
@@ -475,8 +734,16 @@ def test_wfs_getfeature_featureid_hello_1(self):
475734
self.assertFalse(
476735
str(response).find("<qgs:color>NULL</qgs:color>") != -1, # spellok
477736
"Unexpected color NULL in result of GetFeature\n%s" % response)
737+
# The feature with `pk = 2` is still not in the response
738+
self.assertFalse(
739+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
740+
"Unexpected result in GetFeature\n%s" % response)
478741

479-
def test_wfs_getfeature_featureid_hello_2(self):
742+
def test_wfs_getfeature_featureid_hello2(self):
743+
"""Tests WFS GetFeature Request on 'Hello' with FeatureId `Hello.2` and access control
744+
The restricted access to 'Hello' is the expression `$id = 1`
745+
The field 'color' has restricted access
746+
"""
480747
query_string = "&".join(["%s=%s" % i for i in list({
481748
"MAP": urllib.parse.quote(self.projectPath),
482749
"SERVICE": "WFS",
@@ -487,22 +754,36 @@ def test_wfs_getfeature_featureid_hello_2(self):
487754
}.items())])
488755

489756
response, headers = self._get_fullaccess(query_string)
757+
# The feature with `pk = 2` is in the response
490758
self.assertTrue(
491759
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
492760
"No result in GetFeature\n%s" % response)
761+
# The feature with `pk = 1` is not in the response
493762
self.assertFalse(
494763
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
495764
"Unexpected result in GetFeature\n%s" % response)
496765

497766
response, headers = self._get_restricted(query_string)
767+
# The feature with `pk = 2` is not in the response
498768
self.assertFalse(
499769
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
500770
"Unexpected result in GetFeature\n%s" % response)
501771
self.assertFalse(
502772
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
503773
"Unexpected result in GetFeature\n%s" % response)
774+
# The feature with `pk = 1` is still not in the response
775+
self.assertFalse(
776+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
777+
"Unexpected result in GetFeature\n%s" % response)
778+
# No qgs feature Hello element
779+
self.assertFalse(
780+
str(response).find("<qgs:Hello ") != -1,
781+
"Unexpected result in GetFeature\n%s" % response)
504782

505783
def test_wfs_getfeature_featureid_hello_filter(self):
784+
"""Tests WFS GetFeature Request on 'Hello_Filter' with FeatureId `Hello_Filter.1` and access control
785+
The restricted access to 'Hello_Filter is the expression `pkuid = 6 or pkuid = 7`
786+
"""
506787
query_string = "&".join(["%s=%s" % i for i in list({
507788
"MAP": urllib.parse.quote(self.projectPath),
508789
"SERVICE": "WFS",
@@ -513,22 +794,47 @@ def test_wfs_getfeature_featureid_hello_filter(self):
513794
}.items())])
514795

515796
response, headers = self._get_fullaccess(query_string)
797+
# The feature with `pk = 1` is in the response
516798
self.assertTrue(
517799
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
518800
"No result in GetFeature\n%s" % response)
519801
self.assertFalse(
520802
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
521803
"Unexpected result in GetFeature\n%s" % response)
804+
# The feature with `pk = 6` is not in the response
805+
self.assertFalse(
806+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
807+
"Unexpected result in GetFeature\n%s" % response)
808+
# The feature with `pk = 7` is not in the response
809+
self.assertFalse(
810+
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
811+
"Unexpected result in GetFeature\n%s" % response)
522812

523813
response, headers = self._get_restricted(query_string)
814+
# The feature with `pk = 1` is not in the response
524815
self.assertFalse(
525816
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
526817
"Unexpected result in GetFeature\n%s" % response)
527818
self.assertFalse(
528819
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
529820
"Unexpected result in GetFeature\n%s" % response)
821+
# The feature with `pk = 6` is still not in the response
822+
self.assertFalse(
823+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
824+
"Unexpected result in GetFeature\n%s" % response)
825+
# The feature with `pk = 7` is still not in the response
826+
self.assertFalse(
827+
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
828+
"Unexpected result in GetFeature\n%s" % response)
829+
# No qgs feature Hello_Filter element
830+
self.assertFalse(
831+
str(response).find("<qgs:Hello_Filter ") != -1,
832+
"Unexpected result in GetFeature\n%s" % response)
530833

531834
def test_wfs_getfeature_featureid_hello_filter2(self):
835+
"""Tests WFS GetFeature Request on 'Hello_Filter' with FeatureId `Hello_Filter.6` and access control
836+
The restricted access to 'Hello_Filter is the expression `pkuid = 6 or pkuid = 7`
837+
"""
532838
query_string = "&".join(["%s=%s" % i for i in list({
533839
"MAP": urllib.parse.quote(self.projectPath),
534840
"SERVICE": "WFS",
@@ -539,17 +845,202 @@ def test_wfs_getfeature_featureid_hello_filter2(self):
539845
}.items())])
540846

541847
response, headers = self._get_fullaccess(query_string)
848+
# The feature with `pk = 6` is in the response
849+
self.assertTrue(
850+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
851+
"No result in GetFeature\n%s" % response)
852+
# The feature with `pk = 1` is not in the response
853+
self.assertFalse(
854+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
855+
"Unexpected result in GetFeature\n%s" % response)
856+
# The feature with `pk = 7` is not in the response
857+
self.assertFalse(
858+
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
859+
"Unexpected result in GetFeature\n%s" % response)
860+
861+
response, headers = self._get_restricted(query_string)
862+
# The feature with `pk = 6` is in the response
863+
self.assertTrue(
864+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
865+
"No result in GetFeature\n%s" % response)
866+
# The feature with `pk = 1` is not in the response
867+
self.assertFalse(
868+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
869+
"Unexpected result in GetFeature\n%s" % response)
870+
# The feature with `pk = 7` is not in the response
871+
self.assertFalse(
872+
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
873+
"Unexpected result in GetFeature\n%s" % response)
874+
875+
# # ESRI Shapefile datasource # #
876+
877+
def test_wfs_getfeature_shp_featureid_hello(self):
878+
"""Tests WFS GetFeature Request on 'Hello' with FeatureId `Hello.1` and access control
879+
The datasource is an ESRI Shapefile
880+
The restricted access to 'Hello' is the expression `$id = 1`
881+
The field 'color' has restricted access
882+
"""
883+
query_string = "&".join(["%s=%s" % i for i in list({
884+
"MAP": urllib.parse.quote(os.path.join(self.tmp_path, 'project_shp.qgs')),
885+
"SERVICE": "WFS",
886+
"VERSION": "1.0.0",
887+
"REQUEST": "GetFeature",
888+
"TYPENAME": "Hello",
889+
"FEATUREID": "Hello.1"
890+
}.items())])
891+
892+
response, headers = self._get_fullaccess(query_string)
893+
# The feature with `pk = 2` is in the response with the field 'color'
894+
self.assertTrue(
895+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
896+
"No result in GetFeature\n%s" % response)
897+
self.assertTrue(
898+
str(response).find("<qgs:color>blue</qgs:color>") != -1, # spellok
899+
"No color in result of GetFeature\n%s" % response)
900+
# The feature with `pk = 1` is not in the response
901+
self.assertFalse(
902+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
903+
"Unexpected result in GetFeature\n%s" % response)
904+
905+
response, headers = self._get_restricted(query_string)
906+
# The feature with `pk = 2` is in the response without the field 'color'
907+
self.assertTrue(
908+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
909+
"No result in GetFeature\n%s" % response)
910+
self.assertFalse(
911+
str(response).find("<qgs:color>blue</qgs:color>") != -1, # spellok
912+
"Unexpected color in result of GetFeature\n%s" % response)
913+
self.assertFalse(
914+
str(response).find("<qgs:color>NULL</qgs:color>") != -1, # spellok
915+
"Unexpected color NULL in result of GetFeature\n%s" % response)
916+
# The feature with `pk = 1` is still not in the response
917+
self.assertFalse(
918+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
919+
"Unexpected result in GetFeature\n%s" % response)
920+
921+
def test_wfs_getfeature_shp_featureid_hello2(self):
922+
"""Tests WFS GetFeature Request on 'Hello' with FeatureId `Hello.0` and access control
923+
The datasource is an ESRI Shapefile
924+
The restricted access to 'Hello' is the expression `$id = 1`
925+
The field 'color' has restricted access
926+
"""
927+
query_string = "&".join(["%s=%s" % i for i in list({
928+
"MAP": urllib.parse.quote(os.path.join(self.tmp_path, 'project_shp.qgs')),
929+
"SERVICE": "WFS",
930+
"VERSION": "1.0.0",
931+
"REQUEST": "GetFeature",
932+
"TYPENAME": "Hello",
933+
"FEATUREID": "Hello.0"
934+
}.items())])
935+
936+
response, headers = self._get_fullaccess(query_string)
937+
# The feature with `pk = 1` is in the response
938+
self.assertTrue(
939+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
940+
"No result in GetFeature\n%s" % response)
941+
# The feature with `pk = 2` is not in the response
942+
self.assertFalse(
943+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
944+
"Unexpected result in GetFeature\n%s" % response)
945+
946+
response, headers = self._get_restricted(query_string)
947+
# The feature with `pk = 1` is not in the response
948+
self.assertFalse(
949+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
950+
"Unexpected result in GetFeature\n%s" % response)
951+
# The feature with `pk = 2` is still not in the response
952+
self.assertFalse(
953+
str(response).find("<qgs:pk>2</qgs:pk>") != -1,
954+
"Unexpected result in GetFeature\n%s" % response)
955+
# No qgs feature Hello_Filter element
956+
self.assertFalse(
957+
str(response).find("<qgs:Hello ") != -1,
958+
"Unexpected result in GetFeature\n%s" % response)
959+
960+
def test_wfs_getfeature_shp_featureid_hello_filter(self):
961+
"""Tests WFS GetFeature Request on 'Hello_Filter' with FeatureId `Hello_Filter.1` and access control
962+
The datasource is an ESRI Shapefile
963+
The restricted access to 'Hello_Filter is the expression `pkuid = 6 or pkuid = 7`
964+
"""
965+
query_string = "&".join(["%s=%s" % i for i in list({
966+
"MAP": urllib.parse.quote(os.path.join(self.tmp_path, 'project_shp.qgs')),
967+
"SERVICE": "WFS",
968+
"VERSION": "1.0.0",
969+
"REQUEST": "GetFeature",
970+
"TYPENAME": "Hello_Filter",
971+
"FEATUREID": "Hello_Filter.0"
972+
}.items())])
973+
974+
response, headers = self._get_fullaccess(query_string)
975+
# The feature with `pk = 1` is in the response
976+
self.assertTrue(
977+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
978+
"No result in GetFeature\n%s" % response)
979+
# The feature with `pk = 6` is not in the response
980+
self.assertFalse(
981+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
982+
"Unexpected result in GetFeature\n%s" % response)
983+
# The feature with `pk = 7` is not in the response
984+
self.assertFalse(
985+
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
986+
"Unexpected result in GetFeature\n%s" % response)
987+
988+
response, headers = self._get_restricted(query_string)
989+
# The feature with `pk = 1` is not in the response
990+
self.assertFalse(
991+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
992+
"Unexpected result in GetFeature\n%s" % response)
993+
# The feature with `pk = 6` is still not in the response
994+
self.assertFalse(
995+
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
996+
"Unexpected result in GetFeature\n%s" % response)
997+
# The feature with `pk = 7` is still not in the response
998+
self.assertFalse(
999+
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
1000+
"Unexpected result in GetFeature\n%s" % response)
1001+
# No qgs feature Hello_Filter element
1002+
self.assertFalse(
1003+
str(response).find("<qgs:Hello_Filter ") != -1,
1004+
"Unexpected result in GetFeature\n%s" % response)
1005+
1006+
def test_wfs_getfeature_shp_featureid_hello_filter2(self):
1007+
"""Tests WFS GetFeature Request on 'Hello_Filter' with FeatureId `Hello_Filter.5` and access control
1008+
The datasource is an ESRI Shapefile
1009+
The restricted access to 'Hello_Filter is the expression `pkuid = 6 or pkuid = 7`
1010+
"""
1011+
query_string = "&".join(["%s=%s" % i for i in list({
1012+
"MAP": urllib.parse.quote(os.path.join(self.tmp_path, 'project_shp.qgs')),
1013+
"SERVICE": "WFS",
1014+
"VERSION": "1.0.0",
1015+
"REQUEST": "GetFeature",
1016+
"TYPENAME": "Hello_Filter",
1017+
"FEATUREID": "Hello_Filter.5"
1018+
}.items())])
1019+
1020+
response, headers = self._get_fullaccess(query_string)
1021+
# The feature with `pk = 6` is in the response
5421022
self.assertTrue(
5431023
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
5441024
"No result in GetFeature\n%s" % response)
1025+
# The feature with `pk = 1` is not in the response
1026+
self.assertFalse(
1027+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
1028+
"Unexpected result in GetFeature\n%s" % response)
1029+
# The feature with `pk = 7` is not in the response
5451030
self.assertFalse(
5461031
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
5471032
"Unexpected result in GetFeature\n%s" % response)
5481033

5491034
response, headers = self._get_restricted(query_string)
1035+
# The feature with `pk = 6` is in the response
5501036
self.assertTrue(
5511037
str(response).find("<qgs:pk>6</qgs:pk>") != -1,
5521038
"No result in GetFeature\n%s" % response)
1039+
# The feature with `pk = 1` is not in the response
1040+
self.assertFalse(
1041+
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
1042+
"Unexpected result in GetFeature\n%s" % response)
1043+
# The feature with `pk = 7` is not in the response
5531044
self.assertFalse(
5541045
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
5551046
"Unexpected result in GetFeature\n%s" % response)

0 commit comments

Comments
 (0)
Please sign in to comment.