def remove_project_from_cache(sender, **kwargs): from qdjango.apps import QGS_SERVER, QgsConfigCache from qdjango.utils.data import QgisProject if not isinstance(sender, QgisProject): return path = sender.instance.qgis_file.path QgsConfigCache.instance().removeEntry(path) QGS_SERVER.serverInterface().capabilitiesCache( ).removeCapabilitiesDocument(path) logging.getLogger('g3wadmin.debug').warning( 'settings.DEBUG is True: QGIS Server cached project invalidated: %s' % path)
def baseDoRequest(self, q): request = self.request # Uppercase REQUEST if 'REQUEST' in [k.upper() for k in q.keys()]: if request.method == 'GET': ows_request = q['REQUEST'].upper() else: if request.content_type == 'application/x-www-form-urlencoded': ows_request = request.POST['REQUEST'].upper() else: ows_request = request.POST['REQUEST'][0].upper() q['REQUEST'] = ows_request # FIXME: proxy or redirect in case of WMS/WFS/XYZ cascading? qgs_project = get_qgs_project(self.project.qgis_file.path) if qgs_project is None: raise Http404('The requested QGIS project could not be loaded!') data = None if request.method == 'GET': method = QgsBufferServerRequest.GetMethod elif request.method == 'POST': method = QgsBufferServerRequest.PostMethod data = request.body elif request.method == 'PUT': method = QgsBufferServerRequest.PutMethod data = request.body elif request.method == 'PATCH': method = QgsBufferServerRequest.PatchMethod data = request.body elif request.method == 'HEAD': method = QgsBufferServerRequest.HeadMethod elif request.method == 'DELETE': method = QgsBufferServerRequest.DeleteMethod else: logger.warning("Request method not supported: %s, assuming GET" % request.method) method = QgsBufferServerRequest.GetMethod headers = {} for header_key in request.headers.keys(): headers[header_key] = request.headers.get(header_key) uri = request.build_absolute_uri(request.path) + '?' + q.urlencode() logger.debug('Calling QGIS Server: %s' % uri) qgs_request = QgsBufferServerRequest(uri, method, headers, data) # Attach user and project to the server object to make them accessible by the # server access control plugins (constraints etc.) QGS_SERVER.user = request.user QGS_SERVER.project = self.project qgs_response = QgsBufferServerResponse() try: QGS_SERVER.handleRequest(qgs_request, qgs_response, qgs_project) except Exception as ex: return HttpResponseServerError( reason="Error handling server request: %s" % ex) response = HttpResponse(bytes(qgs_response.body())) response.status_code = qgs_response.statusCode() for key, value in qgs_response.headers().items(): response[key] = value return response
"""A filter that excludes columns from layers""" def __init__(self, server_iface): super().__init__(server_iface) def authorizedLayerAttributes(self, layer, attributes): """Retrieve and sets column acl""" try: qdjango_layer = Layer.objects.get(project=QGS_SERVER.project, qgs_layer_id=layer.id()) if qdjango_layer.has_column_acl: user = QGS_SERVER.user return qdjango_layer.visible_fields_for_user(user) except Layer.DoesNotExist: pass return attributes def cacheKey(self): """Return a cache key, a constant value means that the cache works normally and this filter does not influence the cache, an empty value (which is the default implementation) means that the cache is disabled""" # Return a constant: the cache is not influenced by this filter return "ca" # Register the filter, keep a reference because of the garbage collector ac_filter = ColumnAclAccessControlFilter(QGS_SERVER.serverInterface()) QGS_SERVER.serverInterface().registerAccessControl(ac_filter, 1)
% (QGS_SERVER.user, layer.id(), rule), "", Qgis.Info) return rule def cacheKey(self): """Return a cache key, a constant value means that the cache works normally and this filter does not influence the cache, an empty value (which is the default implementation) means that the cache is disabled""" # Return a constant: the cache is not influenced by this filter return "sl" # Register the filter, keep a reference because of the garbage collector ac_filter = SingleLayerSubsetStringAccessControlFilter( QGS_SERVER.serverInterface()) # Note: this should be the last filter, set the priority to 10000 QGS_SERVER.serverInterface().registerAccessControl(ac_filter, 10000) class SingleLayerExpressionAccessControlFilter(QgsAccessControlFilter): """A filter that sets an expression filter from the layer constraints""" def __init__(self, server_iface): super().__init__(server_iface) 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())
return "" # check for filtertoken request_data = QGS_SERVER.djrequest.POST if QGS_SERVER.djrequest.method == 'POST' \ else QGS_SERVER.djrequest.GET filtertoken = request_data.get('filtertoken') if not filtertoken: return "" rule = SessionTokenFilter.get_expr_for_token(filtertoken, qdjango_layer) QgsMessageLog.logMessage( "SingleLayerSessionTokenAccessControlFilter expression for filtertoken %s layer id %s: %s" % (filtertoken, layer.id(), rule), "", Qgis.Info) return rule def cacheKey(self): """Return a cache key, a contant value means that the cache works normally and this filter does not influence the cache, an empty value (which is the default implementation) means that the cache is disabled""" # Return a constant: the cache is not influenced by this filter return "slt" # Register the filter, keep a reference because of the garbage collector ac_filter3 = SingleLayerSessionTokenAccessControlFilter( QGS_SERVER.serverInterface()) QGS_SERVER.serverInterface().registerAccessControl(ac_filter3, 9998)
if qlayer.dataProvider().name() == Layer.TYPES.gdal and rlayer == qlayer.id(): self.layers_render.append({ 'qlayer': qlayer, 'renderer': qlayer.renderer().clone() }) rts = RTS(qlayer) rts.setDateIndex(int(rband)) def responseComplete(self): # Restore renderer for l in self.layers_render: l['qlayer'].setRenderer(l['renderer']) # Register the filter, keep a reference because of the garbage collector ac_filter10 = QRasterTimeSeriesFilter(QGS_SERVER.serverInterface()) QGS_SERVER.serverInterface().registerFilter(ac_filter10, 9995)
in the query string""" def __init__(self, server_iface): super().__init__(server_iface) def layerPermissions(self, layer): """Return the layer rights canRead, canInsert, canUpdate, canDelete """ rh = self.serverInterface().requestHandler() if rh.parameterMap().get("TEST_ACCESS_CONTROL", "") == layer.name(): permissions = QgsAccessControlFilter.LayerPermissions() permissions.canRead = False permissions.canUpdate = False permissions.canDelete = False permissions.canCreate = False return permissions else: return super().layerPermissions(layer) def cacheKey(self): """Return a cache key, a constant value means that the cache works normally and this filter does not influence the cache, an empty value (which is the default implementation) means that the cache is disabled""" # Return a constant: the cache is not influenced by this filter return "tac" # Register the filter, keep a reference because of the garbage collector ac_filter = TestAccessControlFilter(QGS_SERVER.serverInterface()) QGS_SERVER.serverInterface().registerAccessControl(ac_filter, 100)
def baseDoRequest(self, q): request = self.request # Uppercase REQUEST if 'REQUEST' in [k.upper() for k in q.keys()]: if request.method == 'GET': ows_request = q['REQUEST'].upper() else: if request.content_type == 'application/x-www-form-urlencoded': ows_request = request.POST['REQUEST'].upper() else: ows_request = request.POST['REQUEST'][0].upper() q['REQUEST'] = ows_request # FIXME: proxy or redirect in case of WMS/WFS/XYZ cascading? qgs_project = get_qgs_project(self.project.qgis_file.path) if qgs_project is None: raise Http404('The requested QGIS project could not be loaded!') data = None if request.method == 'GET': method = QgsBufferServerRequest.GetMethod elif request.method == 'POST': method = QgsBufferServerRequest.PostMethod data = request.body elif request.method == 'PUT': method = QgsBufferServerRequest.PutMethod data = request.body elif request.method == 'PATCH': method = QgsBufferServerRequest.PatchMethod data = request.body elif request.method == 'HEAD': method = QgsBufferServerRequest.HeadMethod elif request.method == 'DELETE': method = QgsBufferServerRequest.DeleteMethod else: logger.warning( "Request method not supported: %s, assuming GET" % request.method) method = QgsBufferServerRequest.GetMethod headers = {} for header_key in request.headers.keys(): headers[header_key] = request.headers.get(header_key) uri = request.build_absolute_uri(request.path) + '?' + q.urlencode() logger.debug('Calling QGIS Server: %s' % uri) qgs_request = QgsBufferServerRequest(uri, method, headers, data) # Attach user and project to the server object to make them accessible by the # server access control plugins (constraints etc.) QGS_SERVER.djrequest = request QGS_SERVER.user = request.user QGS_SERVER.project = self.project # For GetPrint QGIS functions that rely on layers visibility, we need to check # the layers from LAYERS use_ids = QgsServerProjectUtils.wmsUseLayerIds(qgs_project) tree_root = qgs_project.layerTreeRoot() # Loop through the layers and make them visible for layer_name in qgs_request.queryParameter('LAYERS').split(','): layer_name = urllib.parse.unquote(layer_name) layer = None if use_ids: layer = qgs_project.mapLayer(layer_name) else: try: layer = qgs_project.mapLayersByName(layer_name)[0] except: # short name? for l in qgs_project.mapLayers().values(): if l.shortName() == layer_name: layer = l break if layer is None: logger.warning( 'Could not find layer "{}" when configuring OWS call'.format(layer_name)) else: layer_node = tree_root.findLayer(layer) if layer_node is not None: layer_node.setItemVisibilityCheckedParentRecursive(True) else: logger.warning( 'Could not find layer tree node "{}" when configuring OWS call'.format(layer_name)) qgs_response = QgsBufferServerResponse() try: QGS_SERVER.handleRequest(qgs_request, qgs_response, qgs_project) except Exception as ex: return HttpResponseServerError(reason="Error handling server request: %s" % ex) response = HttpResponse(bytes(qgs_response.body())) response.status_code = qgs_response.statusCode() for key, value in qgs_response.headers().items(): response[key] = value return response
def layerFilterSubsetString(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: return "" rule = ConstraintSubsetStringRule.get_rule_definition_for_user(QGS_SERVER.user, qdjango_layer.pk) QgsMessageLog.logMessage("SingleLayerSubsetStringAccessControlFilter rule for user %s and layer id %s: %s" % (QGS_SERVER.user, layer.id(), rule), "", Qgis.Info) return rule # Register the filter, keep a reference because of the garbage collector ac_filter = SingleLayerSubsetStringAccessControlFilter(QGS_SERVER.serverInterface()) # Note: this should be the last filter, set the priority to 10000 QGS_SERVER.serverInterface().registerAccessControl(ac_filter, 10000) class SingleLayerExpressionAccessControlFilter(QgsAccessControlFilter): """A filter that sets an expression filter from the layer constraints""" def __init__(self, server_iface): super().__init__(server_iface) 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())
handler = self.server_iface.requestHandler() params = handler.parameterMap() service = params.get('SERVICE') if not service: return if service.lower() != 'wms': return # Check request to change atlas one if 'REQUEST' not in params or params['REQUEST'].lower() not in [ 'getprintatlas', 'getcapabilitiesatlas' ]: return request = params['REQUEST'].lower() handler.setParameter('SERVICE', 'ATLAS') handler.setParameter('VERSION', '1.0.0') if request == 'getcapabilitiesatlas': handler.setParameter('REQUEST', 'GetCapabilities') elif request == 'getprintatlas': handler.setParameter('REQUEST', 'GetPrint') # Register the filter, keep a reference because of the garbage collector altas_filter = AtlasPrintFilter(QGS_SERVER.serverInterface()) # Note: this should be the last filter, set the priority to 10000 QGS_SERVER.serverInterface().registerFilter(altas_filter, 50)
def tearDownClass(cls): super().tearDownClass() iface = QGS_SERVER.serverInterface() iface.removeConfigCacheEntry( cls.qdjango_project.qgis_project.fileName())