mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-05 00:09:32 -04:00
The plugin define the following methods:
* layerFilterExpression Return an additional filter, used in WMS/GetMap, WMS/GetFeatureInfo, WFS/GetFeature to filter the features * layerFilterSubsetString Return an additional the subset string (typically SQL) filter. Faster than the layerFilterExpression but not supported on all the type of layer * layerPermissions Change the rights on the layer per user (known by the plugin) Concern rights: publish, insert, update, delete. Mostly used in WFS/Transaction, and the publish in all requests. * authorizedLayerAttributes Be able to show some attributes only for a subset of user Used in: WMS/GetFeatureInfo, WFS/GetFeature * allowToEdit Be able to don't allow to edit a particular feature, in our case base on the Geometry Used in: WFS/Transaction * cacheKey Cache key to used to create the capabilities cache, "" for no cache, shouldn't contains any "-", default to ""
This commit is contained in:
parent
b1743dc8a8
commit
c9f0d83aaf
@ -44,6 +44,7 @@ sudo apt-get install --force-yes --no-install-recommends --no-install-suggests \
|
||||
python-qt4-sql \
|
||||
python-sip \
|
||||
python-sip-dev \
|
||||
python-gdal \
|
||||
spawn-fcgi \
|
||||
txt2tags \
|
||||
xauth \
|
||||
|
@ -1,4 +1,3 @@
|
||||
printf "[qgis_test]\nhost=localhost\ndbname=qgis_test\nuser=postgres" > ~/.pg_service.conf
|
||||
psql -c 'CREATE DATABASE qgis_test;' -U postgres
|
||||
psql -f $TRAVIS_BUILD_DIR/tests/testdata/provider/testdata.sql -U postgres -d qgis_test
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
xvfb-run ctest -V -E 'qgis_openstreetmaptest|qgis_wcsprovidertest' -S ./qgis-test-travis.ctest --output-on-failure
|
||||
|
||||
|
@ -604,6 +604,7 @@ INPUT = @CMAKE_SOURCE_DIR@/doc \
|
||||
@CMAKE_SOURCE_DIR@/src/server/qgsmapserviceexception.h \
|
||||
@CMAKE_SOURCE_DIR@/src/server/qgsrequesthandler.h \
|
||||
@CMAKE_SOURCE_DIR@/src/server/qgsserverfilter.h \
|
||||
@CMAKE_SOURCE_DIR@/src/server/qgsaccesscontrolfilter.h \
|
||||
@CMAKE_SOURCE_DIR@/src/server/qgsserverinterface.h
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
|
@ -47,6 +47,7 @@
|
||||
%Include qgsfeature.sip
|
||||
%Include qgsfeatureiterator.sip
|
||||
%Include qgsfeaturerequest.sip
|
||||
%Include qgsfeaturefilterprovider.sip
|
||||
%Include qgsfield.sip
|
||||
%Include qgsgeometryvalidator.sip
|
||||
%Include qgsgeometrysimplifier.sip
|
||||
|
24
python/core/qgsfeaturefilterprovider.sip
Normal file
24
python/core/qgsfeaturefilterprovider.sip
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Interface used by class that will filter the features of a layer.
|
||||
* The only method `filterFeatures` fill the `QgsFeatureRequest` to get only the
|
||||
* wanted features.
|
||||
**/
|
||||
class QgsFeatureFilterProvider
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsfeaturefilterprovider.h>
|
||||
%End
|
||||
|
||||
public:
|
||||
/** Add some filter to the feature request to don't have the unauthorized (unauthorised) features
|
||||
* @param layer the layer to filter
|
||||
* @param featureRequest the feature request to update
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
virtual void filterFeatures( const QgsVectorLayer* layer, QgsFeatureRequest& featureRequest ) const = 0;
|
||||
|
||||
/** Create a clone of the feature filter provider
|
||||
* @return a new clone
|
||||
*/
|
||||
virtual QgsFeatureFilterProvider* clone() const = 0;
|
||||
};
|
@ -288,6 +288,10 @@ class QgsMapRenderer : QObject
|
||||
*/
|
||||
bool splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent /In,Out/, QgsRectangle& r2 /Out/ );
|
||||
|
||||
/** Set a feature filter provider to filter the features
|
||||
* @param ffp the feature filter provider
|
||||
*/
|
||||
void setFeatureFilterProvider( const QgsFeatureFilterProvider* ffp );
|
||||
signals:
|
||||
|
||||
//! @deprecated in 2.4 - not emitted anymore
|
||||
|
33
python/server/qgsaccesscontrol.sip
Normal file
33
python/server/qgsaccesscontrol.sip
Normal file
@ -0,0 +1,33 @@
|
||||
/***************************************************************************
|
||||
qgsaccesscontrol.sip
|
||||
--------------------
|
||||
Access control helper for Qgis Server plugins
|
||||
|
||||
begin : 2015-05-19
|
||||
copyright : (C) 2015 by Stéphane Brunner
|
||||
email : stephane dot brunner at camptocamp dot org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* \class QgsAccessControl
|
||||
* \brief Class defining access control helper for QGIS Server.
|
||||
*/
|
||||
class QgsAccessControl : QgsFeatureFilterProvider
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgsaccesscontrol.h"
|
||||
#include "qgsaccesscontrolfilter.h"
|
||||
|
||||
#include <QMultiMap>
|
||||
%End
|
||||
|
||||
};
|
77
python/server/qgsaccesscontrolfilter.sip
Normal file
77
python/server/qgsaccesscontrolfilter.sip
Normal file
@ -0,0 +1,77 @@
|
||||
/***************************************************************************
|
||||
qgsaccesscontrolfilter.sip
|
||||
--------------------------
|
||||
Access control interface for Qgis Server plugins
|
||||
|
||||
begin : 2015-05-19
|
||||
copyright : (C) 2015 by Stéphane Brunner
|
||||
email : stephane dot brunner at camptocamp dot org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* \class QgsAccessControlFilter
|
||||
* \brief Class defining access control interface for QGIS Server.
|
||||
*
|
||||
* Security can define any (or none) of the following method:
|
||||
* * layerFilterExpression()
|
||||
* * layerFilterSubsetString()
|
||||
* * layerPermissions()
|
||||
* * authorizedLayerAttributes()
|
||||
* * allowToEdit()
|
||||
* * cacheKey()
|
||||
*/
|
||||
|
||||
class QgsAccessControlFilter
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgsaccesscontrolfilter.h"
|
||||
#include "qgsserverinterface.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsmaplayer.h"
|
||||
%End
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
* QgsServerInterface passed to plugins constructors
|
||||
* and must be passed to QgsAccessControlPlugin instances.
|
||||
*/
|
||||
QgsAccessControlFilter( const QgsServerInterface* serverInterface );
|
||||
/** Destructor */
|
||||
virtual ~QgsAccessControlFilter();
|
||||
|
||||
/** Describe the layer permission */
|
||||
struct LayerPermissions
|
||||
{
|
||||
bool canRead;
|
||||
bool canUpdate;
|
||||
bool canInsert;
|
||||
bool canDelete;
|
||||
};
|
||||
|
||||
/** Return the QgsServerInterface instance*/
|
||||
const QgsServerInterface* serverInterface() const;
|
||||
/** Return an additional expression filter */
|
||||
virtual const QString layerFilterExpression( const QgsVectorLayer* layer /Transfer/ ) const;
|
||||
/** Return an additional the subset string (typically SQL) filter.
|
||||
Faster than the layerFilterExpression but not supported on all the type of layer */
|
||||
virtual const QString layerFilterSubsetString( const QgsVectorLayer* layer /Transfer/ ) const;
|
||||
/** Return the layer permissions */
|
||||
virtual const LayerPermissions layerPermissions( const QgsMapLayer* layer /Transfer/ ) const;
|
||||
/** Return the authorized layer attributes */
|
||||
virtual const QStringList* authorizedLayerAttributes( const QgsVectorLayer* layer /Transfer/, const QStringList& attributes ) const;
|
||||
/** Are we authorize to modify the following geometry */
|
||||
virtual bool allowToEdit( const QgsVectorLayer* layer /Transfer/, const QgsFeature& feature /Transfer/ ) const;
|
||||
/** Cache key to used to create the capabilities cache, "" for no cache, shouldn't any contains "-", default to "" */
|
||||
virtual const QString cacheKey() const;
|
||||
};
|
||||
|
||||
typedef QMultiMap<int, QgsAccessControlFilter*> QgsAccessControlFilterMap;
|
@ -25,15 +25,16 @@ class QgsConfigCache: QObject
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgsconfigcache.h"
|
||||
#include "qgsaccesscontrolfilter.h"
|
||||
%End
|
||||
public:
|
||||
static QgsConfigCache* instance();
|
||||
~QgsConfigCache();
|
||||
|
||||
QgsServerProjectParser* serverConfiguration( const QString& filePath );
|
||||
QgsWCSProjectParser* wcsConfiguration( const QString& filePath );
|
||||
QgsWFSProjectParser* wfsConfiguration( const QString& filePath );
|
||||
QgsWMSConfigParser* wmsConfiguration( const QString& filePath, const QMap<QString, QString>& parameterMap = QMap< QString, QString >() );
|
||||
QgsWCSProjectParser* wcsConfiguration( const QString& filePath, const QgsAccessControl* accessControl );
|
||||
QgsWFSProjectParser* wfsConfiguration( const QString& filePath, const QgsAccessControl* accessControl );
|
||||
QgsWMSConfigParser* wmsConfiguration( const QString& filePath, const QgsAccessControl* accessControl, const QMap<QString, QString>& parameterMap = QMap< QString, QString >() );
|
||||
|
||||
private:
|
||||
QgsConfigCache();
|
||||
|
@ -61,7 +61,7 @@ class QgsRequestHandler
|
||||
/** Remove a request parameter*/
|
||||
virtual int removeParameter( const QString &key ) = 0;
|
||||
/** Return a request parameter*/
|
||||
virtual QString parameter( const QString &key) const = 0;
|
||||
virtual QString parameter( const QString &key ) const = 0;
|
||||
/** Return the requested format string*/
|
||||
QString format() const;
|
||||
/** Return the mime type for the response*/
|
||||
|
@ -50,6 +50,8 @@ class QgsServerInterface
|
||||
virtual void registerFilter( QgsServerFilter* filter /Transfer/, int priority = 0 ) = 0;
|
||||
/** Set the filters map */
|
||||
virtual void setFilters( QgsServerFiltersMap* filters /Transfer/) = 0;
|
||||
/** Register a security module with the given priority.*/
|
||||
virtual void registerAccessControl( QgsAccessControlFilter* accessControl /Transfer/, int priority = 0 ) = 0;
|
||||
/** Return an environment variable set by FCGI*/
|
||||
virtual QString getEnv(const QString& name ) const = 0;
|
||||
// Commented because of problems with typedef QgsServerFiltersMap, provided
|
||||
|
@ -37,7 +37,7 @@ class QgsWCSServer: public QgsOWSServer
|
||||
public:
|
||||
/** Constructor. Takes parameter map and a pointer to a renderer object (does not take ownership)*/
|
||||
QgsWCSServer( const QString& configFilePath, QMap<QString, QString>& parameters, QgsWCSProjectParser* pp,
|
||||
QgsRequestHandler* rh );
|
||||
QgsRequestHandler* rh, const QgsAccessControl* accessControl );
|
||||
~QgsWCSServer();
|
||||
|
||||
void executeRequest() override;
|
||||
|
@ -23,7 +23,7 @@ class QgsWCSProjectParser
|
||||
|
||||
%End
|
||||
public:
|
||||
QgsWCSProjectParser( const QString& filePath );
|
||||
QgsWCSProjectParser( const QString& filePath, const QgsAccessControl* ac );
|
||||
~QgsWCSProjectParser();
|
||||
|
||||
void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
|
||||
|
@ -61,7 +61,7 @@ class QgsWFSServer: public QgsOWSServer
|
||||
public:
|
||||
/** Constructor. Takes parameter map and a pointer to a renderer object (does not take ownership)*/
|
||||
QgsWFSServer( const QString& configFilePath, QMap<QString, QString>& parameters, QgsWFSProjectParser* cp,
|
||||
QgsRequestHandler* rh );
|
||||
QgsRequestHandler* rh, const QgsAccessControl* accessControl );
|
||||
~QgsWFSServer();
|
||||
|
||||
void executeRequest() override;
|
||||
|
@ -24,7 +24,7 @@ class QgsWFSProjectParser
|
||||
%End
|
||||
|
||||
public:
|
||||
QgsWFSProjectParser( const QString& filePath );
|
||||
QgsWFSProjectParser( const QString& filePath, const QgsAccessControl* ac );
|
||||
~QgsWFSProjectParser();
|
||||
|
||||
void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
|
||||
|
@ -59,7 +59,7 @@ class QgsWMSServer: public QgsOWSServer
|
||||
/** Constructor. Does _NOT_ take ownership of
|
||||
QgsConfigParser, QgsCapabilitiesCache and QgsMapRenderer*/
|
||||
QgsWMSServer( const QString& configFilePath, QMap<QString, QString> ¶meters, QgsWMSConfigParser* cp, QgsRequestHandler* rh,
|
||||
QgsMapRenderer* renderer, QgsCapabilitiesCache* capCache );
|
||||
QgsMapRenderer* renderer, QgsCapabilitiesCache* capCache, const QgsAccessControl* accessControl );
|
||||
~QgsWMSServer();
|
||||
|
||||
void executeRequest() override;
|
||||
|
@ -23,7 +23,7 @@ class QgsWMSProjectParser : public QgsWMSConfigParser
|
||||
|
||||
%End
|
||||
public:
|
||||
QgsWMSProjectParser( const QString& filePath );
|
||||
QgsWMSProjectParser( const QString& filePath, const QgsAccessControl* ac );
|
||||
virtual ~QgsWMSProjectParser();
|
||||
|
||||
/** Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.
|
||||
|
@ -14,6 +14,8 @@
|
||||
%If (HAVE_SERVER_PYTHON_PLUGINS)
|
||||
%Include qgsserverfilter.sip
|
||||
%Include qgsserverinterface.sip
|
||||
%Include qgsaccesscontrolfilter.sip
|
||||
%Include qgsaccesscontrol.sip
|
||||
%End
|
||||
|
||||
%Include qgsmapserviceexception.sip
|
||||
|
55
src/core/qgsfeaturefilterprovider.h
Normal file
55
src/core/qgsfeaturefilterprovider.h
Normal file
@ -0,0 +1,55 @@
|
||||
/***************************************************************************
|
||||
qgsfeaturefilterprovider.h
|
||||
--------------------------
|
||||
begin : 22-05-2015
|
||||
copyright : (C) 2008 by Stéphane Brunner
|
||||
email : stephane dot brunner at camptocamp dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSFEATUREFILTERPROVIDER_H
|
||||
#define QGSFEATUREFILTERPROVIDER_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
class QString;
|
||||
class QgsVectorLayer;
|
||||
class QgsFeatureRequest;
|
||||
|
||||
|
||||
/** \ingroup core
|
||||
* Interface used by class that will filter the features of a layer.
|
||||
* The only method `filterFeatures` fill the `QgsFeatureRequest` to get only the
|
||||
* wanted features.
|
||||
**/
|
||||
class CORE_EXPORT QgsFeatureFilterProvider
|
||||
{
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
QgsFeatureFilterProvider() {};
|
||||
|
||||
/** Destructor */
|
||||
virtual ~QgsFeatureFilterProvider() {};
|
||||
|
||||
/** Add some filter to the feature request to don't have the unauthorized (unauthorised) features
|
||||
* @param layer the layer to filter
|
||||
* @param featureRequest the feature request to update
|
||||
*/
|
||||
virtual void filterFeatures( const QgsVectorLayer* layer, QgsFeatureRequest& featureRequest ) const = 0;
|
||||
|
||||
/** Create a clone of the feature filter provider
|
||||
* @return a new clone
|
||||
*/
|
||||
virtual QgsFeatureFilterProvider* clone() const = 0;
|
||||
};
|
||||
|
||||
#endif
|
@ -335,6 +335,13 @@ class CORE_EXPORT QgsMapRenderer : public QObject
|
||||
*/
|
||||
bool splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent, QgsRectangle& r2 );
|
||||
|
||||
/** Set a feature filter provider to filter the features
|
||||
* @param ffp the feature filter provider
|
||||
*/
|
||||
void setFeatureFilterProvider( const QgsFeatureFilterProvider* ffp ) {
|
||||
mRenderContext.setFeatureFilterProvider( ffp );
|
||||
}
|
||||
|
||||
signals:
|
||||
|
||||
//! @deprecated in 2.4 - not emitted anymore
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "qgsrendercontext.h"
|
||||
|
||||
#include "qgsmapsettings.h"
|
||||
#include "qgsexpression.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
QgsRenderContext::QgsRenderContext()
|
||||
: mFlags( DrawEditingInfo | UseAdvancedEffects | DrawSelection | UseRenderingOptimization )
|
||||
@ -31,12 +33,17 @@ QgsRenderContext::QgsRenderContext()
|
||||
, mLabelingEngine( NULL )
|
||||
, mLabelingEngine2( 0 )
|
||||
, mGeometry( 0 )
|
||||
, mFeatureFilterProvider( NULL )
|
||||
{
|
||||
mVectorSimplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
|
||||
}
|
||||
|
||||
QgsRenderContext::~QgsRenderContext()
|
||||
{
|
||||
if ( mFeatureFilterProvider != NULL ) {
|
||||
delete mFeatureFilterProvider;
|
||||
mFeatureFilterProvider = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsRenderContext::setFlags( const QgsRenderContext::Flags& flags )
|
||||
@ -140,3 +147,15 @@ void QgsRenderContext::setUseRenderingOptimization( bool enabled )
|
||||
{
|
||||
setFlag( UseRenderingOptimization, enabled );
|
||||
}
|
||||
|
||||
void QgsRenderContext::setFeatureFilterProvider( const QgsFeatureFilterProvider* ffp )
|
||||
{
|
||||
if ( mFeatureFilterProvider != NULL ) {
|
||||
delete mFeatureFilterProvider;
|
||||
mFeatureFilterProvider = NULL;
|
||||
}
|
||||
if ( ffp != NULL )
|
||||
{
|
||||
mFeatureFilterProvider = ffp->clone();
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "qgsrectangle.h"
|
||||
#include "qgsvectorsimplifymethod.h"
|
||||
#include "qgsexpressioncontext.h"
|
||||
#include "qgsfeaturefilterprovider.h"
|
||||
|
||||
class QPainter;
|
||||
|
||||
@ -32,6 +33,9 @@ class QgsAbstractGeometryV2;
|
||||
class QgsLabelingEngineInterface;
|
||||
class QgsLabelingEngineV2;
|
||||
class QgsMapSettings;
|
||||
class QgsExpression;
|
||||
class QgsVectorLayer;
|
||||
|
||||
|
||||
/** \ingroup core
|
||||
* Contains information about the context of a rendering operation.
|
||||
@ -195,6 +199,18 @@ class CORE_EXPORT QgsRenderContext
|
||||
/** Sets pointer to original (unsegmentized) geometry*/
|
||||
void setGeometry( const QgsAbstractGeometryV2* geometry ) { mGeometry = geometry; }
|
||||
|
||||
/** Set a filter feature provider used to filter the features
|
||||
* @param ffp the filter feature provider
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
void setFeatureFilterProvider( const QgsFeatureFilterProvider* ffp );
|
||||
|
||||
/** Get the filter feature provider used to filter the features
|
||||
* @return the filter feature provider
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
const QgsFeatureFilterProvider* featureFilterProvider() { return mFeatureFilterProvider; }
|
||||
|
||||
private:
|
||||
|
||||
Flags mFlags;
|
||||
@ -238,6 +254,9 @@ class CORE_EXPORT QgsRenderContext
|
||||
|
||||
/** Pointer to the (unsegmentized) geometry*/
|
||||
const QgsAbstractGeometryV2* mGeometry;
|
||||
|
||||
/** The feature filter provider */
|
||||
const QgsFeatureFilterProvider* mFeatureFilterProvider;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsRenderContext::Flags )
|
||||
|
@ -43,6 +43,7 @@
|
||||
QgsVectorLayerRenderer::QgsVectorLayerRenderer( QgsVectorLayer* layer, QgsRenderContext& context )
|
||||
: QgsMapLayerRenderer( layer->id() )
|
||||
, mContext( context )
|
||||
, mLayer( layer )
|
||||
, mFields( layer->fields() )
|
||||
, mRendererV2( 0 )
|
||||
, mCache( 0 )
|
||||
@ -152,10 +153,23 @@ bool QgsVectorLayerRenderer::render()
|
||||
.setFilterRect( requestExtent )
|
||||
.setSubsetOfAttributes( mAttrNames, mFields );
|
||||
|
||||
if ( !rendererFilter.isEmpty() && rendererFilter != "TRUE" )
|
||||
const QgsFeatureFilterProvider* featureFilterProvider = mContext.featureFilterProvider();
|
||||
if ( featureFilterProvider != NULL)
|
||||
{
|
||||
featureFilterProvider->filterFeatures( mLayer, featureRequest );
|
||||
}
|
||||
if ( !rendererFilter.isNull() )
|
||||
{
|
||||
featureRequest.setFilterExpression( rendererFilter );
|
||||
featureRequest.setExpressionContext( mContext.expressionContext() );
|
||||
if ( featureRequest.filterExpression() == NULL )
|
||||
{
|
||||
featureRequest.setFilterExpression( rendererFilter );
|
||||
}
|
||||
else
|
||||
{
|
||||
featureRequest.setFilterExpression( QString( "(%s) AND (%s)" )
|
||||
.arg( rendererFilter, featureRequest.filterExpression()->expression() ) );
|
||||
}
|
||||
}
|
||||
|
||||
// enable the simplification of the geometries (Using the current map2pixel context) before send it to renderer engine.
|
||||
|
@ -86,6 +86,9 @@ class QgsVectorLayerRenderer : public QgsMapLayerRenderer
|
||||
|
||||
QgsRenderContext& mContext;
|
||||
|
||||
/** The rendered layer */
|
||||
QgsVectorLayer* mLayer;
|
||||
|
||||
QgsFields mFields; // TODO: use fields from mSource
|
||||
|
||||
QgsFeatureIds mSelectedFeatureIds;
|
||||
|
@ -25,6 +25,7 @@ SET ( qgis_mapserv_SRCS
|
||||
qgsgetrequesthandler.cpp
|
||||
qgspostrequesthandler.cpp
|
||||
qgssoaprequesthandler.cpp
|
||||
qgsowsserver.cpp
|
||||
qgswmsserver.cpp
|
||||
qgswfsserver.cpp
|
||||
qgswcsserver.cpp
|
||||
@ -82,6 +83,8 @@ SET(qgis_mapserv_SRCS ${qgis_mapserv_SRCS}
|
||||
qgsserverplugins.cpp
|
||||
qgsserverinterface.cpp
|
||||
qgsserverfilter.cpp
|
||||
qgsaccesscontrolfilter.cpp
|
||||
qgsaccesscontrol.cpp
|
||||
qgsserverinterfaceimpl.cpp
|
||||
)
|
||||
ENDIF (WITH_SERVER_PLUGINS)
|
||||
|
169
src/server/qgsaccesscontrol.cpp
Normal file
169
src/server/qgsaccesscontrol.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
/***************************************************************************
|
||||
qgsaccesscontrol.cpp
|
||||
--------------------
|
||||
begin : 22-05-2015
|
||||
copyright : (C) 2008 by Stéphane Brunner
|
||||
email : stephane dot brunner at camptocamp dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsaccesscontrol.h"
|
||||
#include "qgsfeaturerequest.h"
|
||||
#include "qgsmaplayer.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
/** Filter the features of the layer */
|
||||
void QgsAccessControl::filterFeatures( const QgsVectorLayer* layer, QgsFeatureRequest& featureRequest ) const
|
||||
{
|
||||
QStringList expressions = QStringList();
|
||||
QgsAccessControlFilterMap::const_iterator acIterator;
|
||||
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
|
||||
{
|
||||
const QString expression = acIterator.value()->layerFilterExpression( layer );
|
||||
if ( expression != NULL ) {
|
||||
expressions.append( expression );
|
||||
}
|
||||
}
|
||||
if ( !expressions.isEmpty() ) {
|
||||
featureRequest.setFilterExpression( expressions.join(" AND ") );
|
||||
}
|
||||
}
|
||||
|
||||
/** Clone the object */
|
||||
QgsFeatureFilterProvider* QgsAccessControl::clone() const
|
||||
{
|
||||
return new QgsAccessControl(*this);
|
||||
}
|
||||
|
||||
/** Return an additional subset string (typically SQL) filter */
|
||||
const QString QgsAccessControl::extraSubsetString( const QgsVectorLayer* layer ) const
|
||||
{
|
||||
QStringList sqls = QStringList();
|
||||
QgsAccessControlFilterMap::const_iterator acIterator;
|
||||
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
|
||||
{
|
||||
const QString sql = acIterator.value()->layerFilterSubsetString( layer );
|
||||
if ( sql != NULL ) {
|
||||
sqls.append( sql );
|
||||
}
|
||||
}
|
||||
return sqls.isEmpty() ? NULL : sqls.join(" AND ");
|
||||
}
|
||||
|
||||
/** Return the layer read right */
|
||||
bool QgsAccessControl::layerReadPermission( const QgsMapLayer* layer ) const
|
||||
{
|
||||
QgsAccessControlFilterMap::const_iterator acIterator;
|
||||
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
|
||||
{
|
||||
if ( !acIterator.value()->layerPermissions( layer ).canRead)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Return the layer insert right */
|
||||
bool QgsAccessControl::layerInsertPermission( const QgsVectorLayer* layer ) const
|
||||
{
|
||||
QgsAccessControlFilterMap::const_iterator acIterator;
|
||||
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
|
||||
{
|
||||
if ( !acIterator.value()->layerPermissions( layer ).canInsert)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Return the layer update right */
|
||||
bool QgsAccessControl::layerUpdatePermission( const QgsVectorLayer* layer ) const
|
||||
{
|
||||
QgsAccessControlFilterMap::const_iterator acIterator;
|
||||
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
|
||||
{
|
||||
if ( !acIterator.value()->layerPermissions( layer ).canUpdate)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Return the layer delete right */
|
||||
bool QgsAccessControl::layerDeletePermission( const QgsVectorLayer* layer ) const
|
||||
{
|
||||
QgsAccessControlFilterMap::const_iterator acIterator;
|
||||
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
|
||||
{
|
||||
if ( !acIterator.value()->layerPermissions( layer ).canDelete)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Return the authorized layer attributes */
|
||||
const QStringList QgsAccessControl::layerAttributes( const QgsVectorLayer* layer, const QStringList attributes ) const
|
||||
{
|
||||
QStringList currentAttributes( attributes );
|
||||
QgsAccessControlFilterMap::const_iterator acIterator;
|
||||
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
|
||||
{
|
||||
const QStringList* newAttributes = acIterator.value()->authorizedLayerAttributes( layer, currentAttributes );
|
||||
if (newAttributes != NULL) {
|
||||
currentAttributes = *newAttributes;
|
||||
}
|
||||
}
|
||||
return currentAttributes;
|
||||
}
|
||||
|
||||
/** Are we authorized to modify the following geometry */
|
||||
bool QgsAccessControl::allowToEdit( const QgsVectorLayer* layer, const QgsFeature& feature ) const
|
||||
{
|
||||
QgsAccessControlFilterMap::const_iterator acIterator;
|
||||
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
|
||||
{
|
||||
if ( !acIterator.value()->allowToEdit( layer, feature ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Fill the capabilities caching key */
|
||||
bool QgsAccessControl::fillCacheKey( QStringList& cacheKey ) const
|
||||
{
|
||||
QgsAccessControlFilterMap::const_iterator acIterator;
|
||||
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
|
||||
{
|
||||
QString newKey = acIterator.value()->cacheKey();
|
||||
if ( newKey.length() == 0 ) {
|
||||
cacheKey.clear();
|
||||
return false;
|
||||
}
|
||||
cacheKey << newKey;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Register a new access control filter */
|
||||
void QgsAccessControl::registerAccessControl( QgsAccessControlFilter* accessControl, int priority )
|
||||
{
|
||||
mPluginsAccessControls->insert( priority, accessControl );
|
||||
}
|
125
src/server/qgsaccesscontrol.h
Normal file
125
src/server/qgsaccesscontrol.h
Normal file
@ -0,0 +1,125 @@
|
||||
/***************************************************************************
|
||||
qgsaccesscontrol.h
|
||||
------------------
|
||||
begin : 22-05-2015
|
||||
copyright : (C) 2008 by Stéphane Brunner
|
||||
email : stephane dot brunner at camptocamp dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSACCESSCONTROL_H
|
||||
#define QGSACCESSCONTROL_H
|
||||
|
||||
#include "qgsfeaturefilterprovider.h"
|
||||
#include "qgsaccesscontrolfilter.h"
|
||||
|
||||
#include <QMultiMap>
|
||||
|
||||
class QgsAccessControlPlugin;
|
||||
|
||||
|
||||
/** \ingroup server
|
||||
* \class QgsAccessControl
|
||||
* \brief A helper class that centralise the restrictions given by all the
|
||||
* access control filter plugins.
|
||||
**/
|
||||
class SERVER_EXPORT QgsAccessControl : public QgsFeatureFilterProvider
|
||||
{
|
||||
public:
|
||||
/** Constructor */
|
||||
QgsAccessControl()
|
||||
{
|
||||
mPluginsAccessControls = new QgsAccessControlFilterMap();
|
||||
};
|
||||
/** Constructor */
|
||||
QgsAccessControl( const QgsAccessControl& copy )
|
||||
{
|
||||
mPluginsAccessControls = new QgsAccessControlFilterMap( *copy.mPluginsAccessControls );
|
||||
};
|
||||
/** Destructor */
|
||||
~QgsAccessControl()
|
||||
{
|
||||
delete mPluginsAccessControls;
|
||||
};
|
||||
|
||||
/** Filter the features of the layer
|
||||
* @param layer the layer to control
|
||||
* @param filterFeatures the request to fill
|
||||
*/
|
||||
void filterFeatures( const QgsVectorLayer* layer, QgsFeatureRequest& filterFeatures ) const;
|
||||
|
||||
/** Return a clone of the object
|
||||
* @return A clone
|
||||
*/
|
||||
QgsFeatureFilterProvider* clone() const;
|
||||
|
||||
/** Return an additional subset string (typically SQL) filter
|
||||
* @param layer the layer to control
|
||||
* @return the subset string to use
|
||||
*/
|
||||
const QString extraSubsetString( const QgsVectorLayer* layer ) const;
|
||||
|
||||
/** Return the layer read right
|
||||
* @param layer the layer to control
|
||||
* @return true if it can be read
|
||||
*/
|
||||
bool layerReadPermission( const QgsMapLayer* layer ) const;
|
||||
|
||||
/** Return the layer insert right
|
||||
* @param layer the layer to control
|
||||
* @return true if we can insert on it
|
||||
*/
|
||||
bool layerInsertPermission( const QgsVectorLayer* layer ) const;
|
||||
|
||||
/** Return the layer update right
|
||||
* @param layer the layer to control
|
||||
* @return true if we can do an update
|
||||
*/
|
||||
bool layerUpdatePermission( const QgsVectorLayer* layer ) const;
|
||||
|
||||
/** Return the layer delete right
|
||||
* @param layer the layer to control
|
||||
* @return true if we can do a delete
|
||||
*/
|
||||
bool layerDeletePermission( const QgsVectorLayer* layer ) const;
|
||||
|
||||
/** Return the authorized layer attributes
|
||||
* @param layer the layer to control
|
||||
* @param attributes the list of attribute
|
||||
* @return the list of visible attributes
|
||||
*/
|
||||
const QStringList layerAttributes( const QgsVectorLayer* layer, const QStringList attributes ) const;
|
||||
|
||||
/** Are we authorized to modify the following geometry
|
||||
* @param layer the layer to control
|
||||
* @param feature the concerned feature
|
||||
* @return true if we are allowed to edit the feature
|
||||
*/
|
||||
bool allowToEdit( const QgsVectorLayer* layer, const QgsFeature& feature ) const;
|
||||
|
||||
/** Fill the capabilities caching key
|
||||
* @param cacheKey the list to fill with a cache variant
|
||||
* @return false if we cant create a cache
|
||||
*/
|
||||
bool fillCacheKey( QStringList& cacheKey ) const;
|
||||
|
||||
/** Register an access control filter
|
||||
* @param accessControl the access control to add
|
||||
* @priority the priority used to define the order
|
||||
*/
|
||||
void registerAccessControl( QgsAccessControlFilter* accessControl, int priority = 0 );
|
||||
|
||||
private:
|
||||
/** The AccessControl plugins registry */
|
||||
QgsAccessControlFilterMap* mPluginsAccessControls;
|
||||
};
|
||||
|
||||
#endif
|
87
src/server/qgsaccesscontrolfilter.cpp
Normal file
87
src/server/qgsaccesscontrolfilter.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/***************************************************************************
|
||||
qgsaccesscontrolplugin.cpp
|
||||
--------------------------
|
||||
Access control interface for Qgis Server plugins
|
||||
|
||||
begin : 2015-05-19
|
||||
copyright : (C) 2015 by Stéphane Brunner
|
||||
email : stephane dot brunner at camptocamp dot org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "qgsaccesscontrolfilter.h"
|
||||
#include "qgsmessagelog.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
/** Constructor */
|
||||
QgsAccessControlFilter::QgsAccessControlFilter( const QgsServerInterface* serverInterface ):
|
||||
mServerInterface( serverInterface )
|
||||
{
|
||||
}
|
||||
|
||||
/** Destructor */
|
||||
QgsAccessControlFilter::~QgsAccessControlFilter()
|
||||
{
|
||||
}
|
||||
|
||||
/** Return an additional layer expression filter */
|
||||
const QString QgsAccessControlFilter::layerFilterExpression( const QgsVectorLayer* layer ) const
|
||||
{
|
||||
QgsMessageLog::logMessage( "QgsAccessControlFilter plugin default layerFilterExpression called", "AccessControlFilter", QgsMessageLog::INFO );
|
||||
Q_UNUSED( layer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Return an additional layer subset string (typically SQL) filter */
|
||||
const QString QgsAccessControlFilter::layerFilterSubsetString( const QgsVectorLayer* layer ) const
|
||||
{
|
||||
QgsMessageLog::logMessage( "QgsAccessControlFilter plugin default layerFilterSQL called", "AccessControlFilter", QgsMessageLog::INFO );
|
||||
Q_UNUSED( layer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Return the layer permissions */
|
||||
const QgsAccessControlFilter::LayerPermissions QgsAccessControlFilter::layerPermissions( const QgsMapLayer* layer ) const
|
||||
{
|
||||
QgsMessageLog::logMessage( "QgsAccessControlFilter plugin default layerPermissions called", "AccessControlFilter", QgsMessageLog::INFO );
|
||||
Q_UNUSED( layer );
|
||||
LayerPermissions permissions = QgsAccessControlFilter::LayerPermissions();
|
||||
permissions.canRead = permissions.canUpdate = permissions.canInsert = permissions.canDelete = true;
|
||||
return permissions;
|
||||
}
|
||||
|
||||
/** Return the authorized layer attributes */
|
||||
const QStringList* QgsAccessControlFilter::authorizedLayerAttributes( const QgsVectorLayer* layer, const QStringList& attributes ) const
|
||||
{
|
||||
Q_UNUSED( layer );
|
||||
Q_UNUSED( attributes );
|
||||
QgsMessageLog::logMessage( "QgsAccessControlFilter plugin default authorizedLayerAttributes called", "AccessControlFilter", QgsMessageLog::INFO );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Are we authorized to modify the feature */
|
||||
bool QgsAccessControlFilter::allowToEdit( const QgsVectorLayer* layer, const QgsFeature& feature ) const
|
||||
{
|
||||
QgsMessageLog::logMessage( "QgsAccessControlFilter plugin default allowToEdit called", "AccessControlFilter", QgsMessageLog::INFO );
|
||||
Q_UNUSED( layer );
|
||||
Q_UNUSED( feature );
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Cache key to used to create the capabilities cache, "" for no cache */
|
||||
const QString QgsAccessControlFilter::cacheKey() const
|
||||
{
|
||||
return "";
|
||||
}
|
115
src/server/qgsaccesscontrolfilter.h
Normal file
115
src/server/qgsaccesscontrolfilter.h
Normal file
@ -0,0 +1,115 @@
|
||||
/***************************************************************************
|
||||
qgsaccesscontrolfilter.h
|
||||
------------------------
|
||||
begin : 2015-05-19
|
||||
copyright : (C) 2015 by Stéphane Brunner
|
||||
email : stephane dot brunner at camptocamp dot org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSACCESSCONTROLPLUGIN_H
|
||||
#define QGSACCESSCONTROLPLUGIN_H
|
||||
|
||||
#include <QMultiMap>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
class QgsServerInterface;
|
||||
class QgsMapLayer;
|
||||
class QgsVectorLayer;
|
||||
class QgsExpression;
|
||||
class QgsFeature;
|
||||
|
||||
|
||||
/**
|
||||
* \class QgsAccessControlFilter
|
||||
* \brief Class defining access control interface for QGIS Server plugins.
|
||||
*
|
||||
* Security can define any (or none) of the following method:
|
||||
* * layerFilterExpression() - To get an additional expression filter (WMS/GetMap, WMS/GetFeatureInfo, WFS/GetFeature)
|
||||
* * layerFilterSQL() - To get an additional SQL filter (WMS/GetMap, WMS/GetFeatureInfo, WFS/GetFeature) for layer that support SQL
|
||||
* * layerPermissions() - To give the general layer permissins (read / update / insert / delete)
|
||||
* * authorizedLayerAttributes() - Tho filter the attributes (WMS/GetFeatureInfo, WFS/GetFeature)
|
||||
* * allowToEdit() - (all WFS-T requests)
|
||||
*/
|
||||
class SERVER_EXPORT QgsAccessControlFilter
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor
|
||||
* QgsServerInterface passed to plugins constructors
|
||||
* and must be passed to QgsAccessControlFilter instances.
|
||||
*/
|
||||
QgsAccessControlFilter( const QgsServerInterface* serverInterface );
|
||||
/** Destructor */
|
||||
virtual ~QgsAccessControlFilter();
|
||||
|
||||
/** Describe the layer permission */
|
||||
struct LayerPermissions {
|
||||
bool canRead;
|
||||
bool canUpdate;
|
||||
bool canInsert;
|
||||
bool canDelete;
|
||||
};
|
||||
|
||||
/** Return the QgsServerInterface instance */
|
||||
const QgsServerInterface* serverInterface() const { return mServerInterface; }
|
||||
|
||||
/** Return an additional expression filter
|
||||
* @param layer the layer to control
|
||||
* @return the filter expression
|
||||
*/
|
||||
virtual const QString layerFilterExpression( const QgsVectorLayer* layer ) const;
|
||||
|
||||
/** Return an additional subset string (typically SQL) filter
|
||||
* @param layer the layer to control
|
||||
* @return the subset string
|
||||
*/
|
||||
virtual const QString layerFilterSubsetString( const QgsVectorLayer* layer ) const;
|
||||
|
||||
/** Return the layer permissions
|
||||
* @param layer the layer to control
|
||||
* @return the permission to use on the layer
|
||||
*/
|
||||
virtual const LayerPermissions layerPermissions( const QgsMapLayer* layer ) const;
|
||||
|
||||
/** Return the authorized layer attributes
|
||||
* @param layer the layer to control
|
||||
* @param attributes the current list of visible attribute
|
||||
* @return the new list of visible attributes
|
||||
*/
|
||||
virtual const QStringList* authorizedLayerAttributes( const QgsVectorLayer* layer, const QStringList& attributes ) const;
|
||||
|
||||
/** Are we authorized to modify the following geometry
|
||||
* @param layer the layer to control
|
||||
* @param feature the concerned feature
|
||||
* @return true if we are allowed to edit
|
||||
*/
|
||||
virtual bool allowToEdit( const QgsVectorLayer* layer, const QgsFeature& feature ) const;
|
||||
|
||||
/** Cache key to used to create the capabilities cache
|
||||
* @return the cache key, "" for no cache
|
||||
*/
|
||||
virtual const QString cacheKey() const;
|
||||
|
||||
private:
|
||||
|
||||
/** The server interface */
|
||||
const QgsServerInterface* mServerInterface;
|
||||
|
||||
};
|
||||
|
||||
/** The registry definition */
|
||||
typedef QMultiMap<int, QgsAccessControlFilter*> QgsAccessControlFilterMap;
|
||||
|
||||
|
||||
#endif // QGSSERVERSECURITY_H
|
@ -28,13 +28,13 @@ QgsCapabilitiesCache::~QgsCapabilitiesCache()
|
||||
{
|
||||
}
|
||||
|
||||
const QDomDocument* QgsCapabilitiesCache::searchCapabilitiesDocument( const QString& configFilePath, const QString& version )
|
||||
const QDomDocument* QgsCapabilitiesCache::searchCapabilitiesDocument( const QString& configFilePath, const QString& key )
|
||||
{
|
||||
QCoreApplication::processEvents(); //get updates from file system watcher
|
||||
|
||||
if ( mCachedCapabilities.contains( configFilePath ) && mCachedCapabilities[ configFilePath ].contains( version ) )
|
||||
if ( mCachedCapabilities.contains( configFilePath ) && mCachedCapabilities[ configFilePath ].contains( key ) )
|
||||
{
|
||||
return &mCachedCapabilities[configFilePath][version];
|
||||
return &mCachedCapabilities[ configFilePath ][ key ];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -42,7 +42,7 @@ const QDomDocument* QgsCapabilitiesCache::searchCapabilitiesDocument( const QStr
|
||||
}
|
||||
}
|
||||
|
||||
void QgsCapabilitiesCache::insertCapabilitiesDocument( const QString& configFilePath, const QString& version, const QDomDocument* doc )
|
||||
void QgsCapabilitiesCache::insertCapabilitiesDocument( const QString& configFilePath, const QString& key, const QDomDocument* doc )
|
||||
{
|
||||
if ( mCachedCapabilities.size() > 40 )
|
||||
{
|
||||
@ -58,7 +58,7 @@ void QgsCapabilitiesCache::insertCapabilitiesDocument( const QString& configFile
|
||||
mCachedCapabilities.insert( configFilePath, QHash<QString, QDomDocument>() );
|
||||
}
|
||||
|
||||
mCachedCapabilities[ configFilePath ].insert( version, doc->cloneNode().toDocument() );
|
||||
mCachedCapabilities[ configFilePath ].insert( key, doc->cloneNode().toDocument() );
|
||||
}
|
||||
|
||||
void QgsCapabilitiesCache::removeChangedEntry( const QString& path )
|
||||
|
@ -31,10 +31,18 @@ class SERVER_EXPORT QgsCapabilitiesCache : public QObject
|
||||
QgsCapabilitiesCache();
|
||||
~QgsCapabilitiesCache();
|
||||
|
||||
/** Returns cached capabilities document (or 0 if document for configuration file not in cache)*/
|
||||
const QDomDocument* searchCapabilitiesDocument( const QString& configFilePath, const QString& version );
|
||||
/** Inserts new capabilities document (creates a copy of the document, does not take ownership)*/
|
||||
void insertCapabilitiesDocument( const QString& configFilePath, const QString& version, const QDomDocument* doc );
|
||||
/** Returns cached capabilities document (or 0 if document for configuration file not in cache)
|
||||
* @param configFilePath the progect file path
|
||||
* @param key key used to separate different version in different cache
|
||||
*/
|
||||
const QDomDocument* searchCapabilitiesDocument( const QString& configFilePath, const QString& key );
|
||||
|
||||
/** Inserts new capabilities document (creates a copy of the document, does not take ownership)
|
||||
* @param configFilePath the progect file path
|
||||
* @param key key used to separate different version in different cache
|
||||
* @param doc the DOM document
|
||||
*/
|
||||
void insertCapabilitiesDocument( const QString& configFilePath, const QString& key, const QDomDocument* doc );
|
||||
|
||||
private:
|
||||
QHash< QString, QHash< QString, QDomDocument > > mCachedCapabilities;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "qgswfsprojectparser.h"
|
||||
#include "qgswmsprojectparser.h"
|
||||
#include "qgssldconfigparser.h"
|
||||
#include "qgsaccesscontrol.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
@ -54,7 +55,12 @@ QgsServerProjectParser* QgsConfigCache::serverConfiguration( const QString& file
|
||||
return new QgsServerProjectParser( doc, filePath );
|
||||
}
|
||||
|
||||
QgsWCSProjectParser *QgsConfigCache::wcsConfiguration( const QString& filePath )
|
||||
QgsWCSProjectParser *QgsConfigCache::wcsConfiguration(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
)
|
||||
{
|
||||
QgsWCSProjectParser *p = mWCSConfigCache.object( filePath );
|
||||
if ( !p )
|
||||
@ -64,7 +70,12 @@ QgsWCSProjectParser *QgsConfigCache::wcsConfiguration( const QString& filePath )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
p = new QgsWCSProjectParser( filePath );
|
||||
p = new QgsWCSProjectParser(
|
||||
filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
);
|
||||
mWCSConfigCache.insert( filePath, p );
|
||||
p = mWCSConfigCache.object( filePath );
|
||||
Q_ASSERT( p );
|
||||
@ -74,7 +85,12 @@ QgsWCSProjectParser *QgsConfigCache::wcsConfiguration( const QString& filePath )
|
||||
return p;
|
||||
}
|
||||
|
||||
QgsWFSProjectParser *QgsConfigCache::wfsConfiguration( const QString& filePath )
|
||||
QgsWFSProjectParser *QgsConfigCache::wfsConfiguration(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
)
|
||||
{
|
||||
QgsWFSProjectParser *p = mWFSConfigCache.object( filePath );
|
||||
if ( !p )
|
||||
@ -84,7 +100,12 @@ QgsWFSProjectParser *QgsConfigCache::wfsConfiguration( const QString& filePath )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
p = new QgsWFSProjectParser( filePath );
|
||||
p = new QgsWFSProjectParser(
|
||||
filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
);
|
||||
mWFSConfigCache.insert( filePath, p );
|
||||
p = mWFSConfigCache.object( filePath );
|
||||
Q_ASSERT( p );
|
||||
@ -94,7 +115,13 @@ QgsWFSProjectParser *QgsConfigCache::wfsConfiguration( const QString& filePath )
|
||||
return p;
|
||||
}
|
||||
|
||||
QgsWMSConfigParser *QgsConfigCache::wmsConfiguration( const QString& filePath, const QMap<QString, QString>& parameterMap )
|
||||
QgsWMSConfigParser *QgsConfigCache::wmsConfiguration(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
, const QMap<QString, QString>& parameterMap
|
||||
)
|
||||
{
|
||||
QgsWMSConfigParser *p = mWMSConfigCache.object( filePath );
|
||||
if ( !p )
|
||||
@ -114,7 +141,12 @@ QgsWMSConfigParser *QgsConfigCache::wmsConfiguration( const QString& filePath, c
|
||||
}
|
||||
else
|
||||
{
|
||||
p = new QgsWMSProjectParser( filePath );
|
||||
p = new QgsWMSProjectParser(
|
||||
filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
);
|
||||
}
|
||||
mWMSConfigCache.insert( filePath, p );
|
||||
p = mWMSConfigCache.object( filePath );
|
||||
|
@ -18,6 +18,8 @@
|
||||
#ifndef QGSCONFIGCACHE_H
|
||||
#define QGSCONFIGCACHE_H
|
||||
|
||||
#include "qgsconfig.h"
|
||||
|
||||
#include <QCache>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QMap>
|
||||
@ -27,6 +29,7 @@ class QgsServerProjectParser;
|
||||
class QgsWCSProjectParser;
|
||||
class QgsWFSProjectParser;
|
||||
class QgsWMSConfigParser;
|
||||
class QgsAccessControl;
|
||||
|
||||
class QDomDocument;
|
||||
|
||||
@ -38,9 +41,25 @@ class SERVER_EXPORT QgsConfigCache : public QObject
|
||||
~QgsConfigCache();
|
||||
|
||||
QgsServerProjectParser* serverConfiguration( const QString& filePath );
|
||||
QgsWCSProjectParser* wcsConfiguration( const QString& filePath );
|
||||
QgsWFSProjectParser* wfsConfiguration( const QString& filePath );
|
||||
QgsWMSConfigParser* wmsConfiguration( const QString& filePath, const QMap<QString, QString>& parameterMap = ( QMap< QString, QString >() ) );
|
||||
QgsWCSProjectParser* wcsConfiguration(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
);
|
||||
QgsWFSProjectParser* wfsConfiguration(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
);
|
||||
QgsWMSConfigParser* wmsConfiguration(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
, const QMap<QString, QString>& parameterMap = ( QMap< QString, QString >() )
|
||||
);
|
||||
|
||||
private:
|
||||
QgsConfigCache();
|
||||
|
@ -678,6 +678,10 @@ QString QgsHttpRequestHandler::readPostBody() const
|
||||
QgsMessageLog::logMessage( "could not convert CONTENT_LENGTH to int" );
|
||||
}
|
||||
}
|
||||
// Used by the tests
|
||||
else if ( getenv( "REQUEST_BODY" ) != NULL ) {
|
||||
inputString = getenv( "REQUEST_BODY" );
|
||||
}
|
||||
return inputString;
|
||||
}
|
||||
|
||||
|
72
src/server/qgsowsserver.cpp
Normal file
72
src/server/qgsowsserver.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/***************************************************************************
|
||||
qgsowsserver.cpp
|
||||
-------------------
|
||||
begin : February 27, 2012
|
||||
copyright : (C) 2012 by René-Luc D'Hont & Marco Hugentobler
|
||||
email : rldhont at 3liz dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsowsserver.h"
|
||||
#include "qgsmaplayerregistry.h"
|
||||
#include "qgsmessagelog.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
/** Apply filter from AccessControl */
|
||||
void QgsOWSServer::applyAccessControlLayerFilters( QgsMapLayer* mapLayer, QMap<QString, QString>& originalLayerFilters ) const
|
||||
{
|
||||
if ( QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( mapLayer ) )
|
||||
{
|
||||
if ( layer->setSubsetString( "" ) )
|
||||
{
|
||||
QString sql = mAccessControl->extraSubsetString( layer );
|
||||
if ( sql != NULL )
|
||||
{
|
||||
if ( !originalLayerFilters.contains( layer->id() ) )
|
||||
{
|
||||
originalLayerFilters.insert( layer->id(), layer->subsetString() );
|
||||
}
|
||||
if ( !layer->subsetString().isEmpty() )
|
||||
{
|
||||
sql.prepend( " AND " );
|
||||
sql.prepend( layer->subsetString() );
|
||||
}
|
||||
layer->setSubsetString( sql );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsMessageLog::logMessage( "Layer does not support Subset String" );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Restore layer filter as original */
|
||||
void QgsOWSServer::restoreLayerFilters( const QMap<QString, QString>& filterMap ) const
|
||||
{
|
||||
QMap<QString, QString>::const_iterator filterIt = filterMap.constBegin();
|
||||
for ( ; filterIt != filterMap.constEnd(); ++filterIt )
|
||||
{
|
||||
QgsVectorLayer* filteredLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( filterIt.key() ) );
|
||||
if ( filteredLayer )
|
||||
{
|
||||
QgsVectorDataProvider* dp = filteredLayer->dataProvider();
|
||||
if ( dp )
|
||||
{
|
||||
dp->setSubsetString( filterIt.value() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -19,12 +19,28 @@
|
||||
#define QGSOWSSERVER_H
|
||||
|
||||
#include "qgsrequesthandler.h"
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
#include "qgsaccesscontrol.h"
|
||||
#endif
|
||||
|
||||
class QgsOWSServer
|
||||
{
|
||||
public:
|
||||
QgsOWSServer( const QString& configFilePath, const QMap<QString, QString>& parameters, QgsRequestHandler* rh )
|
||||
: mParameters( parameters ), mRequestHandler( rh ), mConfigFilePath( configFilePath ) {}
|
||||
QgsOWSServer(
|
||||
const QString& configFilePath
|
||||
, const QMap<QString, QString>& parameters
|
||||
, QgsRequestHandler* rh
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* ac
|
||||
#endif
|
||||
)
|
||||
: mParameters( parameters )
|
||||
, mRequestHandler( rh )
|
||||
, mConfigFilePath( configFilePath )
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, mAccessControl( ac )
|
||||
#endif
|
||||
{}
|
||||
virtual ~QgsOWSServer() {}
|
||||
|
||||
virtual void executeRequest() = 0;
|
||||
@ -36,6 +52,22 @@ class QgsOWSServer
|
||||
QMap<QString, QString> mParameters;
|
||||
QgsRequestHandler* mRequestHandler;
|
||||
QString mConfigFilePath;
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
/** The access control helper */
|
||||
const QgsAccessControl* mAccessControl;
|
||||
|
||||
/** Apply filter strings from the access control to the layers.
|
||||
* @param layer the concerned layer
|
||||
* @param originalLayerFilters the original layer filter
|
||||
*
|
||||
*/
|
||||
void applyAccessControlLayerFilters( QgsMapLayer* layer, QMap<QString, QString>& originalLayerFilters ) const;
|
||||
#endif
|
||||
|
||||
/** Restores the original layer filters
|
||||
* @param filterMap the original layer filter
|
||||
*/
|
||||
void restoreLayerFilters( const QMap < QString, QString >& filterMap ) const;
|
||||
};
|
||||
|
||||
#endif // QGSOWSSERVER_H
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include "qgsmaplayerregistry.h"
|
||||
#include "qgsserverlogger.h"
|
||||
#include "qgseditorwidgetregistry.h"
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
#include "qgsaccesscontrolfilter.h"
|
||||
#endif
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QNetworkDiskCache>
|
||||
@ -486,6 +489,10 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
|
||||
|
||||
// Copy the parameters map
|
||||
QMap<QString, QString> parameterMap( theRequestHandler->parameterMap() );
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
const QgsAccessControl* accessControl = NULL;
|
||||
accessControl = mServerInterface->accessControls();
|
||||
#endif
|
||||
|
||||
printRequestParameters( parameterMap, logLevel );
|
||||
QMap<QString, QString>::const_iterator paramIt;
|
||||
@ -520,40 +527,81 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
|
||||
{
|
||||
if ( serviceString == "WCS" )
|
||||
{
|
||||
QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( configFilePath );
|
||||
QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration(
|
||||
configFilePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
);
|
||||
if ( !p )
|
||||
{
|
||||
theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsWCSServer wcsServer( configFilePath, parameterMap, p, theRequestHandler.data() );
|
||||
QgsWCSServer wcsServer(
|
||||
configFilePath
|
||||
, parameterMap
|
||||
, p
|
||||
, theRequestHandler.data()
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
);
|
||||
wcsServer.executeRequest();
|
||||
}
|
||||
}
|
||||
else if ( serviceString == "WFS" )
|
||||
{
|
||||
QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration( configFilePath );
|
||||
QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration(
|
||||
configFilePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
);
|
||||
if ( !p )
|
||||
{
|
||||
theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsWFSServer wfsServer( configFilePath, parameterMap, p, theRequestHandler.data() );
|
||||
QgsWFSServer wfsServer(
|
||||
configFilePath
|
||||
, parameterMap
|
||||
, p
|
||||
, theRequestHandler.data()
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
);
|
||||
wfsServer.executeRequest();
|
||||
}
|
||||
}
|
||||
else if ( serviceString == "WMS" )
|
||||
{
|
||||
QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration( configFilePath, parameterMap );
|
||||
QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration(
|
||||
configFilePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
);
|
||||
if ( !p )
|
||||
{
|
||||
theRequestHandler->setServiceException( QgsMapServiceException( "WMS configuration error", "There was an error reading the project file or the SLD configuration" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsWMSServer wmsServer( configFilePath, parameterMap, p, theRequestHandler.data(), mMapRenderer, mCapabilitiesCache );
|
||||
QgsWMSServer wmsServer(
|
||||
configFilePath
|
||||
, parameterMap
|
||||
, p
|
||||
, theRequestHandler.data()
|
||||
, mMapRenderer
|
||||
, mCapabilitiesCache
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
);
|
||||
wmsServer.executeRequest();
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +18,13 @@
|
||||
|
||||
#include "qgsserverinterface.h"
|
||||
|
||||
/** Constructor */
|
||||
QgsServerInterface::QgsServerInterface():
|
||||
mConfigFilePath( QString() )
|
||||
{
|
||||
}
|
||||
|
||||
/** Destructor */
|
||||
QgsServerInterface::~QgsServerInterface()
|
||||
{
|
||||
}
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "qgscapabilitiescache.h"
|
||||
#include "qgsrequesthandler.h"
|
||||
#include "qgsserverfilter.h"
|
||||
#include "qgsaccesscontrolfilter.h"
|
||||
#include "qgsaccesscontrol.h"
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
@ -45,6 +47,7 @@ class SERVER_EXPORT QgsServerInterface
|
||||
/**
|
||||
* Set the request handler
|
||||
* @param requestHandler request handler
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
virtual void setRequestHandler( QgsRequestHandler* requestHandler ) = 0;
|
||||
|
||||
@ -85,6 +88,13 @@ class SERVER_EXPORT QgsServerInterface
|
||||
* @return QgsServerFiltersMap list of QgsServerFilter
|
||||
*/
|
||||
virtual QgsServerFiltersMap filters( ) = 0;
|
||||
/** Register an access control filter
|
||||
* @param accessControl the access control to register
|
||||
* @param priority the priority used to order them
|
||||
*/
|
||||
virtual void registerAccessControl( QgsAccessControlFilter* accessControl, int priority = 0 ) = 0;
|
||||
/** Gets the registred access control filters */
|
||||
virtual const QgsAccessControl* accessControls( ) const = 0;
|
||||
|
||||
//! Return an enrironment variable, used to pass environment variables to python
|
||||
virtual QString getEnv( const QString& name ) const = 0;
|
||||
|
@ -20,10 +20,12 @@
|
||||
#include "qgsserverinterfaceimpl.h"
|
||||
|
||||
|
||||
/** Constructor */
|
||||
QgsServerInterfaceImpl::QgsServerInterfaceImpl( QgsCapabilitiesCache* capCache ) :
|
||||
mCapabilitiesCache( capCache )
|
||||
{
|
||||
mRequestHandler = NULL;
|
||||
mAccessControls = new QgsAccessControl();
|
||||
}
|
||||
|
||||
|
||||
@ -36,6 +38,7 @@ QString QgsServerInterfaceImpl::getEnv( const QString& name ) const
|
||||
/** Destructor */
|
||||
QgsServerInterfaceImpl::~QgsServerInterfaceImpl()
|
||||
{
|
||||
delete mAccessControls;
|
||||
}
|
||||
|
||||
|
||||
@ -63,3 +66,9 @@ void QgsServerInterfaceImpl::setFilters( QgsServerFiltersMap* filters )
|
||||
{
|
||||
mFilters = *filters;
|
||||
}
|
||||
|
||||
/** Register a new access control filter */
|
||||
void QgsServerInterfaceImpl::registerAccessControl( QgsAccessControlFilter* accessControl, int priority )
|
||||
{
|
||||
mAccessControls->registerAccessControl( accessControl, priority );
|
||||
}
|
||||
|
@ -51,6 +51,12 @@ class QgsServerInterfaceImpl : public QgsServerInterface
|
||||
QgsRequestHandler* requestHandler( ) override { return mRequestHandler; }
|
||||
void registerFilter( QgsServerFilter *filter, int priority = 0 ) override;
|
||||
QgsServerFiltersMap filters( ) override { return mFilters; }
|
||||
/** Register an access control filter */
|
||||
void registerAccessControl( QgsAccessControlFilter *accessControl, int priority = 0 ) override;
|
||||
/** Gets the helper over all the registered access control filters
|
||||
* @return the access control helper
|
||||
*/
|
||||
const QgsAccessControl* accessControls( ) const override { return mAccessControls; }
|
||||
QString getEnv( const QString& name ) const override;
|
||||
QString configFilePath( ) override { return mConfigFilePath; }
|
||||
void setConfigFilePath( const QString& configFilePath ) override;
|
||||
@ -60,6 +66,7 @@ class QgsServerInterfaceImpl : public QgsServerInterface
|
||||
|
||||
QString mConfigFilePath;
|
||||
QgsServerFiltersMap mFilters;
|
||||
QgsAccessControl* mAccessControls;
|
||||
QgsCapabilitiesCache* mCapabilitiesCache;
|
||||
QgsRequestHandler* mRequestHandler;
|
||||
|
||||
|
@ -18,7 +18,9 @@
|
||||
#ifndef QGSSERVERPROJECTPARSER_H
|
||||
#define QGSSERVERPROJECTPARSER_H
|
||||
|
||||
#include "qgsconfig.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
#include <QDomElement>
|
||||
#include <QHash>
|
||||
#include <QMap>
|
||||
|
@ -19,8 +19,22 @@
|
||||
#include "qgsconfigcache.h"
|
||||
#include "qgsconfigparserutils.h"
|
||||
#include "qgsrasterlayer.h"
|
||||
#include "qgsmapserviceexception.h"
|
||||
#include "qgsmessagelog.h"
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
#include "qgsaccesscontrol.h"
|
||||
#endif
|
||||
|
||||
QgsWCSProjectParser::QgsWCSProjectParser( const QString& filePath )
|
||||
|
||||
QgsWCSProjectParser::QgsWCSProjectParser(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* as
|
||||
#endif
|
||||
)
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
: mAccessControl( as )
|
||||
#endif
|
||||
{
|
||||
mProjectParser = QgsConfigCache::instance()->serverConfiguration( filePath );
|
||||
}
|
||||
@ -81,6 +95,12 @@ void QgsWCSProjectParser::wcsContentMetadata( QDomElement& parentElement, QDomDo
|
||||
QgsMapLayer *layer = mProjectParser->createLayerFromElement( elem );
|
||||
if ( layer && wcsLayersId.contains( layer->id() ) )
|
||||
{
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( !mAccessControl->layerReadPermission( layer ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
QgsDebugMsg( QString( "add layer %1 to map" ).arg( layer->id() ) );
|
||||
layerMap.insert( layer->id(), layer );
|
||||
|
||||
@ -201,6 +221,14 @@ void QgsWCSProjectParser::describeCoverage( const QString& aCoveName, QDomElemen
|
||||
QgsRasterLayer *rLayer = dynamic_cast<QgsRasterLayer *>( mProjectParser->createLayerFromElement( elem ) );
|
||||
if ( !rLayer )
|
||||
continue;
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( !mAccessControl->layerReadPermission( rLayer ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString coveName = rLayer->name();
|
||||
coveName = coveName.replace( " ", "_" );
|
||||
if ( wcsLayersId.contains( rLayer->id() ) && ( aCoveName == "" || coveNameList.contains( coveName ) ) )
|
||||
|
@ -20,10 +20,19 @@
|
||||
|
||||
#include "qgsserverprojectparser.h"
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
class QgsAccessControl;
|
||||
#endif
|
||||
|
||||
class SERVER_EXPORT QgsWCSProjectParser
|
||||
{
|
||||
public:
|
||||
QgsWCSProjectParser( const QString& filePath );
|
||||
QgsWCSProjectParser(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* ac
|
||||
#endif
|
||||
);
|
||||
~QgsWCSProjectParser();
|
||||
|
||||
void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
|
||||
@ -36,6 +45,9 @@ class SERVER_EXPORT QgsWCSProjectParser
|
||||
|
||||
private:
|
||||
QgsServerProjectParser* mProjectParser;
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
const QgsAccessControl* mAccessControl;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // QGSWCSPROJECTPARSER_H
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "qgsrasterfilewriter.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmapserviceexception.h"
|
||||
#include "qgsaccesscontrol.h"
|
||||
|
||||
#include <QTemporaryFile>
|
||||
#include <QUrl>
|
||||
@ -37,15 +38,38 @@ static const QString WCS_NAMESPACE = "http://www.opengis.net/wcs";
|
||||
static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
|
||||
static const QString OGC_NAMESPACE = "http://www.opengis.net/ogc";
|
||||
|
||||
QgsWCSServer::QgsWCSServer( const QString& configFilePath, QMap<QString, QString> ¶meters, QgsWCSProjectParser* pp,
|
||||
QgsRequestHandler* rh )
|
||||
: QgsOWSServer( configFilePath, parameters, rh )
|
||||
, mConfigParser( pp )
|
||||
QgsWCSServer::QgsWCSServer(
|
||||
const QString& configFilePath
|
||||
, QMap<QString, QString> ¶meters
|
||||
, QgsWCSProjectParser* pp
|
||||
, QgsRequestHandler* rh
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
)
|
||||
: QgsOWSServer(
|
||||
configFilePath
|
||||
, parameters
|
||||
, rh
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
)
|
||||
, mConfigParser(
|
||||
pp
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
QgsWCSServer::QgsWCSServer()
|
||||
: QgsOWSServer( QString(), QMap<QString, QString>(), 0 )
|
||||
: QgsOWSServer(
|
||||
QString()
|
||||
, QMap<QString, QString>()
|
||||
, 0
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, NULL
|
||||
#endif
|
||||
)
|
||||
, mConfigParser( 0 )
|
||||
{
|
||||
}
|
||||
@ -353,6 +377,13 @@ QByteArray* QgsWCSServer::getCoverage()
|
||||
QgsRasterLayer* rLayer = dynamic_cast<QgsRasterLayer*>( layer );
|
||||
if ( rLayer && wcsLayersId.contains( rLayer->id() ) )
|
||||
{
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( !mAccessControl->layerReadPermission( rLayer ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "You are not allowed to access to this coverage" );
|
||||
}
|
||||
#endif
|
||||
|
||||
// RESPONSE_CRS
|
||||
QgsCoordinateReferenceSystem responseCRS = rLayer->crs();
|
||||
crs = mParameters.value( "RESPONSE_CRS", "" );
|
||||
|
@ -36,8 +36,15 @@ class QgsWCSServer: public QgsOWSServer
|
||||
{
|
||||
public:
|
||||
/** Constructor. Takes parameter map and a pointer to a renderer object (does not take ownership)*/
|
||||
QgsWCSServer( const QString& configFilePath, QMap<QString, QString>& parameters, QgsWCSProjectParser* pp,
|
||||
QgsRequestHandler* rh );
|
||||
QgsWCSServer(
|
||||
const QString& configFilePath
|
||||
, QMap<QString, QString>& parameters
|
||||
, QgsWCSProjectParser* pp
|
||||
, QgsRequestHandler* rh
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
);
|
||||
~QgsWCSServer();
|
||||
|
||||
void executeRequest() override;
|
||||
|
@ -20,8 +20,18 @@
|
||||
#include "qgsconfigparserutils.h"
|
||||
#include "qgsmaplayerregistry.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsmapserviceexception.h"
|
||||
#include "qgsaccesscontrol.h"
|
||||
|
||||
QgsWFSProjectParser::QgsWFSProjectParser( const QString& filePath )
|
||||
QgsWFSProjectParser::QgsWFSProjectParser(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* ac
|
||||
#endif
|
||||
)
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
: mAccessControl( ac )
|
||||
#endif
|
||||
{
|
||||
mProjectParser = QgsConfigCache::instance()->serverConfiguration( filePath );
|
||||
}
|
||||
@ -76,6 +86,12 @@ void QgsWFSProjectParser::featureTypeList( QDomElement& parentElement, QDomDocum
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( !mAccessControl->layerReadPermission( layer ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
QgsDebugMsg( QString( "add layer %1 to map" ).arg( layer->id() ) );
|
||||
layerMap.insert( layer->id(), layer );
|
||||
|
||||
@ -331,6 +347,13 @@ void QgsWFSProjectParser::describeFeatureType( const QString& aTypeName, QDomEle
|
||||
if ( !layer )
|
||||
continue;
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( !mAccessControl->layerReadPermission( layer ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString typeName = layer->name();
|
||||
typeName = typeName.replace( " ", "_" );
|
||||
|
||||
|
@ -20,10 +20,21 @@
|
||||
|
||||
#include "qgsserverprojectparser.h"
|
||||
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
class QgsAccessControl;
|
||||
#endif
|
||||
|
||||
|
||||
class SERVER_EXPORT QgsWFSProjectParser
|
||||
{
|
||||
public:
|
||||
QgsWFSProjectParser( const QString& filePath );
|
||||
QgsWFSProjectParser(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* ac
|
||||
#endif
|
||||
);
|
||||
~QgsWFSProjectParser();
|
||||
|
||||
void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
|
||||
@ -45,6 +56,9 @@ class SERVER_EXPORT QgsWFSProjectParser
|
||||
|
||||
private:
|
||||
QgsServerProjectParser* mProjectParser;
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
const QgsAccessControl* mAccessControl;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // QGSWFSPROJECTPARSER_H
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "qgscomposerlegenditem.h"
|
||||
#include "qgsrequesthandler.h"
|
||||
#include "qgsogcutils.h"
|
||||
#include "qgsaccesscontrol.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
@ -65,16 +66,37 @@ static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
|
||||
static const QString OGC_NAMESPACE = "http://www.opengis.net/ogc";
|
||||
static const QString QGS_NAMESPACE = "http://www.qgis.org/gml";
|
||||
|
||||
QgsWFSServer::QgsWFSServer( const QString& configFilePath, QMap<QString, QString> ¶meters, QgsWFSProjectParser* cp,
|
||||
QgsRequestHandler* rh )
|
||||
: QgsOWSServer( configFilePath, parameters, rh )
|
||||
QgsWFSServer::QgsWFSServer(
|
||||
const QString& configFilePath
|
||||
, QMap<QString, QString> ¶meters
|
||||
, QgsWFSProjectParser* cp
|
||||
, QgsRequestHandler* rh
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
)
|
||||
: QgsOWSServer(
|
||||
configFilePath
|
||||
, parameters
|
||||
, rh
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
)
|
||||
, mWithGeom( true )
|
||||
, mConfigParser( cp )
|
||||
{
|
||||
}
|
||||
|
||||
QgsWFSServer::QgsWFSServer()
|
||||
: QgsOWSServer( QString(), QMap<QString, QString>(), 0 )
|
||||
: QgsOWSServer(
|
||||
QString()
|
||||
, QMap<QString, QString>()
|
||||
, 0
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, NULL
|
||||
#endif
|
||||
)
|
||||
, mWithGeom( true )
|
||||
, mConfigParser( 0 )
|
||||
{
|
||||
@ -438,6 +460,16 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
|
||||
QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( currentLayer );
|
||||
if ( layer && wfsLayersId.contains( layer->id() ) )
|
||||
{
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( !mAccessControl->layerReadPermission( currentLayer ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "Feature access permission denied" );
|
||||
}
|
||||
|
||||
QMap<QString, QString> originalLayerFilters;
|
||||
applyAccessControlLayerFilters( currentLayer, originalLayerFilters );
|
||||
#endif
|
||||
|
||||
expressionContext << QgsExpressionContextUtils::layerScope( layer );
|
||||
|
||||
//is there alias info for this vector layer?
|
||||
@ -513,10 +545,21 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
|
||||
, searchRect.yMaximum() + 1. / pow( 10., layerPrec ) );
|
||||
layerCrs = layer->crs();
|
||||
|
||||
QgsFeatureIterator fit = layer->getFeatures(
|
||||
QgsFeatureRequest()
|
||||
.setFlags( QgsFeatureRequest::ExactIntersect | ( mWithGeom ? QgsFeatureRequest::NoFlags : QgsFeatureRequest::NoGeometry ) )
|
||||
.setSubsetOfAttributes( attrIndexes ) );
|
||||
QgsFeatureRequest fReq;
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
fReq.setFlags( QgsFeatureRequest::ExactIntersect | ( mWithGeom ? QgsFeatureRequest::NoFlags : QgsFeatureRequest::NoGeometry ) );
|
||||
mAccessControl->filterFeatures( layer, fReq );
|
||||
|
||||
QStringList attributes = QStringList();
|
||||
foreach( int idx, attrIndexes ) {
|
||||
attributes.append( layer->pendingFields().field(idx).name() );
|
||||
}
|
||||
fReq.setSubsetOfAttributes(
|
||||
mAccessControl->layerAttributes( layer, attributes ),
|
||||
layer->pendingFields() );
|
||||
#endif
|
||||
|
||||
QgsFeatureIterator fit = layer->getFeatures( fReq );
|
||||
|
||||
long featCounter = 0;
|
||||
QDomNodeList filterNodes = queryElem.elementsByTagName( "Filter" );
|
||||
@ -634,6 +677,10 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
|
||||
++featureCounter;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
restoreLayerFilters( originalLayerFilters );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1394,12 +1441,37 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
|
||||
// it's a vectorlayer and defined by the administrator as a WFS layer
|
||||
if ( layer && wfsLayersId.contains( layer->id() ) )
|
||||
{
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( actionName == "Insert" )
|
||||
{
|
||||
if ( !mAccessControl->layerInsertPermission( layer ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "Feature insert permission denied" );
|
||||
}
|
||||
}
|
||||
else if ( actionName == "Update" )
|
||||
{
|
||||
if ( !mAccessControl->layerUpdatePermission( layer ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "Feature update permission denied" );
|
||||
}
|
||||
}
|
||||
else if ( actionName == "Delete" )
|
||||
{
|
||||
if ( !mAccessControl->layerDeletePermission( layer ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "Feature delete permission denied" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get the provider and it's capabilities
|
||||
QgsVectorDataProvider* provider = layer->dataProvider();
|
||||
if ( !provider )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int cap = provider->capabilities();
|
||||
|
||||
// Start the update transaction
|
||||
@ -1459,6 +1531,18 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
|
||||
QgsFeatureIds::const_iterator fidIt = fids.constBegin();
|
||||
for ( ; fidIt != fids.constEnd(); ++fidIt )
|
||||
{
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
QgsFeatureIterator fit = layer->getFeatures(QgsFeatureRequest( *fidIt ) );
|
||||
QgsFeature feature;
|
||||
while ( fit.nextFeature( feature ) )
|
||||
{
|
||||
if ( !mAccessControl->allowToEdit( layer, feature ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "Feature modify permission denied" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QMap< QString, QString >::const_iterator it = propertyMap.constBegin();
|
||||
for ( ; it != propertyMap.constEnd(); ++it )
|
||||
{
|
||||
@ -1482,6 +1566,18 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
|
||||
if ( !layer->changeGeometry( *fidIt, QgsOgcUtils::geometryFromGML( geometryElem ) ) )
|
||||
throw QgsMapServiceException( "RequestNotWellFormed", "Error in change geometry" );
|
||||
}
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
fit = layer->getFeatures(QgsFeatureRequest( *fidIt ) );
|
||||
while ( fit.nextFeature( feature ) )
|
||||
{
|
||||
if ( !mAccessControl->allowToEdit( layer, feature ) )
|
||||
{
|
||||
layer->rollBack();
|
||||
throw QgsMapServiceException( "Security", "Feature modify permission denied" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1512,6 +1608,23 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
|
||||
QDomElement filterElem = actionElem.firstChild().toElement();
|
||||
// Get Feature Ids for the Filter element
|
||||
QgsFeatureIds fids = getFeatureIdsFromFilter( filterElem, layer );
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
QgsFeatureIds::const_iterator fidIt = fids.constBegin();
|
||||
for ( ; fidIt != fids.constEnd(); ++fidIt )
|
||||
{
|
||||
QgsFeatureIterator fit = layer->getFeatures(QgsFeatureRequest( *fidIt ) );
|
||||
QgsFeature feature;
|
||||
while ( fit.nextFeature( feature ) )
|
||||
{
|
||||
if ( !mAccessControl->allowToEdit( layer, feature ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "Feature modify permission denied" );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
layer->setSelectedFeatures( fids );
|
||||
layer->deleteSelectedFeatures();
|
||||
}
|
||||
@ -1595,6 +1708,18 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
QgsFeatureList::iterator featureIt = inFeatList.begin();
|
||||
while ( featureIt != inFeatList.end() )
|
||||
{
|
||||
if ( !mAccessControl->allowToEdit( layer, *featureIt) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "Feature modify permission denied" );
|
||||
}
|
||||
featureIt++;
|
||||
}
|
||||
#endif
|
||||
|
||||
// add the features
|
||||
if ( !provider->addFeatures( inFeatList ) )
|
||||
{
|
||||
|
@ -60,8 +60,15 @@ class QgsWFSServer: public QgsOWSServer
|
||||
{
|
||||
public:
|
||||
/** Constructor. Takes parameter map and a pointer to a renderer object (does not take ownership)*/
|
||||
QgsWFSServer( const QString& configFilePath, QMap<QString, QString>& parameters, QgsWFSProjectParser* cp,
|
||||
QgsRequestHandler* rh );
|
||||
QgsWFSServer(
|
||||
const QString& configFilePath
|
||||
, QMap<QString, QString>& parameters
|
||||
, QgsWFSProjectParser* cp
|
||||
, QgsRequestHandler* rh
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
);
|
||||
~QgsWFSServer();
|
||||
|
||||
void executeRequest() override;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "qgscomposershape.h"
|
||||
#include "qgslayertreegroup.h"
|
||||
#include "qgslayertreelayer.h"
|
||||
#include "qgsaccesscontrol.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QTextDocument>
|
||||
@ -48,8 +49,16 @@
|
||||
// this implies that a layer style called "default" will not be usable in WMS server
|
||||
#define EMPTY_STYLE_NAME "default"
|
||||
|
||||
QgsWMSProjectParser::QgsWMSProjectParser( const QString& filePath )
|
||||
QgsWMSProjectParser::QgsWMSProjectParser(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
)
|
||||
: QgsWMSConfigParser()
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, mAccessControl( accessControl )
|
||||
#endif
|
||||
{
|
||||
mProjectParser = QgsConfigCache::instance()->serverConfiguration( filePath );
|
||||
mLegendLayerFont.fromString( mProjectParser->firstComposerLegendElement().attribute( "layerFont" ) );
|
||||
@ -185,7 +194,12 @@ QList<QgsMapLayer*> QgsWMSProjectParser::mapLayerFromStyle( const QString& lName
|
||||
if ( legendIt->attribute( "embedded" ) == "1" )
|
||||
{
|
||||
QString project = mProjectParser->convertToAbsolutePath( legendIt->attribute( "project" ) );
|
||||
QgsWMSProjectParser* p = dynamic_cast<QgsWMSProjectParser*>( QgsConfigCache::instance()->wmsConfiguration( project ) );
|
||||
QgsWMSProjectParser* p = dynamic_cast<QgsWMSProjectParser*>( QgsConfigCache::instance()->wmsConfiguration(
|
||||
project
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, mAccessControl
|
||||
#endif
|
||||
) );
|
||||
if ( p )
|
||||
{
|
||||
QgsServerProjectParser* pp = p->mProjectParser;
|
||||
@ -229,7 +243,12 @@ void QgsWMSProjectParser::addLayersFromGroup( const QDomElement& legendGroupElem
|
||||
int drawingOrder = mProjectParser->updateLegendDrawingOrder() ? legendGroupElem.attribute( "drawingOrder", "-1" ).toInt() : -1;
|
||||
|
||||
QString project = mProjectParser->convertToAbsolutePath( legendGroupElem.attribute( "project" ) );
|
||||
QgsWMSProjectParser* p = dynamic_cast<QgsWMSProjectParser*>( QgsConfigCache::instance()->wmsConfiguration( project ) );
|
||||
QgsWMSProjectParser* p = dynamic_cast<QgsWMSProjectParser*>( QgsConfigCache::instance()->wmsConfiguration(
|
||||
project
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, mAccessControl
|
||||
#endif
|
||||
) );
|
||||
if ( p )
|
||||
{
|
||||
QgsServerProjectParser* pp = p->mProjectParser;
|
||||
@ -945,7 +964,12 @@ void QgsWMSProjectParser::addLayers( QDomDocument &doc,
|
||||
QString project = mProjectParser->convertToAbsolutePath( currentChildElem.attribute( "project" ) );
|
||||
QgsDebugMsg( QString( "Project path: %1" ).arg( project ) );
|
||||
QString embeddedGroupName = currentChildElem.attribute( "name" );
|
||||
QgsWMSProjectParser* p = dynamic_cast<QgsWMSProjectParser*>( QgsConfigCache::instance()->wmsConfiguration( project ) );
|
||||
QgsWMSProjectParser* p = dynamic_cast<QgsWMSProjectParser*>( QgsConfigCache::instance()->wmsConfiguration(
|
||||
project
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, mAccessControl
|
||||
#endif
|
||||
) );
|
||||
if ( p )
|
||||
{
|
||||
QgsServerProjectParser* pp = p->mProjectParser;
|
||||
@ -1001,6 +1025,13 @@ void QgsWMSProjectParser::addLayers( QDomDocument &doc,
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( !mAccessControl->layerReadPermission( currentLayer ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
// queryable layer
|
||||
if ( nonIdentifiableLayers.contains( currentLayer->id() ) )
|
||||
{
|
||||
@ -1273,7 +1304,12 @@ void QgsWMSProjectParser::addOWSLayers( QDomDocument &doc,
|
||||
QString project = mProjectParser->convertToAbsolutePath( currentChildElem.attribute( "project" ) );
|
||||
QgsDebugMsg( QString( "Project path: %1" ).arg( project ) );
|
||||
QString embeddedGroupName = currentChildElem.attribute( "name" );
|
||||
QgsWMSProjectParser* p = dynamic_cast<QgsWMSProjectParser*>( QgsConfigCache::instance()->wmsConfiguration( project ) );
|
||||
QgsWMSProjectParser* p = dynamic_cast<QgsWMSProjectParser*>( QgsConfigCache::instance()->wmsConfiguration(
|
||||
project
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, mAccessControl
|
||||
#endif
|
||||
) );
|
||||
if ( p )
|
||||
{
|
||||
QgsServerProjectParser* pp = p->mProjectParser;
|
||||
@ -1640,6 +1676,14 @@ QDomDocument QgsWMSProjectParser::describeLayer( QStringList& layerList, const Q
|
||||
for ( int j = 0; j < currentLayerList.size(); j++ )
|
||||
{
|
||||
QgsMapLayer* currentLayer = currentLayerList.at( j );
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( !mAccessControl->layerReadPermission( currentLayer ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "You are not allowed to access to this layer" );
|
||||
}
|
||||
#endif
|
||||
|
||||
QString layerTypeName = mProjectParser->useLayerIDs() ? currentLayer->id() : currentLayer->name();
|
||||
|
||||
// Create the NamedLayer element
|
||||
|
@ -22,13 +22,22 @@
|
||||
#include "qgsserverprojectparser.h"
|
||||
#include "qgslayertreegroup.h"
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
class QgsAccessControl;
|
||||
#endif
|
||||
|
||||
class QTextDocument;
|
||||
class QSvgRenderer;
|
||||
|
||||
class SERVER_EXPORT QgsWMSProjectParser : public QgsWMSConfigParser
|
||||
{
|
||||
public:
|
||||
QgsWMSProjectParser( const QString& filePath );
|
||||
QgsWMSProjectParser(
|
||||
const QString& filePath
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
);
|
||||
virtual ~QgsWMSProjectParser();
|
||||
|
||||
/** Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.
|
||||
@ -114,6 +123,9 @@ class SERVER_EXPORT QgsWMSProjectParser : public QgsWMSConfigParser
|
||||
|
||||
private:
|
||||
QgsServerProjectParser* mProjectParser;
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
const QgsAccessControl* mAccessControl;
|
||||
#endif
|
||||
|
||||
mutable QFont mLegendLayerFont;
|
||||
mutable QFont mLegendItemFont;
|
||||
|
@ -48,6 +48,8 @@
|
||||
#include "qgsfeature.h"
|
||||
#include "qgseditorwidgetregistry.h"
|
||||
#include "qgsserverstreamingdevice.h"
|
||||
#include "qgsaccesscontrol.h"
|
||||
#include "qgsfeaturerequest.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
@ -64,9 +66,25 @@
|
||||
#include <QUrl>
|
||||
#include <QPaintEngine>
|
||||
|
||||
QgsWMSServer::QgsWMSServer( const QString& configFilePath, QMap<QString, QString> ¶meters, QgsWMSConfigParser* cp,
|
||||
QgsRequestHandler* rh, QgsMapRenderer* renderer, QgsCapabilitiesCache* capCache )
|
||||
: QgsOWSServer( configFilePath, parameters, rh )
|
||||
QgsWMSServer::QgsWMSServer(
|
||||
const QString& configFilePath
|
||||
, QMap<QString, QString> ¶meters
|
||||
, QgsWMSConfigParser* cp
|
||||
, QgsRequestHandler* rh
|
||||
, QgsMapRenderer* renderer
|
||||
, QgsCapabilitiesCache* capCache
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
)
|
||||
: QgsOWSServer(
|
||||
configFilePath
|
||||
, parameters
|
||||
, rh
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, accessControl
|
||||
#endif
|
||||
)
|
||||
, mMapRenderer( renderer )
|
||||
, mCapabilitiesCache( capCache )
|
||||
, mConfigParser( cp )
|
||||
@ -74,10 +92,20 @@ QgsWMSServer::QgsWMSServer( const QString& configFilePath, QMap<QString, QString
|
||||
, mDrawLegendLayerLabel( true )
|
||||
, mDrawLegendItemLabel( true )
|
||||
{
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
mMapRenderer->setFeatureFilterProvider( mAccessControl );
|
||||
#endif
|
||||
}
|
||||
|
||||
QgsWMSServer::QgsWMSServer()
|
||||
: QgsOWSServer( QString(), QMap<QString, QString>(), 0 )
|
||||
: QgsOWSServer(
|
||||
QString()
|
||||
, QMap<QString, QString>()
|
||||
, 0
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, NULL
|
||||
#endif
|
||||
)
|
||||
, mMapRenderer( 0 )
|
||||
, mCapabilitiesCache()
|
||||
, mConfigParser( 0 )
|
||||
@ -129,7 +157,14 @@ void QgsWMSServer::executeRequest()
|
||||
//GetCapabilities
|
||||
if ( request.compare( "GetCapabilities", Qt::CaseInsensitive ) == 0 || getProjectSettings )
|
||||
{
|
||||
const QDomDocument* capabilitiesDocument = mCapabilitiesCache->searchCapabilitiesDocument( mConfigFilePath, getProjectSettings ? "projectSettings" : version );
|
||||
QStringList cacheKeyList;
|
||||
cacheKeyList << (getProjectSettings ? "projectSettings" : version);
|
||||
bool cache = true;
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
cache = mAccessControl->fillCacheKey( cacheKeyList );
|
||||
#endif
|
||||
QString cacheKey = cacheKeyList.join( "-" );
|
||||
const QDomDocument* capabilitiesDocument = mCapabilitiesCache->searchCapabilitiesDocument( mConfigFilePath, cacheKey );
|
||||
if ( !capabilitiesDocument ) //capabilities xml not in cache. Create a new one
|
||||
{
|
||||
QgsMessageLog::logMessage( "Capabilities document not found in cache" );
|
||||
@ -144,8 +179,16 @@ void QgsWMSServer::executeRequest()
|
||||
cleanupAfterRequest();
|
||||
return;
|
||||
}
|
||||
mCapabilitiesCache->insertCapabilitiesDocument( mConfigFilePath, getProjectSettings ? "projectSettings" : version, &doc );
|
||||
capabilitiesDocument = mCapabilitiesCache->searchCapabilitiesDocument( mConfigFilePath, getProjectSettings ? "projectSettings" : version );
|
||||
if ( cache )
|
||||
{
|
||||
mCapabilitiesCache->insertCapabilitiesDocument( mConfigFilePath, cacheKey, &doc );
|
||||
capabilitiesDocument = mCapabilitiesCache->searchCapabilitiesDocument( mConfigFilePath, cacheKey );
|
||||
}
|
||||
else
|
||||
{
|
||||
doc = doc.cloneNode().toDocument();
|
||||
capabilitiesDocument = &doc;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -857,6 +900,14 @@ QImage* QgsWMSServer::getLegendGraphics()
|
||||
if ( QgsLayerTree::isLayer( node ) )
|
||||
{
|
||||
QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( !mAccessControl->layerReadPermission( nodeLayer->layer() ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "You are not allowed to access to the layer: " + nodeLayer->layer()->name() );
|
||||
}
|
||||
#endif
|
||||
|
||||
// layer titles - hidden or not
|
||||
QgsLegendRenderer::setNodeLegendStyle( nodeLayer, mDrawLegendLayerLabel ? QgsComposerLegendStyle::Subgroup : QgsComposerLegendStyle::Hidden );
|
||||
|
||||
@ -1177,6 +1228,19 @@ QByteArray* QgsWMSServer::getPrint( const QString& formatString )
|
||||
delete theImage;
|
||||
|
||||
QMap<QString, QString> originalLayerFilters = applyRequestedLayerFilters( layersList );
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
foreach ( QgsMapLayer *layer, QgsMapLayerRegistry::instance()->mapLayers() )
|
||||
{
|
||||
if ( !mAccessControl->layerReadPermission( layer ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "You are not allowed to access to the layer: " + layer->name() );
|
||||
}
|
||||
}
|
||||
|
||||
applyAccessControlLayersFilters( layersList, originalLayerFilters );
|
||||
#endif
|
||||
|
||||
QStringList selectedLayerIdList = applyFeatureSelections( layersList );
|
||||
|
||||
//GetPrint request needs a template parameter
|
||||
@ -1298,6 +1362,19 @@ QImage* QgsWMSServer::getMap( HitTest* hitTest )
|
||||
thePainter.setRenderHint( QPainter::Antialiasing ); //make it look nicer
|
||||
|
||||
QMap<QString, QString> originalLayerFilters = applyRequestedLayerFilters( layersList );
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
foreach ( QgsMapLayer *layer, QgsMapLayerRegistry::instance()->mapLayers() )
|
||||
{
|
||||
if ( !mAccessControl->layerReadPermission( layer ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "You are not allowed to access to the layer: " + layer->name() );
|
||||
}
|
||||
}
|
||||
|
||||
applyAccessControlLayersFilters( layersList, originalLayerFilters );
|
||||
#endif
|
||||
|
||||
QStringList selectedLayerIdList = applyFeatureSelections( layersList );
|
||||
|
||||
QList< QPair< QgsVectorLayer*, QgsFeatureRendererV2*> > bkVectorRenderers;
|
||||
@ -1310,7 +1387,9 @@ QImage* QgsWMSServer::getMap( HitTest* hitTest )
|
||||
if ( hitTest )
|
||||
runHitTest( &thePainter, *hitTest );
|
||||
else
|
||||
{
|
||||
mMapRenderer->render( &thePainter );
|
||||
}
|
||||
|
||||
if ( mConfigParser )
|
||||
{
|
||||
@ -1518,6 +1597,9 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, const QString& version )
|
||||
//get the layer registered in QgsMapLayerRegistry and apply possible filters
|
||||
QStringList layerIds = layerSet( layersList, stylesList, mMapRenderer->destinationCrs() );
|
||||
QMap<QString, QString> originalLayerFilters = applyRequestedLayerFilters( layersList );
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
applyAccessControlLayersFilters( layersList, originalLayerFilters );
|
||||
#endif
|
||||
|
||||
QDomElement getFeatureInfoElement;
|
||||
QString infoFormat = mParameters.value( "INFO_FORMAT" );
|
||||
@ -1595,6 +1677,13 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, const QString& version )
|
||||
currentLayer = registeredMapLayer;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
if ( !mAccessControl->layerReadPermission( currentLayer ) )
|
||||
{
|
||||
throw QgsMapServiceException( "Security", "You are not allowed to access to the layer: " + currentLayer->name() );
|
||||
}
|
||||
#endif
|
||||
|
||||
//skip layer if not visible at current map scale
|
||||
bool useScaleConstraint = ( scaleDenominator > 0 && currentLayer->hasScaleBasedVisibility() );
|
||||
if ( useScaleConstraint && ( currentLayer->minimumScale() > scaleDenominator || currentLayer->maximumScale() < scaleDenominator ) )
|
||||
@ -2055,10 +2144,36 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
|
||||
QgsFeatureRequest fReq;
|
||||
bool hasGeometry = addWktGeometry || featureBBox;
|
||||
fReq.setFlags((( hasGeometry ) ? QgsFeatureRequest::NoFlags : QgsFeatureRequest::NoGeometry ) | QgsFeatureRequest::ExactIntersect );
|
||||
if ( !searchRect.isEmpty() )
|
||||
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
mAccessControl->filterFeatures( layer, fReq );
|
||||
if ( ! searchRect.isEmpty() )
|
||||
{
|
||||
if ( fReq.filterExpression() != NULL )
|
||||
{
|
||||
fReq.setFilterExpression( QString("intersects( $geometry , geomFromWKT( '%1' ) ) AND ( %2 )").
|
||||
arg( searchRect.asWktPolygon() ).arg( fReq.filterExpression()->expression() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
fReq.setFilterRect( searchRect );
|
||||
}
|
||||
}
|
||||
|
||||
QStringList attributes;
|
||||
QgsField field;
|
||||
foreach( field, layer->pendingFields().toList() ) {
|
||||
attributes.append( field.name() );
|
||||
}
|
||||
attributes = mAccessControl->layerAttributes( layer, attributes );
|
||||
fReq.setSubsetOfAttributes( attributes, layer->pendingFields() );
|
||||
#else
|
||||
if ( ! searchRect.isEmpty() )
|
||||
{
|
||||
fReq.setFilterRect( searchRect );
|
||||
}
|
||||
#endif
|
||||
|
||||
QgsFeatureIterator fit = layer->getFeatures( fReq );
|
||||
|
||||
bool featureBBoxInitialized = false;
|
||||
@ -2115,7 +2230,13 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
|
||||
{
|
||||
bool withGeom = layer->wkbType() != QGis::WKBNoGeometry && addWktGeometry;
|
||||
int version = infoFormat.startsWith( "application/vnd.ogc.gml/3" ) ? 3 : 2;
|
||||
QDomElement elem = createFeatureGML( &feature, layer, infoDocument, outputCrs, mConfigParser && mConfigParser->useLayerIDs() ? layer->id() : layer->name(), withGeom, version );
|
||||
QString typeName = mConfigParser && mConfigParser->useLayerIDs() ? layer->id() : layer->name();
|
||||
QDomElement elem = createFeatureGML(
|
||||
&feature, layer, infoDocument, outputCrs, typeName, withGeom, version
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, &attributes
|
||||
#endif
|
||||
);
|
||||
QDomElement featureMemberElem = infoDocument.createElement( "gml:featureMember"/*wfs:FeatureMember*/ );
|
||||
featureMemberElem.appendChild( elem );
|
||||
layerElement.appendChild( featureMemberElem );
|
||||
@ -2136,6 +2257,13 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
//skip attribute if it is excluded by access control
|
||||
if ( !attributes.contains( fields[i].name() ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
//replace attribute name if there is an attribute alias?
|
||||
QString attributeName = layer->attributeDisplayName( i );
|
||||
@ -2249,7 +2377,9 @@ int QgsWMSServer::featureInfoFromRasterLayer( QgsRasterLayer* layer,
|
||||
|
||||
QgsCoordinateReferenceSystem layerCrs = layer->crs();
|
||||
int version = infoFormat.startsWith( "application/vnd.ogc.gml/3" ) ? 3 : 2;
|
||||
QDomElement elem = createFeatureGML( &feature, 0, infoDocument, layerCrs, mConfigParser && mConfigParser->useLayerIDs() ? layer->id() : layer->name(), false, version );
|
||||
QString typeName = mConfigParser && mConfigParser->useLayerIDs() ? layer->id() : layer->name();
|
||||
QDomElement elem = createFeatureGML(
|
||||
&feature, 0, infoDocument, layerCrs, typeName, false, version, NULL );
|
||||
layerElement.appendChild( elem );
|
||||
}
|
||||
else
|
||||
@ -2417,22 +2547,17 @@ QMap<QString, QString> QgsWMSServer::applyRequestedLayerFilters( const QStringLi
|
||||
return filterMap;
|
||||
}
|
||||
|
||||
void QgsWMSServer::restoreLayerFilters( const QMap < QString, QString >& filterMap ) const
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
void QgsWMSServer::applyAccessControlLayersFilters( const QStringList& layerList, QMap<QString, QString>& originalLayerFilters ) const
|
||||
{
|
||||
QMap < QString, QString >::const_iterator filterIt = filterMap.constBegin();
|
||||
for ( ; filterIt != filterMap.constEnd(); ++filterIt )
|
||||
{
|
||||
QgsVectorLayer* filteredLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( filterIt.key() ) );
|
||||
if ( filteredLayer )
|
||||
{
|
||||
QgsVectorDataProvider* dp = filteredLayer->dataProvider();
|
||||
if ( dp )
|
||||
{
|
||||
dp->setSubsetString( filterIt.value() );
|
||||
}
|
||||
foreach ( QString layerName, layerList ) {
|
||||
QList<QgsMapLayer*> mapLayers = QgsMapLayerRegistry::instance()->mapLayersByName( layerName );
|
||||
foreach ( QgsMapLayer* mapLayer, mapLayers ) {
|
||||
applyAccessControlLayerFilters(mapLayer, originalLayerFilters);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool QgsWMSServer::testFilterStringSafety( const QString& filter ) const
|
||||
{
|
||||
@ -2986,7 +3111,8 @@ QDomElement QgsWMSServer::createFeatureGML(
|
||||
QgsCoordinateReferenceSystem& crs,
|
||||
const QString& typeName,
|
||||
bool withGeom,
|
||||
int version ) const
|
||||
int version,
|
||||
QStringList* attributes) const
|
||||
{
|
||||
//qgs:%TYPENAME%
|
||||
QDomElement typeNameElement = doc.createElement( "qgs:" + typeName /*qgs:%TYPENAME%*/ );
|
||||
@ -3085,6 +3211,12 @@ QDomElement QgsWMSServer::createFeatureGML(
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//skip attribute if it is excluded by access control
|
||||
if ( attributes != NULL && !attributes->contains( attributeName ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QDomElement fieldElem = doc.createElement( "qgs:" + attributeName.replace( QString( " " ), QString( "_" ) ) );
|
||||
QString fieldTextString = featureAttributes[i].toString();
|
||||
if ( layer )
|
||||
|
@ -44,6 +44,8 @@ class QgsRenderContext;
|
||||
class QgsVectorLayer;
|
||||
class QgsSymbol;
|
||||
class QgsSymbolV2;
|
||||
class QgsAccessControl;
|
||||
|
||||
class QColor;
|
||||
class QFile;
|
||||
class QFont;
|
||||
@ -61,8 +63,17 @@ class QgsWMSServer: public QgsOWSServer
|
||||
public:
|
||||
/** Constructor. Does _NOT_ take ownership of
|
||||
QgsConfigParser, QgsCapabilitiesCache and QgsMapRenderer*/
|
||||
QgsWMSServer( const QString& configFilePath, QMap<QString, QString> ¶meters, QgsWMSConfigParser* cp, QgsRequestHandler* rh,
|
||||
QgsMapRenderer* renderer, QgsCapabilitiesCache* capCache );
|
||||
QgsWMSServer(
|
||||
const QString& configFilePath
|
||||
, QMap<QString, QString> ¶meters
|
||||
, QgsWMSConfigParser* cp
|
||||
, QgsRequestHandler* rh
|
||||
, QgsMapRenderer* renderer
|
||||
, QgsCapabilitiesCache* capCache
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
, const QgsAccessControl* accessControl
|
||||
#endif
|
||||
);
|
||||
~QgsWMSServer();
|
||||
|
||||
void executeRequest() override;
|
||||
@ -178,8 +189,13 @@ class QgsWMSServer: public QgsOWSServer
|
||||
/** Apply filter (subset) strings from the request to the layers. Example: '&FILTER=<layer1>:"AND property > 100",<layer2>:"AND bla = 'hallo!'" '
|
||||
@return a map with the original filters ( layer id / filter string )*/
|
||||
QMap<QString, QString> applyRequestedLayerFilters( const QStringList& layerList ) const;
|
||||
/** Restores the original layer filters*/
|
||||
void restoreLayerFilters( const QMap < QString, QString >& filterMap ) const;
|
||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||
/** Apply filter strings from the access control to the layers.
|
||||
* @param layerList layers to filter
|
||||
* @param originalLayerFilters the original layers filter dictionary
|
||||
*/
|
||||
void applyAccessControlLayersFilters( const QStringList& layerList, QMap<QString, QString>& originalLayerFilters ) const;
|
||||
#endif
|
||||
/** Tests if a filter sql string is allowed (safe)
|
||||
@return true in case of success, false if string seems unsafe*/
|
||||
bool testFilterStringSafety( const QString& filter ) const;
|
||||
@ -236,13 +252,15 @@ class QgsWMSServer: public QgsOWSServer
|
||||
bool mDrawLegendLayerLabel;
|
||||
bool mDrawLegendItemLabel;
|
||||
|
||||
QDomElement createFeatureGML( QgsFeature* feat,
|
||||
QgsVectorLayer* layer,
|
||||
QDomDocument& doc,
|
||||
QgsCoordinateReferenceSystem& crs,
|
||||
const QString& typeName,
|
||||
bool withGeom,
|
||||
int version ) const;
|
||||
QDomElement createFeatureGML(
|
||||
QgsFeature* feat,
|
||||
QgsVectorLayer* layer,
|
||||
QDomDocument& doc,
|
||||
QgsCoordinateReferenceSystem& crs,
|
||||
const QString& typeName,
|
||||
bool withGeom,
|
||||
int version,
|
||||
QStringList* attributes=NULL) const;
|
||||
|
||||
/** Replaces attribute value with ValueRelation or ValueRelation if defined. Otherwise returns the original value*/
|
||||
static QString replaceValueMapAndRelation( QgsVectorLayer* vl, int idx, const QString& attributeVal );
|
||||
|
@ -93,4 +93,5 @@ ENDIF (WITH_APIDOC)
|
||||
|
||||
IF (WITH_SERVER)
|
||||
ADD_PYTHON_TEST(PyQgsServer test_qgsserver.py)
|
||||
ADD_PYTHON_TEST(PyQgsServerAccessControl test_qgsserver_accesscontrol.py)
|
||||
ENDIF (WITH_SERVER)
|
||||
|
1056
tests/src/python/test_qgsserver_accesscontrol.py
Normal file
1056
tests/src/python/test_qgsserver_accesscontrol.py
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
tests/testdata/control_images/qgis_server_accesscontrol/WMS_GetMap/WMS_GetMap.png
vendored
Normal file
BIN
tests/testdata/control_images/qgis_server_accesscontrol/WMS_GetMap/WMS_GetMap.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
58
tests/testdata/qgis_server_accesscontrol/Country.qml
vendored
Normal file
58
tests/testdata/qgis_server_accesscontrol/Country.qml
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
|
||||
<qgis version="1.8.0-Trunk" minimumScale="0" maximumScale="1e+08" hasScaleBasedVisibilityFlag="0">
|
||||
<transparencyLevelInt>255</transparencyLevelInt>
|
||||
<renderer-v2 symbollevels="0" type="singleSymbol">
|
||||
<symbols>
|
||||
<symbol outputUnit="MM" alpha="1" type="fill" name="0">
|
||||
<layer pass="0" class="SimpleFill" locked="0">
|
||||
<prop k="color" v="145,149,158,255"/>
|
||||
<prop k="color_border" v="157,157,157,255"/>
|
||||
<prop k="offset" v="2,2"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<prop k="style_border" v="solid"/>
|
||||
<prop k="width_border" v="0.26"/>
|
||||
</layer>
|
||||
<layer pass="0" class="SimpleFill" locked="0">
|
||||
<prop k="color" v="0,0,255,255"/>
|
||||
<prop k="color_border" v="0,0,0,255"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<prop k="style_border" v="solid"/>
|
||||
<prop k="width_border" v="0.26"/>
|
||||
</layer>
|
||||
</symbol>
|
||||
</symbols>
|
||||
<rotation field=""/>
|
||||
<sizescale field=""/>
|
||||
</renderer-v2>
|
||||
<customproperties/>
|
||||
<displayfield>name</displayfield>
|
||||
<label>0</label>
|
||||
<labelattributes>
|
||||
<label fieldname="" text="Label"/>
|
||||
<family fieldname="" name="Ubuntu"/>
|
||||
<size fieldname="" units="pt" value="12"/>
|
||||
<bold fieldname="" on="0"/>
|
||||
<italic fieldname="" on="0"/>
|
||||
<underline fieldname="" on="0"/>
|
||||
<strikeout fieldname="" on="0"/>
|
||||
<color fieldname="" red="0" blue="0" green="0"/>
|
||||
<x fieldname=""/>
|
||||
<y fieldname=""/>
|
||||
<offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
|
||||
<angle fieldname="" value="0" auto="0"/>
|
||||
<alignment fieldname="" value="center"/>
|
||||
<buffercolor fieldname="" red="255" blue="255" green="255"/>
|
||||
<buffersize fieldname="" units="pt" value="1"/>
|
||||
<bufferenabled fieldname="" on=""/>
|
||||
<multilineenabled fieldname="" on=""/>
|
||||
<selectedonly on=""/>
|
||||
</labelattributes>
|
||||
<edittypes>
|
||||
<edittype type="0" name="name"/>
|
||||
</edittypes>
|
||||
<editform>.</editform>
|
||||
<editforminit></editforminit>
|
||||
<annotationform>.</annotationform>
|
||||
<attributeactions/>
|
||||
</qgis>
|
59
tests/testdata/qgis_server_accesscontrol/Hello.qml
vendored
Normal file
59
tests/testdata/qgis_server_accesscontrol/Hello.qml
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
|
||||
<qgis version="1.8.0-Trunk" minimumScale="0" maximumScale="1e+08" hasScaleBasedVisibilityFlag="0">
|
||||
<transparencyLevelInt>255</transparencyLevelInt>
|
||||
<renderer-v2 symbollevels="0" type="singleSymbol">
|
||||
<symbols>
|
||||
<symbol outputUnit="MM" alpha="1" type="fill" name="0">
|
||||
<layer pass="0" class="SimpleFill" locked="0">
|
||||
<prop k="color" v="174,176,194,255"/>
|
||||
<prop k="color_border" v="121,121,121,255"/>
|
||||
<prop k="offset" v="2,2"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<prop k="style_border" v="solid"/>
|
||||
<prop k="width_border" v="0.26"/>
|
||||
</layer>
|
||||
<layer pass="0" class="SimpleFill" locked="0">
|
||||
<prop k="color" v="224,15,183,255"/>
|
||||
<prop k="color_border" v="0,0,0,255"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<prop k="style_border" v="solid"/>
|
||||
<prop k="width_border" v="0.26"/>
|
||||
</layer>
|
||||
</symbol>
|
||||
</symbols>
|
||||
<rotation field=""/>
|
||||
<sizescale field=""/>
|
||||
</renderer-v2>
|
||||
<customproperties/>
|
||||
<displayfield>pkuid</displayfield>
|
||||
<label>0</label>
|
||||
<labelattributes>
|
||||
<label fieldname="" text="Label"/>
|
||||
<family fieldname="" name="Ubuntu"/>
|
||||
<size fieldname="" units="pt" value="12"/>
|
||||
<bold fieldname="" on="0"/>
|
||||
<italic fieldname="" on="0"/>
|
||||
<underline fieldname="" on="0"/>
|
||||
<strikeout fieldname="" on="0"/>
|
||||
<color fieldname="" red="0" blue="0" green="0"/>
|
||||
<x fieldname=""/>
|
||||
<y fieldname=""/>
|
||||
<offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
|
||||
<angle fieldname="" value="0" auto="0"/>
|
||||
<alignment fieldname="" value="center"/>
|
||||
<buffercolor fieldname="" red="255" blue="255" green="255"/>
|
||||
<buffersize fieldname="" units="pt" value="1"/>
|
||||
<bufferenabled fieldname="" on=""/>
|
||||
<multilineenabled fieldname="" on=""/>
|
||||
<selectedonly on=""/>
|
||||
</labelattributes>
|
||||
<edittypes>
|
||||
<edittype type="0" name="colour"/>
|
||||
<edittype type="0" name="pkuid"/>
|
||||
</edittypes>
|
||||
<editform>../projects</editform>
|
||||
<editforminit></editforminit>
|
||||
<annotationform>../projects</annotationform>
|
||||
<attributeactions/>
|
||||
</qgis>
|
BIN
tests/testdata/qgis_server_accesscontrol/dem.tif
vendored
Normal file
BIN
tests/testdata/qgis_server_accesscontrol/dem.tif
vendored
Normal file
Binary file not shown.
20
tests/testdata/qgis_server_accesscontrol/dem.tif.aux.xml
vendored
Normal file
20
tests/testdata/qgis_server_accesscontrol/dem.tif.aux.xml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<PAMDataset>
|
||||
<PAMRasterBand band="1">
|
||||
<Histograms>
|
||||
<HistItem>
|
||||
<HistMin>-18.929</HistMin>
|
||||
<HistMax>3842.929</HistMax>
|
||||
<BucketCount>1000</BucketCount>
|
||||
<IncludeOutOfRange>0</IncludeOutOfRange>
|
||||
<Approximate>1</Approximate>
|
||||
<HistCounts>0|0|0|0|3|4|6|3|4|4|5|5|2|3|2|8|3|3|4|6|4|4|1|3|8|6|2|2|6|3|6|3|3|2|2|3|5|4|2|2|5|4|2|2|2|2|1|0|4|4|0|4|3|3|0|1|3|0|0|2|1|1|4|1|0|1|3|3|2|3|1|2|3|1|2|2|0|0|3|3|0|3|2|2|3|1|2|3|2|0|3|2|2|0|2|0|0|2|1|1|2|3|1|0|2|3|1|1|2|1|2|1|0|1|1|1|1|0|2|0|1|1|2|1|2|0|0|0|3|1|1|0|1|0|2|2|1|0|2|1|3|4|4|1|0|1|1|3|3|0|2|1|0|0|1|1|1|2|0|1|0|2|2|0|2|1|0|0|1|3|0|0|1|2|2|2|1|1|0|1|1|1|4|2|1|1|1|1|1|1|2|1|1|4|0|1|0|0|1|1|0|2|3|1|4|1|0|2|0|3|1|2|2|1|1|5|0|1|2|0|1|1|3|1|0|0|1|0|2|2|2|5|0|1|0|2|0|0|3|1|0|1|2|0|1|1|0|1|0|3|1|2|0|1|0|0|1|1|1|2|0|0|0|1|2|0|0|0|1|0|0|0|0|0|0|2|1|1|0|1|0|2|1|0|2|1|1|0|1|2|0|0|0|0|2|3|2|0|2|0|1|0|0|1|1|0|1|0|2|0|1|1|0|1|1|1|2|0|0|2|1|1|0|1|0|0|1|3|1|0|0|0|1|0|0|0|1|1|1|0|0|2|2|1|0|0|0|2|0|2|0|0|0|0|0|0|0|0|1|1|1|0|1|0|0|0|0|0|0|0|1|0|0|1|0|1|0|1|0|0|0|0|0|0|0|0|0|0|0|1|0|0|1|2|0|1|0|0|1|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|1|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|1|0|0|1|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|1|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0</HistCounts>
|
||||
</HistItem>
|
||||
</Histograms>
|
||||
<Metadata>
|
||||
<MDI key="STATISTICS_MAXIMUM">3841</MDI>
|
||||
<MDI key="STATISTICS_MEAN">550.59810315778</MDI>
|
||||
<MDI key="STATISTICS_MINIMUM">-17</MDI>
|
||||
<MDI key="STATISTICS_STDDEV">506.70554545277</MDI>
|
||||
</Metadata>
|
||||
</PAMRasterBand>
|
||||
</PAMDataset>
|
BIN
tests/testdata/qgis_server_accesscontrol/dem.tif.ovr
vendored
Normal file
BIN
tests/testdata/qgis_server_accesscontrol/dem.tif.ovr
vendored
Normal file
Binary file not shown.
BIN
tests/testdata/qgis_server_accesscontrol/helloworld.db
vendored
Normal file
BIN
tests/testdata/qgis_server_accesscontrol/helloworld.db
vendored
Normal file
Binary file not shown.
2842
tests/testdata/qgis_server_accesscontrol/project.qgs
vendored
Normal file
2842
tests/testdata/qgis_server_accesscontrol/project.qgs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
79
tests/testdata/qgis_server_accesscontrol/project.qgs.cfg
vendored
Normal file
79
tests/testdata/qgis_server_accesscontrol/project.qgs.cfg
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
{
|
||||
"layers": {
|
||||
"Country": {
|
||||
"abstract": "",
|
||||
"displayInLegend": "True",
|
||||
"baseLayer": "False",
|
||||
"noLegendImage": "False",
|
||||
"id": "country20131022151106556",
|
||||
"title": "Country",
|
||||
"singleTile": "False",
|
||||
"groupAsLayer": "False",
|
||||
"popup": "False",
|
||||
"clientCacheExpiration": 300,
|
||||
"link": "",
|
||||
"toggled": "True",
|
||||
"name": "Country",
|
||||
"cached": "False",
|
||||
"type": "layer",
|
||||
"maxScale": 1000000000000,
|
||||
"imageFormat": "image/png",
|
||||
"minScale": 1
|
||||
},
|
||||
"Hello": {
|
||||
"abstract": "",
|
||||
"displayInLegend": "True",
|
||||
"baseLayer": "False",
|
||||
"noLegendImage": "False",
|
||||
"id": "hello20131022151106574",
|
||||
"title": "Hello",
|
||||
"singleTile": "False",
|
||||
"groupAsLayer": "False",
|
||||
"popup": "False",
|
||||
"clientCacheExpiration": 300,
|
||||
"link": "",
|
||||
"toggled": "True",
|
||||
"name": "Hello",
|
||||
"cached": "False",
|
||||
"type": "layer",
|
||||
"maxScale": 1000000000000,
|
||||
"imageFormat": "image/png",
|
||||
"minScale": 1
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"projection": {
|
||||
"proj4": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs",
|
||||
"ref": "EPSG:3857"
|
||||
},
|
||||
"initialExtent": [
|
||||
-33626185.4981,
|
||||
-13032965.1854,
|
||||
33978427.7365,
|
||||
21121731.156
|
||||
],
|
||||
"maxScale": 100000000,
|
||||
"tmTimeFrameType": "seconds",
|
||||
"mapScales": [
|
||||
10000,
|
||||
25000,
|
||||
50000,
|
||||
100000,
|
||||
250000,
|
||||
500000,
|
||||
1000000,
|
||||
10000000,
|
||||
100000000
|
||||
],
|
||||
"tmTimeFrameSize": 10,
|
||||
"tmAnimationFrameLength": 1000,
|
||||
"bbox": [
|
||||
-33626185.49808586,
|
||||
-13032965.185421439,
|
||||
33978427.73650816,
|
||||
21121731.15603344
|
||||
],
|
||||
"print": "True",
|
||||
"minScale": 10000
|
||||
}
|
||||
}
|
BIN
tests/testdata/qgis_server_accesscontrol/results/WCS_GetCoverage.geotiff
vendored
Normal file
BIN
tests/testdata/qgis_server_accesscontrol/results/WCS_GetCoverage.geotiff
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user