Skip to content

Commit

Permalink
Merge pull request #5253 from boundlessgeo/auth_proxy
Browse files Browse the repository at this point in the history
[auth][feature][needs-docs] Proxy authentication integration with QGIS authentication system
  • Loading branch information
elpaso committed Sep 27, 2017
2 parents 6ce8b4c + 385cca6 commit 829702b
Show file tree
Hide file tree
Showing 14 changed files with 324 additions and 74 deletions.
11 changes: 11 additions & 0 deletions python/core/auth/qgsauthmanager.sip
Expand Up @@ -359,6 +359,17 @@ Get list of authentication ids from database
:rtype: bool :rtype: bool
%End %End


bool updateNetworkProxy( QNetworkProxy &proxy /In,Out/, const QString &authcfg,
const QString &dataprovider = QString() );
%Docstring
Provider call to update a QNetworkProxy with an authentication config
\param proxy the QNetworkProxy
\param authcfg Associated authentication config id
\param dataprovider Provider key filter, offering logic branching in authentication method
:return: Whether operation succeeded
:rtype: bool
%End



bool storeAuthSetting( const QString &key, const QVariant &value, bool encrypt = false ); bool storeAuthSetting( const QString &key, const QVariant &value, bool encrypt = false );
%Docstring %Docstring
Expand Down
13 changes: 13 additions & 0 deletions python/core/auth/qgsauthmethod.sip
Expand Up @@ -28,6 +28,7 @@ class QgsAuthMethod : QObject
NetworkReply, NetworkReply,
DataSourceUri, DataSourceUri,
GenericDataSourceUri, GenericDataSourceUri,
NetworkProxy,
All All
}; };
typedef QFlags<QgsAuthMethod::Expansion> Expansions; typedef QFlags<QgsAuthMethod::Expansion> Expansions;
Expand Down Expand Up @@ -110,6 +111,18 @@ Increment this if method is significantly updated, allow updater code to be writ
:rtype: bool :rtype: bool
%End %End


virtual bool updateNetworkProxy( QNetworkProxy &proxy, const QString &authcfg,
const QString &dataprovider = QString() );
%Docstring
Update proxy settings with authentication components
\param proxy
\param authcfg Authentication configuration ID
\param dataprovider Textual key for a data provider, e.g. 'proxy', that allows
for custom updater code specific to the provider
:return: Whether the update succeeded
:rtype: bool
%End

virtual void clearCachedConfig( const QString &authcfg ) = 0; virtual void clearCachedConfig( const QString &authcfg ) = 0;
%Docstring %Docstring
Clear any cached configuration. Called when the QgsAuthManager deletes an authentication configuration (authcfg). Clear any cached configuration. Called when the QgsAuthManager deletes an authentication configuration (authcfg).
Expand Down
14 changes: 7 additions & 7 deletions src/app/qgisapp.cpp
Expand Up @@ -630,8 +630,6 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
connect( mUserProfileManager, &QgsUserProfileManager::profilesChanged, this, &QgisApp::refreshProfileMenu ); connect( mUserProfileManager, &QgsUserProfileManager::profilesChanged, this, &QgisApp::refreshProfileMenu );
endProfile(); endProfile();


namSetup();

// load GUI: actions, menus, toolbars // load GUI: actions, menus, toolbars
profiler->beginGroup( QStringLiteral( "qgisapp" ) ); profiler->beginGroup( QStringLiteral( "qgisapp" ) );
profiler->beginGroup( QStringLiteral( "startup" ) ); profiler->beginGroup( QStringLiteral( "startup" ) );
Expand All @@ -656,6 +654,10 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
} }
endProfile(); endProfile();


mTray = new QSystemTrayIcon();
mTray->setIcon( QIcon( QgsApplication::appIconPath() ) );
mTray->hide();

startProfile( QStringLiteral( "Initializing authentication" ) ); startProfile( QStringLiteral( "Initializing authentication" ) );
mSplash->showMessage( tr( "Initializing authentication" ), Qt::AlignHCenter | Qt::AlignBottom ); mSplash->showMessage( tr( "Initializing authentication" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents(); qApp->processEvents();
Expand All @@ -666,6 +668,9 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
} }
endProfile(); endProfile();


// Setup QgsNetworkAccessManager (this needs to happen after authentication, for proxy settings)
namSetup();

// Create the themes folder for the user // Create the themes folder for the user
startProfile( QStringLiteral( "Creating theme folder" ) ); startProfile( QStringLiteral( "Creating theme folder" ) );
QgsApplication::createThemeFolder(); QgsApplication::createThemeFolder();
Expand Down Expand Up @@ -1156,11 +1161,6 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
grabGesture( Qt::TapAndHoldGesture ); grabGesture( Qt::TapAndHoldGesture );
} }



mTray = new QSystemTrayIcon();
mTray->setIcon( QIcon( QgsApplication::appIconPath() ) );
mTray->hide();

connect( QgsApplication::taskManager(), &QgsTaskManager::statusChanged, this, &QgisApp::onTaskCompleteShowNotify ); connect( QgsApplication::taskManager(), &QgsTaskManager::statusChanged, this, &QgisApp::onTaskCompleteShowNotify );


#ifdef Q_OS_WIN #ifdef Q_OS_WIN
Expand Down
14 changes: 14 additions & 0 deletions src/app/qgsoptions.cpp
Expand Up @@ -28,6 +28,7 @@
#include "qgstolerance.h" #include "qgstolerance.h"
#include "qgsscaleutils.h" #include "qgsscaleutils.h"
#include "qgsnetworkaccessmanager.h" #include "qgsnetworkaccessmanager.h"
#include "qgsauthconfigselect.h"
#include "qgsproject.h" #include "qgsproject.h"
#include "qgsdualview.h" #include "qgsdualview.h"
#include "qgsrasterlayer.h" #include "qgsrasterlayer.h"
Expand Down Expand Up @@ -307,6 +308,16 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
// WMS/WMS-C default max retry in case of tile request errors // WMS/WMS-C default max retry in case of tile request errors
mDefaultTileMaxRetrySpinBox->setValue( mSettings->value( QStringLiteral( "/qgis/defaultTileMaxRetry" ), "3" ).toInt() ); mDefaultTileMaxRetrySpinBox->setValue( mSettings->value( QStringLiteral( "/qgis/defaultTileMaxRetry" ), "3" ).toInt() );


// Proxy stored authentication configurations
mProxyAuthConfigSelect = new QgsAuthConfigSelect( this, QStringLiteral( "proxy" ) );
tabAuth->insertTab( 1, mProxyAuthConfigSelect, tr( "Configurations" ) );
QString authcfg = mSettings->value( QStringLiteral( "proxy/authcfg" ) ).toString();
mProxyAuthConfigSelect->setConfigId( authcfg );
if ( !authcfg.isEmpty() )
{
tabAuth->setCurrentIndex( tabAuth->indexOf( mProxyAuthConfigSelect ) );
}

//Web proxy settings //Web proxy settings
grpProxy->setChecked( mSettings->value( QStringLiteral( "proxy/proxyEnabled" ), "0" ).toBool() ); grpProxy->setChecked( mSettings->value( QStringLiteral( "proxy/proxyEnabled" ), "0" ).toBool() );
leProxyHost->setText( mSettings->value( QStringLiteral( "proxy/proxyHost" ), "" ).toString() ); leProxyHost->setText( mSettings->value( QStringLiteral( "proxy/proxyHost" ), "" ).toString() );
Expand Down Expand Up @@ -1162,6 +1173,9 @@ void QgsOptions::saveOptions()
// WMS/WMS-C default max retry in case of tile request errors // WMS/WMS-C default max retry in case of tile request errors
mSettings->setValue( QStringLiteral( "/qgis/defaultTileMaxRetry" ), mDefaultTileMaxRetrySpinBox->value() ); mSettings->setValue( QStringLiteral( "/qgis/defaultTileMaxRetry" ), mDefaultTileMaxRetrySpinBox->value() );


// Proxy stored authentication configurations
mSettings->setValue( QStringLiteral( "proxy/authcfg" ), mProxyAuthConfigSelect->configId( ) );

//Web proxy settings //Web proxy settings
mSettings->setValue( QStringLiteral( "proxy/proxyEnabled" ), grpProxy->isChecked() ); mSettings->setValue( QStringLiteral( "proxy/proxyEnabled" ), grpProxy->isChecked() );
mSettings->setValue( QStringLiteral( "proxy/proxyHost" ), leProxyHost->text() ); mSettings->setValue( QStringLiteral( "proxy/proxyHost" ), leProxyHost->text() );
Expand Down
2 changes: 2 additions & 0 deletions src/app/qgsoptions.h
Expand Up @@ -32,6 +32,7 @@
class QgsExpressionContext; class QgsExpressionContext;
class QgsOptionsPageWidget; class QgsOptionsPageWidget;
class QgsLocatorOptionsWidget; class QgsLocatorOptionsWidget;
class QgsAuthConfigSelect;


/** /**
* \class QgsOptions * \class QgsOptions
Expand Down Expand Up @@ -255,6 +256,7 @@ class APP_EXPORT QgsOptions : public QgsOptionsDialogBase, private Ui::QgsOption


QList< QgsOptionsPageWidget * > mAdditionalOptionWidgets; QList< QgsOptionsPageWidget * > mAdditionalOptionWidgets;
QgsLocatorOptionsWidget *mLocatorOptionsWidget = nullptr; QgsLocatorOptionsWidget *mLocatorOptionsWidget = nullptr;
QgsAuthConfigSelect *mProxyAuthConfigSelect = nullptr;


}; };


Expand Down
27 changes: 26 additions & 1 deletion src/auth/basic/qgsauthbasicmethod.cpp
Expand Up @@ -20,6 +20,8 @@
#include "qgsauthmanager.h" #include "qgsauthmanager.h"
#include "qgslogger.h" #include "qgslogger.h"


#include <QNetworkProxy>

static const QString AUTH_METHOD_KEY = QStringLiteral( "Basic" ); static const QString AUTH_METHOD_KEY = QStringLiteral( "Basic" );
static const QString AUTH_METHOD_DESCRIPTION = QStringLiteral( "Basic authentication" ); static const QString AUTH_METHOD_DESCRIPTION = QStringLiteral( "Basic authentication" );


Expand All @@ -37,7 +39,8 @@ QgsAuthBasicMethod::QgsAuthBasicMethod()
<< QStringLiteral( "ows" ) << QStringLiteral( "ows" )
<< QStringLiteral( "wfs" ) // convert to lowercase << QStringLiteral( "wfs" ) // convert to lowercase
<< QStringLiteral( "wcs" ) << QStringLiteral( "wcs" )
<< QStringLiteral( "wms" ) ); << QStringLiteral( "wms" )
<< QStringLiteral( "proxy" ) );
} }


QgsAuthBasicMethod::~QgsAuthBasicMethod() QgsAuthBasicMethod::~QgsAuthBasicMethod()
Expand Down Expand Up @@ -126,6 +129,28 @@ bool QgsAuthBasicMethod::updateDataSourceUriItems( QStringList &connectionItems,
return true; return true;
} }


bool QgsAuthBasicMethod::updateNetworkProxy( QNetworkProxy &proxy, const QString &authcfg, const QString &dataprovider )
{
Q_UNUSED( dataprovider )

QgsAuthMethodConfig mconfig = getMethodConfig( authcfg );
if ( !mconfig.isValid() )
{
QgsDebugMsg( QString( "Update proxy config FAILED for authcfg: %1: config invalid" ).arg( authcfg ) );
return false;
}

QString username = mconfig.config( QStringLiteral( "username" ) );
QString password = mconfig.config( QStringLiteral( "password" ) );

if ( !username.isEmpty() )
{
proxy.setUser( username );
proxy.setPassword( password );
}
return true;
}

void QgsAuthBasicMethod::updateMethodConfig( QgsAuthMethodConfig &mconfig ) void QgsAuthBasicMethod::updateMethodConfig( QgsAuthMethodConfig &mconfig )
{ {
if ( mconfig.hasConfig( QStringLiteral( "oldconfigstyle" ) ) ) if ( mconfig.hasConfig( QStringLiteral( "oldconfigstyle" ) ) )
Expand Down
4 changes: 4 additions & 0 deletions src/auth/basic/qgsauthbasicmethod.h
Expand Up @@ -44,6 +44,10 @@ class QgsAuthBasicMethod : public QgsAuthMethod
bool updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg, bool updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
const QString &dataprovider = QString() ) override; const QString &dataprovider = QString() ) override;



bool updateNetworkProxy( QNetworkProxy &proxy, const QString &authcfg,
const QString &dataprovider = QString() ) override;

void clearCachedConfig( const QString &authcfg ) override; void clearCachedConfig( const QString &authcfg ) override;


void updateMethodConfig( QgsAuthMethodConfig &mconfig ) override; void updateMethodConfig( QgsAuthMethodConfig &mconfig ) override;
Expand Down
26 changes: 26 additions & 0 deletions src/core/auth/qgsauthmanager.cpp
Expand Up @@ -1457,6 +1457,32 @@ bool QgsAuthManager::updateDataSourceUriItems( QStringList &connectionItems, con
return false; return false;
} }


bool QgsAuthManager::updateNetworkProxy( QNetworkProxy &proxy, const QString &authcfg, const QString &dataprovider )
{
if ( isDisabled() )
return false;

QgsAuthMethod *authmethod = configAuthMethod( authcfg );
if ( authmethod )
{
if ( !( authmethod->supportedExpansions() & QgsAuthMethod::NetworkProxy ) )
{
QgsDebugMsg( QStringLiteral( "Proxy updating not supported by authcfg: %1" ).arg( authcfg ) );
return true;
}

if ( !authmethod->updateNetworkProxy( proxy, authcfg, dataprovider.toLower() ) )
{
authmethod->clearCachedConfig( authcfg );
return false;
}
QgsDebugMsg( QStringLiteral( "Proxy updated successfully from authcfg: %1" ).arg( authcfg ) );
return true;
}

return false;
}

bool QgsAuthManager::storeAuthSetting( const QString &key, const QVariant &value, bool encrypt ) bool QgsAuthManager::storeAuthSetting( const QString &key, const QVariant &value, bool encrypt )
{ {
if ( key.isEmpty() ) if ( key.isEmpty() )
Expand Down
10 changes: 10 additions & 0 deletions src/core/auth/qgsauthmanager.h
Expand Up @@ -332,6 +332,16 @@ class CORE_EXPORT QgsAuthManager : public QObject
bool updateDataSourceUriItems( QStringList &connectionItems SIP_INOUT, const QString &authcfg, bool updateDataSourceUriItems( QStringList &connectionItems SIP_INOUT, const QString &authcfg,
const QString &dataprovider = QString() ); const QString &dataprovider = QString() );


/**
* Provider call to update a QNetworkProxy with an authentication config
* \param proxy the QNetworkProxy
* \param authcfg Associated authentication config id
* \param dataprovider Provider key filter, offering logic branching in authentication method
* \returns Whether operation succeeded
*/
bool updateNetworkProxy( QNetworkProxy &proxy SIP_INOUT, const QString &authcfg,
const QString &dataprovider = QString() );

////////////////// Generic settings /////////////////////// ////////////////// Generic settings ///////////////////////


//! Store an authentication setting (stored as string via QVariant( value ).toString() ) //! Store an authentication setting (stored as string via QVariant( value ).toString() )
Expand Down
19 changes: 18 additions & 1 deletion src/core/auth/qgsauthmethod.h
Expand Up @@ -51,7 +51,8 @@ class CORE_EXPORT QgsAuthMethod : public QObject
NetworkReply = 0x2, NetworkReply = 0x2,
DataSourceUri = 0x4, DataSourceUri = 0x4,
GenericDataSourceUri = 0x8, GenericDataSourceUri = 0x8,
All = NetworkRequest | NetworkReply | DataSourceUri | GenericDataSourceUri NetworkProxy = 0x16,
All = NetworkRequest | NetworkReply | DataSourceUri | GenericDataSourceUri | NetworkProxy
}; };
Q_DECLARE_FLAGS( Expansions, Expansion ) Q_DECLARE_FLAGS( Expansions, Expansion )


Expand Down Expand Up @@ -126,6 +127,22 @@ class CORE_EXPORT QgsAuthMethod : public QObject
return true; // noop return true; // noop
} }


/** Update proxy settings with authentication components
* \param proxy
* \param authcfg Authentication configuration ID
* \param dataprovider Textual key for a data provider, e.g. 'proxy', that allows
* for custom updater code specific to the provider
* \returns Whether the update succeeded
*/
virtual bool updateNetworkProxy( QNetworkProxy &proxy, const QString &authcfg,
const QString &dataprovider = QString() )
{
Q_UNUSED( proxy )
Q_UNUSED( authcfg )
Q_UNUSED( dataprovider )
return true; // noop
}

/** Clear any cached configuration. Called when the QgsAuthManager deletes an authentication configuration (authcfg). /** Clear any cached configuration. Called when the QgsAuthManager deletes an authentication configuration (authcfg).
* \note It is highly recommended that a cache of authentication components (per requested authcfg) * \note It is highly recommended that a cache of authentication components (per requested authcfg)
* be implemented, to avoid excessive queries on the auth database. Such a cache could be as * be implemented, to avoid excessive queries on the auth database. Such a cache could be as
Expand Down
11 changes: 10 additions & 1 deletion src/core/qgsnetworkaccessmanager.cpp
Expand Up @@ -321,6 +321,7 @@ void QgsNetworkAccessManager::setupDefaultProxyAndCache()
//read type, host, port, user, passw from settings //read type, host, port, user, passw from settings
QString proxyHost = settings.value( QStringLiteral( "proxy/proxyHost" ), "" ).toString(); QString proxyHost = settings.value( QStringLiteral( "proxy/proxyHost" ), "" ).toString();
int proxyPort = settings.value( QStringLiteral( "proxy/proxyPort" ), "" ).toString().toInt(); int proxyPort = settings.value( QStringLiteral( "proxy/proxyPort" ), "" ).toString().toInt();

QString proxyUser = settings.value( QStringLiteral( "proxy/proxyUser" ), "" ).toString(); QString proxyUser = settings.value( QStringLiteral( "proxy/proxyUser" ), "" ).toString();
QString proxyPassword = settings.value( QStringLiteral( "proxy/proxyPassword" ), "" ).toString(); QString proxyPassword = settings.value( QStringLiteral( "proxy/proxyPassword" ), "" ).toString();


Expand Down Expand Up @@ -356,7 +357,7 @@ void QgsNetworkAccessManager::setupDefaultProxyAndCache()
{ {
proxyType = QNetworkProxy::FtpCachingProxy; proxyType = QNetworkProxy::FtpCachingProxy;
} }
QgsDebugMsg( QString( "setting proxy %1 %2:%3 %4/%5" ) QgsDebugMsg( QStringLiteral( "setting proxy %1 %2:%3 %4/%5" )
.arg( proxyType ) .arg( proxyType )
.arg( proxyHost ).arg( proxyPort ) .arg( proxyHost ).arg( proxyPort )
.arg( proxyUser, proxyPassword ) .arg( proxyUser, proxyPassword )
Expand All @@ -365,6 +366,14 @@ void QgsNetworkAccessManager::setupDefaultProxyAndCache()
} }
} }


// Setup network proxy authentication configuration
QString authcfg = settings.value( QStringLiteral( "proxy/authcfg" ), "" ).toString();
if ( !authcfg.isEmpty( ) )
{
QgsDebugMsg( QStringLiteral( "setting proxy from stored authentication configuration %1" ).arg( authcfg ) );
QgsAuthManager::instance()->updateNetworkProxy( proxy, authcfg );
}

setFallbackProxyAndExcludes( proxy, excludes ); setFallbackProxyAndExcludes( proxy, excludes );


QgsNetworkDiskCache *newcache = qobject_cast<QgsNetworkDiskCache *>( cache() ); QgsNetworkDiskCache *newcache = qobject_cast<QgsNetworkDiskCache *>( cache() );
Expand Down

0 comments on commit 829702b

Please sign in to comment.