mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -04:00
Merge pull request #5526 from boundlessgeo/ogr_authconfig_2
[auth][needs-docs] Authentication configuration support in OGR provider
This commit is contained in:
commit
8dd70c1dab
@ -33,3 +33,4 @@ PyQgsServerAccessControl
|
|||||||
# Need a local postgres installation
|
# Need a local postgres installation
|
||||||
PyQgsAuthManagerPKIPostgresTest
|
PyQgsAuthManagerPKIPostgresTest
|
||||||
PyQgsAuthManagerPasswordPostgresTest
|
PyQgsAuthManagerPasswordPostgresTest
|
||||||
|
PyQgsAuthManagerOgrPostgresTest
|
||||||
|
@ -42,6 +42,7 @@ QgsAuthBasicMethod::QgsAuthBasicMethod()
|
|||||||
<< QStringLiteral( "wfs" ) // convert to lowercase
|
<< QStringLiteral( "wfs" ) // convert to lowercase
|
||||||
<< QStringLiteral( "wcs" )
|
<< QStringLiteral( "wcs" )
|
||||||
<< QStringLiteral( "wms" )
|
<< QStringLiteral( "wms" )
|
||||||
|
<< QStringLiteral( "ogr" )
|
||||||
<< QStringLiteral( "proxy" ) );
|
<< QStringLiteral( "proxy" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +86,6 @@ bool QgsAuthBasicMethod::updateNetworkRequest( QNetworkRequest &request, const Q
|
|||||||
bool QgsAuthBasicMethod::updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
|
bool QgsAuthBasicMethod::updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
|
||||||
const QString &dataprovider )
|
const QString &dataprovider )
|
||||||
{
|
{
|
||||||
Q_UNUSED( dataprovider )
|
|
||||||
QgsAuthMethodConfig mconfig = getMethodConfig( authcfg );
|
QgsAuthMethodConfig mconfig = getMethodConfig( authcfg );
|
||||||
if ( !mconfig.isValid() )
|
if ( !mconfig.isValid() )
|
||||||
{
|
{
|
||||||
@ -102,6 +102,138 @@ bool QgsAuthBasicMethod::updateDataSourceUriItems( QStringList &connectionItems,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SSL Extra CAs
|
||||||
|
QString caparam;
|
||||||
|
QList<QSslCertificate> cas;
|
||||||
|
cas = QgsApplication::authManager()->trustedCaCerts();
|
||||||
|
// save CAs to temp file
|
||||||
|
QString tempFileBase = QStringLiteral( "tmp_basic_%1.pem" );
|
||||||
|
QString caFilePath = QgsAuthCertUtils::pemTextToTempFile(
|
||||||
|
tempFileBase.arg( QUuid::createUuid().toString() ),
|
||||||
|
QgsAuthCertUtils::certsToPemText( cas ) );
|
||||||
|
if ( ! caFilePath.isEmpty() )
|
||||||
|
{
|
||||||
|
caparam = "sslrootcert='" + caFilePath + "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Branch for OGR
|
||||||
|
if ( dataprovider == QStringLiteral( "ogr" ) )
|
||||||
|
{
|
||||||
|
if ( ! password.isEmpty() )
|
||||||
|
{
|
||||||
|
QString fullUri( connectionItems.first() );
|
||||||
|
QString uri( fullUri );
|
||||||
|
// Handle sub-layers
|
||||||
|
if ( fullUri.contains( '|' ) )
|
||||||
|
{
|
||||||
|
uri = uri.left( uri.indexOf( '|' ) );
|
||||||
|
}
|
||||||
|
// At least username must be set... password can be empty
|
||||||
|
if ( ! username.isEmpty() )
|
||||||
|
{
|
||||||
|
// Inject credentials
|
||||||
|
if ( uri.startsWith( QStringLiteral( "PG:" ) ) )
|
||||||
|
{
|
||||||
|
bool chopped = false;
|
||||||
|
if ( uri.endsWith( '"' ) )
|
||||||
|
{
|
||||||
|
uri.chop( 1 );
|
||||||
|
chopped = true;
|
||||||
|
}
|
||||||
|
if ( !username.isEmpty() )
|
||||||
|
{
|
||||||
|
uri += QStringLiteral( " user='%1'" ).arg( username );
|
||||||
|
|
||||||
|
if ( !password.isEmpty() )
|
||||||
|
uri += QStringLiteral( " password='%1'" ).arg( password );
|
||||||
|
}
|
||||||
|
// add extra CAs
|
||||||
|
if ( ! caparam.isEmpty() )
|
||||||
|
{
|
||||||
|
uri += ' ' + caparam;
|
||||||
|
}
|
||||||
|
if ( chopped )
|
||||||
|
uri += '"';
|
||||||
|
}
|
||||||
|
else if ( uri.startsWith( QStringLiteral( "SDE:" ) ) )
|
||||||
|
{
|
||||||
|
uri = uri.replace( QRegExp( ",$" ), QStringLiteral( ",%1,%2" ).arg( username, password ) );
|
||||||
|
}
|
||||||
|
else if ( uri.startsWith( QStringLiteral( "IDB" ) ) )
|
||||||
|
{
|
||||||
|
bool chopped = false;
|
||||||
|
if ( uri.endsWith( '"' ) )
|
||||||
|
{
|
||||||
|
uri.chop( 1 );
|
||||||
|
chopped = true;
|
||||||
|
}
|
||||||
|
uri += QStringLiteral( " user=%1" ).arg( username );
|
||||||
|
if ( !password.isEmpty() )
|
||||||
|
uri += QStringLiteral( " pass=%1" ).arg( password );
|
||||||
|
if ( chopped )
|
||||||
|
uri += '"';
|
||||||
|
}
|
||||||
|
else if ( uri.startsWith( QStringLiteral( "@driver=ingres" ) ) )
|
||||||
|
{
|
||||||
|
uri += QStringLiteral( ",userid=%1" ).arg( username );
|
||||||
|
if ( !password.isEmpty() )
|
||||||
|
uri += QStringLiteral( ",password=%1" ).arg( password );
|
||||||
|
}
|
||||||
|
else if ( uri.startsWith( QStringLiteral( "MySQL:" ) ) )
|
||||||
|
{
|
||||||
|
uri += QStringLiteral( ",user=%1" ).arg( username );
|
||||||
|
if ( !password.isEmpty() )
|
||||||
|
uri += QStringLiteral( ",password=%1" ).arg( password );
|
||||||
|
}
|
||||||
|
else if ( uri.startsWith( QStringLiteral( "MSSQL:" ) ) )
|
||||||
|
{
|
||||||
|
uri += QStringLiteral( ";uid=%1" ).arg( username );
|
||||||
|
uri = uri.replace( QLatin1String( ";trusted_connection=yes" ), QString() );
|
||||||
|
|
||||||
|
if ( !password.isEmpty() )
|
||||||
|
uri += QStringLiteral( ";pwd=%1" ).arg( password );
|
||||||
|
}
|
||||||
|
else if ( uri.startsWith( QStringLiteral( "OCI:" ) ) )
|
||||||
|
{
|
||||||
|
// OCI:userid/password@database_instance:table,table
|
||||||
|
uri = uri.replace( QStringLiteral( "OCI:/" ), QStringLiteral( "OCI:%1/%2" ).arg( username, password ) );
|
||||||
|
}
|
||||||
|
else if ( uri.startsWith( QStringLiteral( "ODBC:" ) ) )
|
||||||
|
{
|
||||||
|
if ( password.isEmpty() )
|
||||||
|
{
|
||||||
|
uri = uri.replace( QRegExp( "^ODBC:@?" ), "ODBC:" + username + '@' );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uri = uri.replace( QRegExp( "^ODBC:@?" ), "ODBC:" + username + '/' + password + '@' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( uri.startsWith( QStringLiteral( "couchdb" ) )
|
||||||
|
|| uri.startsWith( QStringLiteral( "DODS" ) )
|
||||||
|
|| uri.startsWith( "http://" )
|
||||||
|
|| uri.startsWith( "https://" )
|
||||||
|
|| uri.startsWith( "ftp://" ) // not really sure that this is supported ...
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uri = uri.replace( QStringLiteral( "://" ), QStringLiteral( "://%1:%2@" ).arg( username, password ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle sub-layers
|
||||||
|
if ( fullUri.contains( '|' ) )
|
||||||
|
{
|
||||||
|
uri += '|' + fullUri.right( fullUri.length() - fullUri.lastIndexOf( '|' ) - 1 );
|
||||||
|
}
|
||||||
|
connectionItems.replace( 0, uri );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QgsDebugMsg( QString( "Update URI items FAILED for authcfg: %1: password empty" ).arg( authcfg ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else // Not-ogr
|
||||||
|
{
|
||||||
QString userparam = "user='" + escapeUserPass( username ) + '\'';
|
QString userparam = "user='" + escapeUserPass( username ) + '\'';
|
||||||
int userindx = connectionItems.indexOf( QRegExp( "^user='.*" ) );
|
int userindx = connectionItems.indexOf( QRegExp( "^user='.*" ) );
|
||||||
if ( userindx != -1 )
|
if ( userindx != -1 )
|
||||||
@ -123,18 +255,9 @@ bool QgsAuthBasicMethod::updateDataSourceUriItems( QStringList &connectionItems,
|
|||||||
{
|
{
|
||||||
connectionItems.append( passparam );
|
connectionItems.append( passparam );
|
||||||
}
|
}
|
||||||
|
|
||||||
// add extra CAs
|
// add extra CAs
|
||||||
QList<QSslCertificate> cas;
|
if ( ! caparam.isEmpty() )
|
||||||
cas = QgsApplication::authManager()->trustedCaCerts();
|
|
||||||
// save CAs to temp file
|
|
||||||
QString tempFileBase = QStringLiteral( "tmp_basic_%1.pem" );
|
|
||||||
QString caFilePath = QgsAuthCertUtils::pemTextToTempFile(
|
|
||||||
tempFileBase.arg( QUuid::createUuid().toString() ),
|
|
||||||
QgsAuthCertUtils::certsToPemText( cas ) );
|
|
||||||
if ( ! caFilePath.isEmpty() )
|
|
||||||
{
|
{
|
||||||
QString caparam = "sslrootcert='" + caFilePath + "'";
|
|
||||||
int sslcaindx = connectionItems.indexOf( QRegExp( "^sslrootcert='.*" ) );
|
int sslcaindx = connectionItems.indexOf( QRegExp( "^sslrootcert='.*" ) );
|
||||||
if ( sslcaindx != -1 )
|
if ( sslcaindx != -1 )
|
||||||
{
|
{
|
||||||
@ -145,6 +268,8 @@ bool QgsAuthBasicMethod::updateDataSourceUriItems( QStringList &connectionItems,
|
|||||||
connectionItems.append( caparam );
|
connectionItems.append( caparam );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -57,18 +57,25 @@ QgsNewOgrConnection::QgsNewOgrConnection( QWidget *parent, const QString &connTy
|
|||||||
txtDatabase->setText( settings.value( key + "/database" ).toString() );
|
txtDatabase->setText( settings.value( key + "/database" ).toString() );
|
||||||
QString port = settings.value( key + "/port" ).toString();
|
QString port = settings.value( key + "/port" ).toString();
|
||||||
txtPort->setText( port );
|
txtPort->setText( port );
|
||||||
txtUsername->setText( settings.value( key + "/username" ).toString() );
|
if ( settings.value( key + "/store_username" ).toString() == QLatin1String( "true" ) )
|
||||||
if ( settings.value( key + "/save" ).toString() == QLatin1String( "true" ) )
|
|
||||||
{
|
{
|
||||||
txtPassword->setText( settings.value( key + "/password" ).toString() );
|
mAuthSettingsDatabase->setUsername( settings.value( key + "/username" ).toString() );
|
||||||
chkStorePassword->setChecked( true );
|
mAuthSettingsDatabase->setStoreUsernameChecked( true );
|
||||||
}
|
}
|
||||||
|
if ( settings.value( key + "/store_password" ).toString() == QLatin1String( "true" ) )
|
||||||
|
{
|
||||||
|
mAuthSettingsDatabase->setPassword( settings.value( key + "/password" ).toString() );
|
||||||
|
mAuthSettingsDatabase->setStorePasswordChecked( true );
|
||||||
|
}
|
||||||
|
mAuthSettingsDatabase->setConfigId( settings.value( key + "/configid" ).toString() );
|
||||||
cmbDatabaseTypes->setCurrentIndex( cmbDatabaseTypes->findText( connType ) );
|
cmbDatabaseTypes->setCurrentIndex( cmbDatabaseTypes->findText( connType ) );
|
||||||
txtName->setText( connName );
|
txtName->setText( connName );
|
||||||
txtName->setEnabled( false );
|
txtName->setEnabled( false );
|
||||||
cmbDatabaseTypes->setEnabled( false );
|
cmbDatabaseTypes->setEnabled( false );
|
||||||
}
|
}
|
||||||
txtName->setValidator( new QRegExpValidator( QRegExp( "[^\\/]+" ), txtName ) );
|
txtName->setValidator( new QRegExpValidator( QRegExp( "[^\\/]+" ), txtName ) );
|
||||||
|
mAuthSettingsDatabase->setDataprovider( QStringLiteral( "ogr" ) );
|
||||||
|
mAuthSettingsDatabase->showStoreCheckboxes( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsNewOgrConnection::~QgsNewOgrConnection()
|
QgsNewOgrConnection::~QgsNewOgrConnection()
|
||||||
@ -80,9 +87,14 @@ QgsNewOgrConnection::~QgsNewOgrConnection()
|
|||||||
void QgsNewOgrConnection::testConnection()
|
void QgsNewOgrConnection::testConnection()
|
||||||
{
|
{
|
||||||
QString uri;
|
QString uri;
|
||||||
uri = createDatabaseURI( cmbDatabaseTypes->currentText(), txtHost->text(),
|
uri = createDatabaseURI( cmbDatabaseTypes->currentText(),
|
||||||
txtDatabase->text(), txtPort->text(),
|
txtHost->text(),
|
||||||
txtUsername->text(), txtPassword->text() );
|
txtDatabase->text(),
|
||||||
|
txtPort->text(),
|
||||||
|
mAuthSettingsDatabase->configId(),
|
||||||
|
mAuthSettingsDatabase->username(),
|
||||||
|
mAuthSettingsDatabase->password(),
|
||||||
|
true );
|
||||||
QgsDebugMsg( "Connecting using uri = " + uri );
|
QgsDebugMsg( "Connecting using uri = " + uri );
|
||||||
OGRRegisterAll();
|
OGRRegisterAll();
|
||||||
OGRDataSourceH poDS;
|
OGRDataSourceH poDS;
|
||||||
@ -133,9 +145,11 @@ void QgsNewOgrConnection::accept()
|
|||||||
settings.setValue( baseKey + "/host", txtHost->text() );
|
settings.setValue( baseKey + "/host", txtHost->text() );
|
||||||
settings.setValue( baseKey + "/database", txtDatabase->text() );
|
settings.setValue( baseKey + "/database", txtDatabase->text() );
|
||||||
settings.setValue( baseKey + "/port", txtPort->text() );
|
settings.setValue( baseKey + "/port", txtPort->text() );
|
||||||
settings.setValue( baseKey + "/username", txtUsername->text() );
|
settings.setValue( baseKey + "/username", mAuthSettingsDatabase->storeUsernameIsChecked() ? mAuthSettingsDatabase->username() : QLatin1String( "" ) );
|
||||||
settings.setValue( baseKey + "/password", chkStorePassword->isChecked() ? txtPassword->text() : QLatin1String( "" ) );
|
settings.setValue( baseKey + "/password", mAuthSettingsDatabase->storePasswordIsChecked() ? mAuthSettingsDatabase->password() : QLatin1String( "" ) );
|
||||||
settings.setValue( baseKey + "/save", chkStorePassword->isChecked() ? "true" : "false" );
|
settings.setValue( baseKey + "/store_username", mAuthSettingsDatabase->storeUsernameIsChecked() ? "true" : "false" );
|
||||||
|
settings.setValue( baseKey + "/store_password", mAuthSettingsDatabase->storePasswordIsChecked() ? "true" : "false" );
|
||||||
|
settings.setValue( baseKey + "/configid", mAuthSettingsDatabase->configId() );
|
||||||
|
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,24 @@
|
|||||||
|
|
||||||
#include "qgsogrhelperfunctions.h"
|
#include "qgsogrhelperfunctions.h"
|
||||||
#include "qgslogger.h"
|
#include "qgslogger.h"
|
||||||
|
#include "qgsapplication.h"
|
||||||
|
#include "qgsauthmanager.h"
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
|
|
||||||
QString createDatabaseURI( const QString &connectionType, const QString &host, const QString &database, QString port, const QString &user, const QString &password )
|
QString createDatabaseURI( const QString &connectionType, const QString &host, const QString &database, QString port, const QString &configId, QString username, QString password, bool expandAuthConfig )
|
||||||
{
|
{
|
||||||
QString uri;
|
QString uri;
|
||||||
|
|
||||||
|
// If an auth configuration is set, override username and password
|
||||||
|
// Note that only Basic auth (username/password) is for now supported for OGR connections
|
||||||
|
if ( ! configId.isEmpty() )
|
||||||
|
{
|
||||||
|
// Blank credentials: we are using authcfg!
|
||||||
|
username = QString();
|
||||||
|
password = QString();
|
||||||
|
// append authcfg is at the end, because we want to append the authcfg as last argument
|
||||||
|
}
|
||||||
|
|
||||||
//todo:add default ports for all kind of databases
|
//todo:add default ports for all kind of databases
|
||||||
if ( connectionType == QLatin1String( "ESRI Personal GeoDatabase" ) )
|
if ( connectionType == QLatin1String( "ESRI Personal GeoDatabase" ) )
|
||||||
{
|
{
|
||||||
@ -34,7 +46,7 @@ QString createDatabaseURI( const QString &connectionType, const QString &host, c
|
|||||||
if ( port.isEmpty() )
|
if ( port.isEmpty() )
|
||||||
port = QStringLiteral( "5151" );
|
port = QStringLiteral( "5151" );
|
||||||
|
|
||||||
uri = "SDE:" + host + ",PORT:" + port + ',' + database + ',' + user + ',' + password;
|
uri = "SDE:" + host + ",PORT:" + port + ',' + database + ',' + username + ',' + password;
|
||||||
}
|
}
|
||||||
else if ( connectionType == QLatin1String( "Informix DataBlade" ) )
|
else if ( connectionType == QLatin1String( "Informix DataBlade" ) )
|
||||||
{
|
{
|
||||||
@ -44,9 +56,9 @@ QString createDatabaseURI( const QString &connectionType, const QString &host, c
|
|||||||
if ( !host.isEmpty() )
|
if ( !host.isEmpty() )
|
||||||
uri += QStringLiteral( " server=%1" ).arg( host );
|
uri += QStringLiteral( " server=%1" ).arg( host );
|
||||||
|
|
||||||
if ( !user.isEmpty() )
|
if ( !username.isEmpty() )
|
||||||
{
|
{
|
||||||
uri += QStringLiteral( " user=%1" ).arg( user );
|
uri += QStringLiteral( " user=%1" ).arg( username );
|
||||||
|
|
||||||
if ( !password.isEmpty() )
|
if ( !password.isEmpty() )
|
||||||
uri += QStringLiteral( " pass=%1" ).arg( password );
|
uri += QStringLiteral( " pass=%1" ).arg( password );
|
||||||
@ -56,9 +68,9 @@ QString createDatabaseURI( const QString &connectionType, const QString &host, c
|
|||||||
{
|
{
|
||||||
//not tested
|
//not tested
|
||||||
uri = "@driver=ingres,dbname=" + database;
|
uri = "@driver=ingres,dbname=" + database;
|
||||||
if ( !user.isEmpty() )
|
if ( !username.isEmpty() )
|
||||||
{
|
{
|
||||||
uri += QStringLiteral( ",userid=%1" ).arg( user );
|
uri += QStringLiteral( ",userid=%1" ).arg( username );
|
||||||
|
|
||||||
if ( !password.isEmpty() )
|
if ( !password.isEmpty() )
|
||||||
uri += QStringLiteral( ",password=%1" ).arg( password );
|
uri += QStringLiteral( ",password=%1" ).arg( password );
|
||||||
@ -76,9 +88,9 @@ QString createDatabaseURI( const QString &connectionType, const QString &host, c
|
|||||||
uri += QStringLiteral( ",port=%1" ).arg( port );
|
uri += QStringLiteral( ",port=%1" ).arg( port );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !user.isEmpty() )
|
if ( !username.isEmpty() )
|
||||||
{
|
{
|
||||||
uri += QStringLiteral( ",user=%1" ).arg( user );
|
uri += QStringLiteral( ",user=%1" ).arg( username );
|
||||||
|
|
||||||
if ( !password.isEmpty() )
|
if ( !password.isEmpty() )
|
||||||
uri += QStringLiteral( ",password=%1" ).arg( password );
|
uri += QStringLiteral( ",password=%1" ).arg( password );
|
||||||
@ -96,9 +108,9 @@ QString createDatabaseURI( const QString &connectionType, const QString &host, c
|
|||||||
uri += QStringLiteral( ",%1" ).arg( port );
|
uri += QStringLiteral( ",%1" ).arg( port );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !user.isEmpty() )
|
if ( !username.isEmpty() )
|
||||||
{
|
{
|
||||||
uri += QStringLiteral( ";uid=%1" ).arg( user );
|
uri += QStringLiteral( ";uid=%1" ).arg( username );
|
||||||
|
|
||||||
if ( !password.isEmpty() )
|
if ( !password.isEmpty() )
|
||||||
uri += QStringLiteral( ";pwd=%1" ).arg( password );
|
uri += QStringLiteral( ";pwd=%1" ).arg( password );
|
||||||
@ -111,10 +123,10 @@ QString createDatabaseURI( const QString &connectionType, const QString &host, c
|
|||||||
}
|
}
|
||||||
else if ( connectionType == QLatin1String( "Oracle Spatial" ) )
|
else if ( connectionType == QLatin1String( "Oracle Spatial" ) )
|
||||||
{
|
{
|
||||||
uri = "OCI:" + user;
|
uri = "OCI:" + username;
|
||||||
|
|
||||||
if ( ( !user.isEmpty() && !password.isEmpty() ) ||
|
if ( ( !username.isEmpty() && !password.isEmpty() ) ||
|
||||||
( user.isEmpty() && password.isEmpty() ) )
|
( username.isEmpty() && password.isEmpty() ) )
|
||||||
{
|
{
|
||||||
uri += '/';
|
uri += '/';
|
||||||
if ( !password.isEmpty() )
|
if ( !password.isEmpty() )
|
||||||
@ -142,15 +154,15 @@ QString createDatabaseURI( const QString &connectionType, const QString &host, c
|
|||||||
}
|
}
|
||||||
else if ( connectionType == QLatin1String( "ODBC" ) )
|
else if ( connectionType == QLatin1String( "ODBC" ) )
|
||||||
{
|
{
|
||||||
if ( !user.isEmpty() )
|
if ( !username.isEmpty() )
|
||||||
{
|
{
|
||||||
if ( password.isEmpty() )
|
if ( password.isEmpty() )
|
||||||
{
|
{
|
||||||
uri = "ODBC:" + user + '@' + database;
|
uri = "ODBC:" + username + '@' + database;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uri = "ODBC:" + user + '/' + password + '@' + database;
|
uri = "ODBC:" + username + '/' + password + '@' + database;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -174,9 +186,9 @@ QString createDatabaseURI( const QString &connectionType, const QString &host, c
|
|||||||
uri += QStringLiteral( " port='%1'" ).arg( port );
|
uri += QStringLiteral( " port='%1'" ).arg( port );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !user.isEmpty() )
|
if ( !username.isEmpty() )
|
||||||
{
|
{
|
||||||
uri += QStringLiteral( " user='%1'" ).arg( user );
|
uri += QStringLiteral( " user='%1'" ).arg( username );
|
||||||
|
|
||||||
if ( !password.isEmpty() )
|
if ( !password.isEmpty() )
|
||||||
uri += QStringLiteral( " password='%1'" ).arg( password );
|
uri += QStringLiteral( " password='%1'" ).arg( password );
|
||||||
@ -184,13 +196,29 @@ QString createDatabaseURI( const QString &connectionType, const QString &host, c
|
|||||||
|
|
||||||
uri += ' ';
|
uri += ' ';
|
||||||
}
|
}
|
||||||
|
// Append authentication configuration to the URI
|
||||||
|
if ( !( configId.isEmpty() ) )
|
||||||
|
{
|
||||||
|
if ( ! expandAuthConfig )
|
||||||
|
{
|
||||||
|
uri += QStringLiteral( " authcfg='%1'" ).arg( configId );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QStringList connectionItems;
|
||||||
|
connectionItems << uri;
|
||||||
|
if ( QgsApplication::authManager()->updateDataSourceUriItems( connectionItems, configId, QStringLiteral( "ogr" ) ) )
|
||||||
|
{
|
||||||
|
uri = connectionItems.join( QString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
QgsDebugMsg( "Connection type is=" + connectionType + " and uri=" + uri );
|
QgsDebugMsg( "Connection type is=" + connectionType + " and uri=" + uri );
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString createProtocolURI( const QString &type, const QString &url )
|
QString createProtocolURI( const QString &type, const QString &url, const QString &configId, const QString &username, const QString &password, bool expandAuthConfig )
|
||||||
{
|
{
|
||||||
QString uri;
|
QString uri;
|
||||||
if ( type == QLatin1String( "GeoJSON" ) )
|
if ( type == QLatin1String( "GeoJSON" ) )
|
||||||
@ -206,5 +234,26 @@ QString createProtocolURI( const QString &type, const QString &url )
|
|||||||
uri = QStringLiteral( "DODS:%1" ).arg( url );
|
uri = QStringLiteral( "DODS:%1" ).arg( url );
|
||||||
}
|
}
|
||||||
QgsDebugMsg( "Connection type is=" + type + " and uri=" + uri );
|
QgsDebugMsg( "Connection type is=" + type + " and uri=" + uri );
|
||||||
|
// Update URI with authentication information
|
||||||
|
if ( ! configId.isEmpty() )
|
||||||
|
{
|
||||||
|
if ( expandAuthConfig )
|
||||||
|
{
|
||||||
|
QStringList connectionItems;
|
||||||
|
connectionItems << uri;
|
||||||
|
if ( QgsApplication::authManager()->updateDataSourceUriItems( connectionItems, configId, QStringLiteral( "ogr" ) ) )
|
||||||
|
{
|
||||||
|
uri = connectionItems.join( QString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uri += QStringLiteral( " authcfg='%1'" ).arg( configId );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( !( username.isEmpty() || password.isEmpty( ) ) )
|
||||||
|
{
|
||||||
|
uri.replace( QStringLiteral( "://" ), QStringLiteral( "://%1:%2@" ).arg( username, password ) );
|
||||||
|
}
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,11 @@
|
|||||||
* \brief Create database uri from connection parameters
|
* \brief Create database uri from connection parameters
|
||||||
* \note not available in python bindings
|
* \note not available in python bindings
|
||||||
*/
|
*/
|
||||||
QString GUI_EXPORT createDatabaseURI( const QString &connectionType, const QString &host, const QString &database, QString port, const QString &user, const QString &password );
|
QString GUI_EXPORT createDatabaseURI( const QString &connectionType, const QString &host, const QString &database, QString port, const QString &configId, QString username, QString password, bool expandAuthConfig = false );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CreateProtocolURI
|
* CreateProtocolURI
|
||||||
* \brief Create protocol uri from connection parameters
|
* \brief Create protocol uri from connection parameters
|
||||||
* \note not available in python bindings
|
* \note not available in python bindings
|
||||||
*/
|
*/
|
||||||
QString GUI_EXPORT createProtocolURI( const QString &type, const QString &url );
|
QString GUI_EXPORT createProtocolURI( const QString &type, const QString &url, const QString &configId, const QString &username, const QString &password, bool expandAuthConfig = false );
|
||||||
|
@ -422,7 +422,7 @@ bool QgsOgrFeatureIterator::readFeature( gdal::ogr_feature_unique_ptr fet, QgsFe
|
|||||||
|
|
||||||
|
|
||||||
QgsOgrFeatureSource::QgsOgrFeatureSource( const QgsOgrProvider *p )
|
QgsOgrFeatureSource::QgsOgrFeatureSource( const QgsOgrProvider *p )
|
||||||
: mDataSource( p->dataSourceUri() )
|
: mDataSource( p->dataSourceUri( true ) )
|
||||||
, mLayerName( p->layerName() )
|
, mLayerName( p->layerName() )
|
||||||
, mLayerIndex( p->layerIndex() )
|
, mLayerIndex( p->layerIndex() )
|
||||||
, mSubsetString( p->mSubsetString )
|
, mSubsetString( p->mSubsetString )
|
||||||
|
@ -469,21 +469,33 @@ QgsOgrProvider::QgsOgrProvider( QString const &uri )
|
|||||||
|
|
||||||
setNativeTypes( nativeTypes );
|
setNativeTypes( nativeTypes );
|
||||||
|
|
||||||
QgsOgrConnPool::instance()->ref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->ref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsOgrProvider::~QgsOgrProvider()
|
QgsOgrProvider::~QgsOgrProvider()
|
||||||
{
|
{
|
||||||
QgsOgrConnPool::instance()->unref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->unref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
// We must also make sure to flush unusef cached connections so that
|
// We must also make sure to flush unusef cached connections so that
|
||||||
// the file can be removed (#15137)
|
// the file can be removed (#15137)
|
||||||
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
|
|
||||||
// Do that as last step for final cleanup that might be prevented by
|
// Do that as last step for final cleanup that might be prevented by
|
||||||
// still opened datasets.
|
// still opened datasets.
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QgsOgrProvider::dataSourceUri( bool expandAuthConfig ) const
|
||||||
|
{
|
||||||
|
if ( expandAuthConfig && QgsDataProvider::dataSourceUri( ).contains( QLatin1String( "authcfg" ) ) )
|
||||||
|
{
|
||||||
|
return QgsOgrProviderUtils::expandAuthConfig( QgsDataProvider::dataSourceUri( ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QgsDataProvider::dataSourceUri( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QgsAbstractFeatureSource *QgsOgrProvider::featureSource() const
|
QgsAbstractFeatureSource *QgsOgrProvider::featureSource() const
|
||||||
{
|
{
|
||||||
return new QgsOgrFeatureSource( this );
|
return new QgsOgrFeatureSource( this );
|
||||||
@ -549,9 +561,9 @@ bool QgsOgrProvider::setSubsetString( const QString &theSQL, bool updateFeatureC
|
|||||||
|
|
||||||
if ( uri != dataSourceUri() )
|
if ( uri != dataSourceUri() )
|
||||||
{
|
{
|
||||||
QgsOgrConnPool::instance()->unref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->unref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
setDataSourceUri( uri );
|
setDataSourceUri( uri );
|
||||||
QgsOgrConnPool::instance()->ref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->ref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
mOgrLayer->ResetReading();
|
mOgrLayer->ResetReading();
|
||||||
@ -901,7 +913,7 @@ OGRwkbGeometryType QgsOgrProvider::getOgrGeomType( OGRLayerH ogrLayer )
|
|||||||
|
|
||||||
void QgsOgrProvider::loadFields()
|
void QgsOgrProvider::loadFields()
|
||||||
{
|
{
|
||||||
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
//the attribute fields need to be read again when the encoding changes
|
//the attribute fields need to be read again when the encoding changes
|
||||||
mAttributeFields.clear();
|
mAttributeFields.clear();
|
||||||
mDefaultValues.clear();
|
mDefaultValues.clear();
|
||||||
@ -1482,7 +1494,7 @@ bool QgsOgrProvider::addAttributes( const QList<QgsField> &attributes )
|
|||||||
{
|
{
|
||||||
// adding attributes in mapinfo requires to be able to delete the .dat file
|
// adding attributes in mapinfo requires to be able to delete the .dat file
|
||||||
// so drop any cached connections.
|
// so drop any cached connections.
|
||||||
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool returnvalue = true;
|
bool returnvalue = true;
|
||||||
@ -1825,7 +1837,7 @@ bool QgsOgrProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_
|
|||||||
{
|
{
|
||||||
pushError( tr( "OGR error syncing to disk: %1" ).arg( CPLGetLastErrorMsg() ) );
|
pushError( tr( "OGR error syncing to disk: %1" ).arg( CPLGetLastErrorMsg() ) );
|
||||||
}
|
}
|
||||||
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1901,7 +1913,7 @@ bool QgsOgrProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
|
|||||||
commitTransaction();
|
commitTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
return syncToDisc();
|
return syncToDisc();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3294,7 +3306,7 @@ QByteArray QgsOgrProvider::quotedIdentifier( const QByteArray &field ) const
|
|||||||
|
|
||||||
void QgsOgrProvider::forceReload()
|
void QgsOgrProvider::forceReload()
|
||||||
{
|
{
|
||||||
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QgsOgrProviderUtils::connectionPoolId( const QString &dataSourceURI )
|
QString QgsOgrProviderUtils::connectionPoolId( const QString &dataSourceURI )
|
||||||
@ -3576,7 +3588,7 @@ QString QgsOgrProviderUtils::quotedValue( const QVariant &value )
|
|||||||
bool QgsOgrProvider::syncToDisc()
|
bool QgsOgrProvider::syncToDisc()
|
||||||
{
|
{
|
||||||
//for shapefiles, remove spatial index files and create a new index
|
//for shapefiles, remove spatial index files and create a new index
|
||||||
QgsOgrConnPool::instance()->unref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->unref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
bool shapeIndex = false;
|
bool shapeIndex = false;
|
||||||
if ( mGDALDriverName == QLatin1String( "ESRI Shapefile" ) )
|
if ( mGDALDriverName == QLatin1String( "ESRI Shapefile" ) )
|
||||||
{
|
{
|
||||||
@ -3591,7 +3603,7 @@ bool QgsOgrProvider::syncToDisc()
|
|||||||
{
|
{
|
||||||
shapeIndex = true;
|
shapeIndex = true;
|
||||||
close();
|
close();
|
||||||
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
QFile::remove( sbnIndexFile );
|
QFile::remove( sbnIndexFile );
|
||||||
open( OpenModeSameAsCurrent );
|
open( OpenModeSameAsCurrent );
|
||||||
if ( !mValid )
|
if ( !mValid )
|
||||||
@ -3615,7 +3627,7 @@ bool QgsOgrProvider::syncToDisc()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QgsOgrConnPool::instance()->ref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->ref( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
if ( shapeIndex )
|
if ( shapeIndex )
|
||||||
{
|
{
|
||||||
return createSpatialIndex();
|
return createSpatialIndex();
|
||||||
@ -3677,7 +3689,7 @@ void QgsOgrProvider::recalculateFeatureCount()
|
|||||||
mOgrLayer->SetSpatialFilter( filter );
|
mOgrLayer->SetSpatialFilter( filter );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri() ) );
|
QgsOgrConnPool::instance()->invalidateConnections( QgsOgrProviderUtils::connectionPoolId( dataSourceUri( true ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsOgrProvider::doesStrictFeatureTypeCheck() const
|
bool QgsOgrProvider::doesStrictFeatureTypeCheck() const
|
||||||
@ -4091,7 +4103,7 @@ static GDALDatasetH OpenHelper( const QString &dsName,
|
|||||||
option.toUtf8().constData() );
|
option.toUtf8().constData() );
|
||||||
}
|
}
|
||||||
GDALDatasetH hDS = QgsOgrProviderUtils::GDALOpenWrapper(
|
GDALDatasetH hDS = QgsOgrProviderUtils::GDALOpenWrapper(
|
||||||
dsName.toUtf8().constData(), updateMode, papszOpenOptions, nullptr );
|
QgsOgrProviderUtils::expandAuthConfig( dsName ).toUtf8().constData(), updateMode, papszOpenOptions, nullptr );
|
||||||
CSLDestroy( papszOpenOptions );
|
CSLDestroy( papszOpenOptions );
|
||||||
return hDS;
|
return hDS;
|
||||||
}
|
}
|
||||||
@ -4241,6 +4253,7 @@ QgsOgrLayer *QgsOgrProviderUtils::getLayer( const QString &dsName,
|
|||||||
QString &errCause )
|
QString &errCause )
|
||||||
{
|
{
|
||||||
QMutexLocker locker( &globalMutex );
|
QMutexLocker locker( &globalMutex );
|
||||||
|
|
||||||
for ( auto iter = mapSharedDS.begin(); iter != mapSharedDS.end(); ++iter )
|
for ( auto iter = mapSharedDS.begin(); iter != mapSharedDS.end(); ++iter )
|
||||||
{
|
{
|
||||||
if ( iter.key().dsName == dsName )
|
if ( iter.key().dsName == dsName )
|
||||||
@ -4290,6 +4303,26 @@ static QDateTime getLastModified( const QString &dsName )
|
|||||||
return QFileInfo( dsName ).lastModified();
|
return QFileInfo( dsName ).lastModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QgsOgrProviderUtils::expandAuthConfig( const QString &dsName )
|
||||||
|
{
|
||||||
|
QString uri( dsName );
|
||||||
|
// Check for authcfg
|
||||||
|
QRegularExpression authcfgRe( " authcfg='([^']+)'" );
|
||||||
|
QRegularExpressionMatch match;
|
||||||
|
if ( uri.contains( authcfgRe, &match ) )
|
||||||
|
{
|
||||||
|
uri = uri.replace( match.captured( 0 ), QString() );
|
||||||
|
QString configId( match.captured( 1 ) );
|
||||||
|
QStringList connectionItems;
|
||||||
|
connectionItems << uri;
|
||||||
|
if ( QgsApplication::authManager()->updateDataSourceUriItems( connectionItems, configId, QStringLiteral( "ogr" ) ) )
|
||||||
|
{
|
||||||
|
uri = connectionItems.first( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
// Must be called under the globalMutex
|
// Must be called under the globalMutex
|
||||||
bool QgsOgrProviderUtils::canUseOpenedDatasets( const QString &dsName )
|
bool QgsOgrProviderUtils::canUseOpenedDatasets( const QString &dsName )
|
||||||
{
|
{
|
||||||
|
@ -64,6 +64,18 @@ class QgsOgrProvider : public QgsVectorDataProvider
|
|||||||
|
|
||||||
virtual ~QgsOgrProvider();
|
virtual ~QgsOgrProvider();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data source specification. This may be a path or database
|
||||||
|
* connection string
|
||||||
|
* \param expandAuthConfig Whether to expand any assigned authentication configuration
|
||||||
|
* \returns data source specification
|
||||||
|
* \note The default authentication configuration expansion is FALSE. This keeps credentials
|
||||||
|
* out of layer data source URIs and project files. Expansion should be specifically done
|
||||||
|
* only when needed within a provider
|
||||||
|
*/
|
||||||
|
QString dataSourceUri( bool expandAuthConfig = false ) const override;
|
||||||
|
|
||||||
|
|
||||||
virtual QgsAbstractFeatureSource *featureSource() const override;
|
virtual QgsAbstractFeatureSource *featureSource() const override;
|
||||||
|
|
||||||
virtual QgsCoordinateReferenceSystem crs() const override;
|
virtual QgsCoordinateReferenceSystem crs() const override;
|
||||||
@ -325,6 +337,10 @@ class QgsOgrProviderUtils
|
|||||||
static bool canUseOpenedDatasets( const QString &dsName );
|
static bool canUseOpenedDatasets( const QString &dsName );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//! Inject credentials into the dsName (if any)
|
||||||
|
static QString expandAuthConfig( const QString &dsName );
|
||||||
|
|
||||||
static void setRelevantFields( OGRLayerH ogrLayer, int fieldCount, bool fetchGeometry, const QgsAttributeList &fetchAttributes, bool firstAttrIsFid );
|
static void setRelevantFields( OGRLayerH ogrLayer, int fieldCount, bool fetchGeometry, const QgsAttributeList &fetchAttributes, bool firstAttrIsFid );
|
||||||
static OGRLayerH setSubsetString( OGRLayerH layer, GDALDatasetH ds, QTextCodec *encoding, const QString &subsetString, bool &origFidAdded );
|
static OGRLayerH setSubsetString( OGRLayerH layer, GDALDatasetH ds, QTextCodec *encoding, const QString &subsetString, bool &origFidAdded );
|
||||||
static QByteArray quotedIdentifier( QByteArray field, const QString &driverName );
|
static QByteArray quotedIdentifier( QByteArray field, const QString &driverName );
|
||||||
|
@ -123,6 +123,8 @@ QgsOgrSourceSelect::QgsOgrSourceSelect( QWidget *parent, Qt::WindowFlags fl, Qgs
|
|||||||
if ( radioSrcProtocol->isChecked() )
|
if ( radioSrcProtocol->isChecked() )
|
||||||
emit enableButtons( !text.isEmpty() );
|
emit enableButtons( !text.isEmpty() );
|
||||||
} );
|
} );
|
||||||
|
// Set filter for ogr compatible auth methods
|
||||||
|
mAuthSettingsProtocol->setDataprovider( QStringLiteral( "ogr" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsOgrSourceSelect::~QgsOgrSourceSelect()
|
QgsOgrSourceSelect::~QgsOgrSourceSelect()
|
||||||
@ -179,6 +181,7 @@ void QgsOgrSourceSelect::deleteConnection()
|
|||||||
settings.remove( key + "/password" );
|
settings.remove( key + "/password" );
|
||||||
settings.remove( key + "/port" );
|
settings.remove( key + "/port" );
|
||||||
settings.remove( key + "/save" );
|
settings.remove( key + "/save" );
|
||||||
|
settings.remove( key + "/autchcfg" );
|
||||||
settings.remove( key );
|
settings.remove( key );
|
||||||
cmbConnections->removeItem( cmbConnections->currentIndex() ); // populateConnectionList();
|
cmbConnections->removeItem( cmbConnections->currentIndex() ); // populateConnectionList();
|
||||||
setConnectionListPosition();
|
setConnectionListPosition();
|
||||||
@ -285,9 +288,10 @@ void QgsOgrSourceSelect::addButtonClicked()
|
|||||||
QString port = settings.value( baseKey + "/port" ).toString();
|
QString port = settings.value( baseKey + "/port" ).toString();
|
||||||
QString user = settings.value( baseKey + "/username" ).toString();
|
QString user = settings.value( baseKey + "/username" ).toString();
|
||||||
QString pass = settings.value( baseKey + "/password" ).toString();
|
QString pass = settings.value( baseKey + "/password" ).toString();
|
||||||
|
QString configid = settings.value( baseKey + "/configid" ).toString();
|
||||||
|
|
||||||
bool makeConnection = false;
|
bool makeConnection = false;
|
||||||
if ( pass.isEmpty() )
|
if ( pass.isEmpty() && configid.isEmpty( ) )
|
||||||
{
|
{
|
||||||
if ( cmbDatabaseTypes->currentText() == QLatin1String( "MSSQL" ) )
|
if ( cmbDatabaseTypes->currentText() == QLatin1String( "MSSQL" ) )
|
||||||
makeConnection = true;
|
makeConnection = true;
|
||||||
@ -299,13 +303,14 @@ void QgsOgrSourceSelect::addButtonClicked()
|
|||||||
&makeConnection );
|
&makeConnection );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( makeConnection || !pass.isEmpty() )
|
if ( makeConnection || !( pass.isEmpty() && configid.isEmpty( ) ) )
|
||||||
{
|
{
|
||||||
mDataSources << createDatabaseURI(
|
mDataSources << createDatabaseURI(
|
||||||
cmbDatabaseTypes->currentText(),
|
cmbDatabaseTypes->currentText(),
|
||||||
host,
|
host,
|
||||||
database,
|
database,
|
||||||
port,
|
port,
|
||||||
|
configid,
|
||||||
user,
|
user,
|
||||||
pass
|
pass
|
||||||
);
|
);
|
||||||
@ -321,7 +326,11 @@ void QgsOgrSourceSelect::addButtonClicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDataSources << createProtocolURI( cmbProtocolTypes->currentText(), protocolURI->text() );
|
mDataSources << createProtocolURI( cmbProtocolTypes->currentText(),
|
||||||
|
protocolURI->text(),
|
||||||
|
mAuthSettingsProtocol->configId(),
|
||||||
|
mAuthSettingsProtocol->username(),
|
||||||
|
mAuthSettingsProtocol->password() );
|
||||||
}
|
}
|
||||||
else if ( radioSrcFile->isChecked() )
|
else if ( radioSrcFile->isChecked() )
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>404</width>
|
<width>404</width>
|
||||||
<height>348</height>
|
<height>386</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -25,7 +25,7 @@
|
|||||||
<property name="modal">
|
<property name="modal">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout">
|
<layout class="QGridLayout" name="grLayout1">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>9</number>
|
<number>9</number>
|
||||||
</property>
|
</property>
|
||||||
@ -41,42 +41,77 @@
|
|||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QGroupBox" name="GroupBox1">
|
<widget class="QGroupBox" name="GroupBox1">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Connection Information</string>
|
<string>Connection Information</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_1">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="8" column="0" colspan="4">
|
||||||
|
<widget class="QPushButton" name="btnConnect">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Test Connection</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0" rowspan="3" colspan="4">
|
||||||
|
<widget class="QGroupBox" name="mAuthGroupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Authentication</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QgsAuthSettingsWidget" name="mAuthSettingsDatabase" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Type</string>
|
<string>&Type</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>cmbDatabaseTypes</cstring>
|
<cstring>cmbDatabaseTypes</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1" colspan="2">
|
|
||||||
<widget class="QComboBox" name="cmbDatabaseTypes"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="TextLabel1_2">
|
<widget class="QLabel" name="TextLabel1_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Name</string>
|
<string>&Name</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>txtName</cstring>
|
<cstring>txtName</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1" colspan="2">
|
|
||||||
<widget class="QLineEdit" name="txtName">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Name of the new connection</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="TextLabel1">
|
<widget class="QLabel" name="TextLabel1">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -87,22 +122,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1" colspan="2">
|
|
||||||
<widget class="QLineEdit" name="txtHost"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="TextLabel2">
|
<widget class="QLabel" name="TextLabel2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Database</string>
|
<string>&Database</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>txtDatabase</cstring>
|
<cstring>txtDatabase</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1" colspan="2">
|
|
||||||
<widget class="QLineEdit" name="txtDatabase"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="TextLabel2_2">
|
<widget class="QLabel" name="TextLabel2_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -113,87 +142,48 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1" colspan="2">
|
<item row="1" column="1" colspan="3">
|
||||||
|
<widget class="QLineEdit" name="txtName">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Name of the new connection</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" colspan="3">
|
||||||
|
<widget class="QComboBox" name="cmbDatabaseTypes"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1" colspan="3">
|
||||||
|
<widget class="QLineEdit" name="txtHost"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1" colspan="3">
|
||||||
|
<widget class="QLineEdit" name="txtDatabase"/>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1" colspan="3">
|
||||||
<widget class="QLineEdit" name="txtPort">
|
<widget class="QLineEdit" name="txtPort">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="TextLabel3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Username</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>txtUsername</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1" colspan="2">
|
|
||||||
<widget class="QLineEdit" name="txtUsername"/>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="TextLabel3_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Password</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>txtPassword</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1" colspan="2">
|
|
||||||
<widget class="QgsPasswordLineEdit" name="txtPassword">
|
|
||||||
<property name="echoMode">
|
|
||||||
<enum>QLineEdit::Password</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="0">
|
|
||||||
<widget class="QCheckBox" name="chkStorePassword">
|
|
||||||
<property name="text">
|
|
||||||
<string>Save Password</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="2">
|
|
||||||
<widget class="QPushButton" name="btnConnect">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Test Connect</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>QgsPasswordLineEdit</class>
|
<class>QgsAuthSettingsWidget</class>
|
||||||
<extends>QLineEdit</extends>
|
<extends>QWidget</extends>
|
||||||
<header>qgspasswordlineedit.h</header>
|
<header>auth/qgsauthsettingswidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>cmbDatabaseTypes</tabstop>
|
|
||||||
<tabstop>txtName</tabstop>
|
<tabstop>txtName</tabstop>
|
||||||
<tabstop>txtHost</tabstop>
|
<tabstop>txtHost</tabstop>
|
||||||
<tabstop>txtDatabase</tabstop>
|
<tabstop>txtDatabase</tabstop>
|
||||||
<tabstop>txtPort</tabstop>
|
<tabstop>txtPort</tabstop>
|
||||||
<tabstop>txtUsername</tabstop>
|
|
||||||
<tabstop>txtPassword</tabstop>
|
|
||||||
<tabstop>chkStorePassword</tabstop>
|
|
||||||
<tabstop>btnConnect</tabstop>
|
|
||||||
<tabstop>buttonBox</tabstop>
|
<tabstop>buttonBox</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>450</width>
|
<width>450</width>
|
||||||
<height>575</height>
|
<height>658</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -26,15 +26,76 @@
|
|||||||
<iconset>
|
<iconset>
|
||||||
<normaloff>.</normaloff>.</iconset>
|
<normaloff>.</normaloff>.</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
<item row="5" column="0">
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QGroupBox" name="srcGroupBox_2">
|
||||||
<property name="standardButtons">
|
<property name="sizePolicy">
|
||||||
<set>QDialogButtonBox::Help</set>
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Source type</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioSrcFile">
|
||||||
|
<property name="text">
|
||||||
|
<string>F&ile</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioSrcDirectory">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Directory</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioSrcDatabase">
|
||||||
|
<property name="text">
|
||||||
|
<string>Da&tabase</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioSrcProtocol">
|
||||||
|
<property name="text">
|
||||||
|
<string>Protoco&l</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Encoding</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="cmbEncodings">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>341</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
<widget class="QGroupBox" name="protocolGroupBox">
|
<widget class="QGroupBox" name="protocolGroupBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
@ -52,19 +113,19 @@
|
|||||||
<string>Protocol</string>
|
<string>Protocol</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="0" column="1" rowspan="2">
|
|
||||||
<widget class="QComboBox" name="cmbProtocolTypes"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" rowspan="2">
|
<item row="1" column="0" rowspan="2">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>URI</string>
|
<string>&URI</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>protocolURI</cstring>
|
<cstring>protocolURI</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="1" rowspan="2">
|
||||||
|
<widget class="QComboBox" name="cmbProtocolTypes"/>
|
||||||
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLineEdit" name="protocolURI"/>
|
<widget class="QLineEdit" name="protocolURI"/>
|
||||||
</item>
|
</item>
|
||||||
@ -75,10 +136,41 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QGroupBox" name="mAuthGroupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Authentication</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QgsAuthSettingsWidget" name="mAuthSettingsProtocol" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
<widget class="QGroupBox" name="fileGroupBox">
|
<widget class="QGroupBox" name="fileGroupBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
@ -124,12 +216,12 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QgsFileWidget" name="mFileWidget"/>
|
<widget class="QgsFileWidget" name="mFileWidget" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item>
|
||||||
<widget class="QGroupBox" name="dbGroupBox">
|
<widget class="QGroupBox" name="dbGroupBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
@ -206,75 +298,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QGroupBox" name="srcGroupBox_2">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="title">
|
|
||||||
<string>Source type</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="radioSrcFile">
|
|
||||||
<property name="text">
|
|
||||||
<string>File</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="radioSrcDirectory">
|
|
||||||
<property name="text">
|
|
||||||
<string>Directory</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="radioSrcDatabase">
|
|
||||||
<property name="text">
|
|
||||||
<string>Database</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="radioSrcProtocol">
|
|
||||||
<property name="text">
|
|
||||||
<string>Protocol</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Encoding</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="cmbEncodings">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>341</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -287,6 +311,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Help</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
@ -296,6 +327,12 @@
|
|||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>qgsfilewidget.h</header>
|
<header>qgsfilewidget.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>QgsAuthSettingsWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>auth/qgsauthsettingswidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>radioSrcFile</tabstop>
|
<tabstop>radioSrcFile</tabstop>
|
||||||
@ -316,38 +353,6 @@
|
|||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>QgsOgrSourceSelectDialogBase</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>451</x>
|
|
||||||
<y>699</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>481</x>
|
|
||||||
<y>297</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>QgsOgrSourceSelectDialogBase</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>392</x>
|
|
||||||
<y>699</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>281</x>
|
|
||||||
<y>339</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
<connection>
|
||||||
<sender>radioSrcDatabase</sender>
|
<sender>radioSrcDatabase</sender>
|
||||||
<signal>toggled(bool)</signal>
|
<signal>toggled(bool)</signal>
|
||||||
|
@ -196,6 +196,7 @@ ADD_PYTHON_TEST(PyQgsSourceSelectProvider test_qgssourceselectprovider.py)
|
|||||||
ADD_PYTHON_TEST(PyQgsAuthManagerProxy test_authmanager_proxy.py)
|
ADD_PYTHON_TEST(PyQgsAuthManagerProxy test_authmanager_proxy.py)
|
||||||
ADD_PYTHON_TEST(PyQgsAuthSettingsWidget test_authsettingswidget.py)
|
ADD_PYTHON_TEST(PyQgsAuthSettingsWidget test_authsettingswidget.py)
|
||||||
ADD_PYTHON_TEST(PyQgsAuxiliaryStorage test_qgsauxiliarystorage.py)
|
ADD_PYTHON_TEST(PyQgsAuxiliaryStorage test_qgsauxiliarystorage.py)
|
||||||
|
ADD_PYTHON_TEST(PyQgsAuthManagerOgr test_authmanager_ogr.py)
|
||||||
|
|
||||||
IF (NOT WIN32)
|
IF (NOT WIN32)
|
||||||
ADD_PYTHON_TEST(PyQgsLogger test_qgslogger.py)
|
ADD_PYTHON_TEST(PyQgsLogger test_qgslogger.py)
|
||||||
@ -216,7 +217,8 @@ IF (ENABLE_PGTEST)
|
|||||||
ADD_PYTHON_TEST(PyQgsVectorLayerTools test_qgsvectorlayertools.py)
|
ADD_PYTHON_TEST(PyQgsVectorLayerTools test_qgsvectorlayertools.py)
|
||||||
ADD_PYTHON_TEST(PyQgsAuthManagerPKIPostgresTest test_authmanager_pki_postgres.py)
|
ADD_PYTHON_TEST(PyQgsAuthManagerPKIPostgresTest test_authmanager_pki_postgres.py)
|
||||||
ADD_PYTHON_TEST(PyQgsAuthManagerPasswordPostgresTest test_authmanager_password_postgres.py)
|
ADD_PYTHON_TEST(PyQgsAuthManagerPasswordPostgresTest test_authmanager_password_postgres.py)
|
||||||
ENDIF (ENABLE_PGTEST)
|
ADD_PYTHON_TEST(PyQgsAuthManagerOgrPostgresTest test_authmanager_ogr_postgres.py)
|
||||||
|
ENDIF (ENABLE_PGTEST)
|
||||||
|
|
||||||
IF (ENABLE_MSSQLTEST)
|
IF (ENABLE_MSSQLTEST)
|
||||||
ADD_PYTHON_TEST(PyQgsMssqlProvider test_provider_mssql.py)
|
ADD_PYTHON_TEST(PyQgsMssqlProvider test_provider_mssql.py)
|
||||||
|
@ -90,6 +90,16 @@ if os.environ.get('QGIS_SERVER_HTTP_BASIC_AUTH') is not None:
|
|||||||
|
|
||||||
class HTTPBasicFilter(QgsServerFilter):
|
class HTTPBasicFilter(QgsServerFilter):
|
||||||
|
|
||||||
|
def requestReady(self):
|
||||||
|
handler = self.serverInterface().requestHandler()
|
||||||
|
auth = self.serverInterface().requestHandler().requestHeader('HTTP_AUTHORIZATION')
|
||||||
|
if auth:
|
||||||
|
username, password = base64.b64decode(auth[6:]).split(b':')
|
||||||
|
if (username.decode('utf-8') == os.environ.get('QGIS_SERVER_USERNAME', 'username') and
|
||||||
|
password.decode('utf-8') == os.environ.get('QGIS_SERVER_PASSWORD', 'password')):
|
||||||
|
return
|
||||||
|
handler.setParameter('SERVICE', 'ACCESS_DENIED')
|
||||||
|
|
||||||
def responseComplete(self):
|
def responseComplete(self):
|
||||||
handler = self.serverInterface().requestHandler()
|
handler = self.serverInterface().requestHandler()
|
||||||
auth = self.serverInterface().requestHandler().requestHeader('HTTP_AUTHORIZATION')
|
auth = self.serverInterface().requestHandler().requestHeader('HTTP_AUTHORIZATION')
|
||||||
|
112
tests/src/python/test_authmanager_ogr.py
Normal file
112
tests/src/python/test_authmanager_ogr.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Tests for auth manager Basic Auth OGR connection credentials injection
|
||||||
|
|
||||||
|
From build dir, run: ctest -R PyQgsAuthManagerOgr -V
|
||||||
|
|
||||||
|
.. note:: 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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from qgis.core import (
|
||||||
|
QgsApplication,
|
||||||
|
QgsAuthManager,
|
||||||
|
QgsAuthMethodConfig,
|
||||||
|
QgsDataSourceUri,
|
||||||
|
QgsProviderRegistry,
|
||||||
|
)
|
||||||
|
|
||||||
|
from qgis.testing import (
|
||||||
|
start_app,
|
||||||
|
unittest,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
__author__ = 'Alessandro Pasotti'
|
||||||
|
__date__ = '14/11/2017'
|
||||||
|
__copyright__ = 'Copyright 2017, The QGIS Project'
|
||||||
|
# This will get replaced with a git SHA1 when you do a git archive
|
||||||
|
__revision__ = '$Format:%H$'
|
||||||
|
|
||||||
|
|
||||||
|
qgis_app = start_app()
|
||||||
|
|
||||||
|
# Note: value is checked with "in" because some drivers may need additional arguments,
|
||||||
|
# like temporary paths with rootcerts for PG
|
||||||
|
TEST_URIS = {
|
||||||
|
"http://mysite.com/geojson authcfg='%s'": "http://username:password@mysite.com/geojson",
|
||||||
|
"PG:\"dbname='databasename' host='addr' port='5432' authcfg='%s'\"": "PG:\"dbname='databasename' host='addr' port='5432' user='username' password='password'",
|
||||||
|
'SDE:127.0.0.1,12345,dbname, authcfg=\'%s\'': 'SDE:127.0.0.1,12345,dbname,username,password',
|
||||||
|
'IDB:"server=demo_on user=informix dbname=frames authcfg=\'%s\'"': 'IDB:"server=demo_on user=informix dbname=frames user=username pass=password"',
|
||||||
|
'@driver=ingres,dbname=test,tables=usa/canada authcfg=\'%s\'': '@driver=ingres,dbname=test,tables=usa/canada,userid=username,password=password',
|
||||||
|
'MySQL:westholland,port=3306,tables=bedrijven authcfg=\'%s\'': 'MySQL:westholland,port=3306,tables=bedrijven,user=username,password=password',
|
||||||
|
'MSSQL:server=.\MSSQLSERVER2008;database=dbname;trusted_connection=yes authcfg=\'%s\'': 'MSSQL:server=.\MSSQLSERVER2008;database=dbname;uid=username;pwd=password',
|
||||||
|
'OCI:/@database_instance:table,table authcfg=\'%s\'': 'OCI:username/password@database_instance:table,table',
|
||||||
|
'ODBC:database_instance authcfg=\'%s\'': 'ODBC:username/password@database_instance',
|
||||||
|
'couchdb://myconnection authcfg=\'%s\'': 'couchdb://username:password@myconnection',
|
||||||
|
'http://www.myconnection.com/geojson authcfg=\'%s\'': 'http://username:password@www.myconnection.com/geojson',
|
||||||
|
'https://www.myconnection.com/geojson authcfg=\'%s\'': 'https://username:password@www.myconnection.com/geojson',
|
||||||
|
'ftp://www.myconnection.com/geojson authcfg=\'%s\'': 'ftp://username:password@www.myconnection.com/geojson',
|
||||||
|
'DODS://www.myconnection.com/geojson authcfg=\'%s\'': 'DODS://username:password@www.myconnection.com/geojson',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestAuthManager(unittest.TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpAuth(cls):
|
||||||
|
"""Run before all tests and set up authentication"""
|
||||||
|
authm = QgsApplication.authManager()
|
||||||
|
assert (authm.setMasterPassword('masterpassword', True))
|
||||||
|
# Client side
|
||||||
|
cls.auth_config = QgsAuthMethodConfig("Basic")
|
||||||
|
cls.auth_config.setConfig('username', cls.username)
|
||||||
|
cls.auth_config.setConfig('password', cls.password)
|
||||||
|
cls.auth_config.setName('test_basic_auth_config')
|
||||||
|
assert (authm.storeAuthenticationConfig(cls.auth_config)[0])
|
||||||
|
assert cls.auth_config.isValid()
|
||||||
|
cls.authcfg = cls.auth_config.id()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
"""Run before all tests:
|
||||||
|
Creates an auth configuration"""
|
||||||
|
cls.username = 'username'
|
||||||
|
cls.password = 'password'
|
||||||
|
cls.dbname = 'test_basic'
|
||||||
|
cls.hostname = 'localhost'
|
||||||
|
cls.setUpAuth()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
"""Run after all tests"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Run before each test."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""Run after each test."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def testConnections(self):
|
||||||
|
"""
|
||||||
|
Test credentials injection
|
||||||
|
"""
|
||||||
|
pr = QgsProviderRegistry.instance().createProvider('ogr', '')
|
||||||
|
for uri, expanded in TEST_URIS.items():
|
||||||
|
pr.setDataSourceUri(uri % self.authcfg)
|
||||||
|
self.assertTrue(expanded in pr.dataSourceUri(True), "%s != %s" % (expanded, pr.dataSourceUri(True)))
|
||||||
|
|
||||||
|
# Test sublayers
|
||||||
|
for uri, expanded in TEST_URIS.items():
|
||||||
|
pr.setDataSourceUri((uri + '|sublayer1') % self.authcfg)
|
||||||
|
self.assertEqual(pr.dataSourceUri(True).split('|')[1], "sublayer1", pr.dataSourceUri(True))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
246
tests/src/python/test_authmanager_ogr_postgres.py
Normal file
246
tests/src/python/test_authmanager_ogr_postgres.py
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Tests for auth manager Basic Auth access to postgres.
|
||||||
|
|
||||||
|
This is an integration test for QGIS Desktop Auth Manager postgres provider that
|
||||||
|
checks if QGIS can use a stored auth manager auth configuration to access
|
||||||
|
a username/password protected postgres.
|
||||||
|
|
||||||
|
Configuration from the environment:
|
||||||
|
|
||||||
|
* QGIS_POSTGRES_SERVER_PORT (default: 55432)
|
||||||
|
* QGIS_POSTGRES_EXECUTABLE_PATH (default: /usr/lib/postgresql/9.4/bin)
|
||||||
|
|
||||||
|
|
||||||
|
From build dir, run: ctest -R PyQgsAuthManagerOgrPostgresTest -V
|
||||||
|
|
||||||
|
or, if your PostgreSQL path differs from the default:
|
||||||
|
|
||||||
|
QGIS_POSTGRES_EXECUTABLE_PATH=/usr/lib/postgresql/<your_version_goes_here>/bin \
|
||||||
|
ctest -R PyQgsAuthManagerOgrPostgresTest -V
|
||||||
|
|
||||||
|
.. note:: 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.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import signal
|
||||||
|
import stat
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
from shutil import rmtree
|
||||||
|
|
||||||
|
from utilities import unitTestDataPath
|
||||||
|
from qgis.core import (
|
||||||
|
QgsApplication,
|
||||||
|
QgsAuthManager,
|
||||||
|
QgsAuthMethodConfig,
|
||||||
|
QgsVectorLayer,
|
||||||
|
QgsDataSourceUri,
|
||||||
|
QgsWkbTypes,
|
||||||
|
)
|
||||||
|
|
||||||
|
from qgis.PyQt.QtNetwork import QSslCertificate
|
||||||
|
|
||||||
|
from qgis.testing import (
|
||||||
|
start_app,
|
||||||
|
unittest,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
__author__ = 'Alessandro Pasotti'
|
||||||
|
__date__ = '03/11/2017'
|
||||||
|
__copyright__ = 'Copyright 2017, The QGIS Project'
|
||||||
|
# This will get replaced with a git SHA1 when you do a git archive
|
||||||
|
__revision__ = '$Format:%H$'
|
||||||
|
|
||||||
|
QGIS_POSTGRES_SERVER_PORT = os.environ.get('QGIS_POSTGRES_SERVER_PORT', '55432')
|
||||||
|
QGIS_POSTGRES_EXECUTABLE_PATH = os.environ.get('QGIS_POSTGRES_EXECUTABLE_PATH', '/usr/lib/postgresql/9.4/bin')
|
||||||
|
|
||||||
|
assert os.path.exists(QGIS_POSTGRES_EXECUTABLE_PATH)
|
||||||
|
|
||||||
|
QGIS_AUTH_DB_DIR_PATH = tempfile.mkdtemp()
|
||||||
|
|
||||||
|
# Postgres test path
|
||||||
|
QGIS_PG_TEST_PATH = tempfile.mkdtemp()
|
||||||
|
|
||||||
|
os.environ['QGIS_AUTH_DB_DIR_PATH'] = QGIS_AUTH_DB_DIR_PATH
|
||||||
|
|
||||||
|
qgis_app = start_app()
|
||||||
|
|
||||||
|
QGIS_POSTGRES_CONF_TEMPLATE = """
|
||||||
|
hba_file = '%(tempfolder)s/pg_hba.conf'
|
||||||
|
listen_addresses = '*'
|
||||||
|
port = %(port)s
|
||||||
|
max_connections = 100
|
||||||
|
unix_socket_directories = '%(tempfolder)s'
|
||||||
|
ssl = true
|
||||||
|
ssl_ciphers = 'DEFAULT:!LOW:!EXP:!MD5:@STRENGTH' # allowed SSL ciphers
|
||||||
|
ssl_cert_file = '%(server_cert)s'
|
||||||
|
ssl_key_file = '%(server_key)s'
|
||||||
|
ssl_ca_file = '%(sslrootcert_path)s'
|
||||||
|
password_encryption = on
|
||||||
|
"""
|
||||||
|
|
||||||
|
QGIS_POSTGRES_HBA_TEMPLATE = """
|
||||||
|
hostssl all all 0.0.0.0/0 md5
|
||||||
|
hostssl all all ::1/0 md5
|
||||||
|
host all all 127.0.0.1/32 trust
|
||||||
|
host all all ::1/32 trust
|
||||||
|
|
||||||
|
host all all 0.0.0.0/0 trust
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class TestAuthManager(unittest.TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpAuth(cls):
|
||||||
|
"""Run before all tests and set up authentication"""
|
||||||
|
authm = QgsApplication.authManager()
|
||||||
|
assert (authm.setMasterPassword('masterpassword', True))
|
||||||
|
cls.pg_conf = os.path.join(cls.tempfolder, 'postgresql.conf')
|
||||||
|
cls.pg_hba = os.path.join(cls.tempfolder, 'pg_hba.conf')
|
||||||
|
# Client side
|
||||||
|
cls.sslrootcert_path = os.path.join(cls.certsdata_path, 'chains_subissuer-issuer-root_issuer2-root2.pem')
|
||||||
|
assert os.path.isfile(cls.sslrootcert_path)
|
||||||
|
os.chmod(cls.sslrootcert_path, stat.S_IRUSR)
|
||||||
|
cls.auth_config = QgsAuthMethodConfig("Basic")
|
||||||
|
cls.auth_config.setConfig('username', cls.username)
|
||||||
|
cls.auth_config.setConfig('password', cls.password)
|
||||||
|
cls.auth_config.setName('test_basic_auth_config')
|
||||||
|
cls.sslrootcert = QSslCertificate.fromPath(cls.sslrootcert_path)
|
||||||
|
assert cls.sslrootcert is not None
|
||||||
|
authm.storeCertAuthorities(cls.sslrootcert)
|
||||||
|
authm.rebuildCaCertsCache()
|
||||||
|
authm.rebuildTrustedCaCertsCache()
|
||||||
|
authm.rebuildCertTrustCache()
|
||||||
|
assert (authm.storeAuthenticationConfig(cls.auth_config)[0])
|
||||||
|
assert cls.auth_config.isValid()
|
||||||
|
cls.authcfg = cls.auth_config.id()
|
||||||
|
|
||||||
|
# Server side
|
||||||
|
cls.server_cert = os.path.join(cls.certsdata_path, 'localhost_ssl_cert.pem')
|
||||||
|
cls.server_key = os.path.join(cls.certsdata_path, 'localhost_ssl_key.pem')
|
||||||
|
cls.server_rootcert = cls.sslrootcert_path
|
||||||
|
os.chmod(cls.server_cert, stat.S_IRUSR)
|
||||||
|
os.chmod(cls.server_key, stat.S_IRUSR)
|
||||||
|
os.chmod(cls.server_rootcert, stat.S_IRUSR)
|
||||||
|
|
||||||
|
# Place conf in the data folder
|
||||||
|
with open(cls.pg_conf, 'w+') as f:
|
||||||
|
f.write(QGIS_POSTGRES_CONF_TEMPLATE % {
|
||||||
|
'port': cls.port,
|
||||||
|
'tempfolder': cls.tempfolder,
|
||||||
|
'server_cert': cls.server_cert,
|
||||||
|
'server_key': cls.server_key,
|
||||||
|
'sslrootcert_path': cls.sslrootcert_path,
|
||||||
|
})
|
||||||
|
|
||||||
|
with open(cls.pg_hba, 'w+') as f:
|
||||||
|
f.write(QGIS_POSTGRES_HBA_TEMPLATE)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
"""Run before all tests:
|
||||||
|
Creates an auth configuration"""
|
||||||
|
cls.port = QGIS_POSTGRES_SERVER_PORT
|
||||||
|
cls.username = 'username'
|
||||||
|
cls.password = 'password'
|
||||||
|
cls.dbname = 'test_basic'
|
||||||
|
cls.tempfolder = QGIS_PG_TEST_PATH
|
||||||
|
cls.certsdata_path = os.path.join(unitTestDataPath('auth_system'), 'certs_keys')
|
||||||
|
cls.hostname = 'localhost'
|
||||||
|
cls.data_path = os.path.join(cls.tempfolder, 'data')
|
||||||
|
os.mkdir(cls.data_path)
|
||||||
|
|
||||||
|
cls.setUpAuth()
|
||||||
|
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'initdb'), '-D', cls.data_path])
|
||||||
|
|
||||||
|
# Disable SSL verification for setup operations
|
||||||
|
env = dict(os.environ)
|
||||||
|
env['PGSSLMODE'] = 'disable'
|
||||||
|
|
||||||
|
cls.server = subprocess.Popen([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'postgres'), '-D',
|
||||||
|
cls.data_path, '-c',
|
||||||
|
"config_file=%s" % cls.pg_conf],
|
||||||
|
env=env,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
# Wait max 10 secs for the server to start
|
||||||
|
end = time.time() + 10
|
||||||
|
while True:
|
||||||
|
line = cls.server.stderr.readline()
|
||||||
|
print(line)
|
||||||
|
if line.find(b"database system is ready to accept") != -1:
|
||||||
|
break
|
||||||
|
if time.time() > end:
|
||||||
|
raise Exception("Timeout connecting to PostgreSQL")
|
||||||
|
# Create a DB
|
||||||
|
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'createdb'), '-h', 'localhost', '-p', cls.port, 'test_basic'], env=env)
|
||||||
|
# Inject test SQL from test path
|
||||||
|
test_sql = os.path.join(unitTestDataPath('provider'), 'testdata_pg.sql')
|
||||||
|
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'psql'), '-h', 'localhost', '-p', cls.port, '-f', test_sql, cls.dbname], env=env)
|
||||||
|
# Create a role
|
||||||
|
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'psql'), '-h', 'localhost', '-p', cls.port, '-c', 'CREATE ROLE "%s" WITH SUPERUSER LOGIN PASSWORD \'%s\'' % (cls.username, cls.password), cls.dbname], env=env)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
"""Run after all tests"""
|
||||||
|
cls.server.terminate()
|
||||||
|
os.kill(cls.server.pid, signal.SIGABRT)
|
||||||
|
del cls.server
|
||||||
|
time.sleep(2)
|
||||||
|
rmtree(QGIS_AUTH_DB_DIR_PATH)
|
||||||
|
rmtree(cls.tempfolder)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Run before each test."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""Run after each test."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _getPostGISLayer(cls, type_name, layer_name=None, authcfg=''):
|
||||||
|
"""
|
||||||
|
PG layer factory
|
||||||
|
"""
|
||||||
|
if layer_name is None:
|
||||||
|
layer_name = 'pg_' + type_name
|
||||||
|
|
||||||
|
# Warning: OGR needs the schema if it's not the default, so qgis_test.someData
|
||||||
|
connstring = "PG:dbname='%(dbname)s' host='%(hostname)s' port='%(port)s' sslmode='verify-full' sslrootcert='%(sslrootcert)s'%(authcfg)s|layername=qgis_test.someData" % (
|
||||||
|
{
|
||||||
|
'dbname': cls.dbname,
|
||||||
|
'hostname': cls.hostname,
|
||||||
|
'port': cls.port,
|
||||||
|
'authcfg': ' authcfg=\'%s\'' % authcfg if authcfg else '',
|
||||||
|
'sslrootcert': cls.sslrootcert_path,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
layer = QgsVectorLayer(connstring, layer_name, 'ogr')
|
||||||
|
return layer
|
||||||
|
|
||||||
|
def testValidAuthAccess(self):
|
||||||
|
"""
|
||||||
|
Access the protected layer with valid credentials
|
||||||
|
"""
|
||||||
|
pg_layer = self._getPostGISLayer('testlayer_èé', authcfg=self.auth_config.id())
|
||||||
|
self.assertTrue(pg_layer.isValid())
|
||||||
|
|
||||||
|
def testInvalidAuthAccess(self):
|
||||||
|
"""
|
||||||
|
Access the protected layer with not valid credentials
|
||||||
|
"""
|
||||||
|
pg_layer = self._getPostGISLayer('testlayer_èé')
|
||||||
|
self.assertFalse(pg_layer.isValid())
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@ -170,6 +170,19 @@ class TestAuthManager(unittest.TestCase):
|
|||||||
wms_layer = QgsRasterLayer(uri, layer_name, 'wms')
|
wms_layer = QgsRasterLayer(uri, layer_name, 'wms')
|
||||||
return wms_layer
|
return wms_layer
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _getGeoJsonLayer(cls, type_name, layer_name=None, authcfg=None):
|
||||||
|
"""
|
||||||
|
OGR layer factory
|
||||||
|
"""
|
||||||
|
if layer_name is None:
|
||||||
|
layer_name = 'geojson_' + type_name
|
||||||
|
uri = '%s://%s:%s/?MAP=%s&SERVICE=WFS&REQUEST=GetFeature&TYPENAME=%s&VERSION=2.0.0&OUTPUTFORMAT=geojson' % (cls.protocol, cls.hostname, cls.port, cls.project_path, urllib.parse.quote(type_name))
|
||||||
|
if authcfg is not None:
|
||||||
|
uri += " authcfg='%s'" % authcfg
|
||||||
|
geojson_layer = QgsVectorLayer(uri, layer_name, 'ogr')
|
||||||
|
return geojson_layer
|
||||||
|
|
||||||
def testValidAuthAccess(self):
|
def testValidAuthAccess(self):
|
||||||
"""
|
"""
|
||||||
Access the HTTP Basic protected layer with valid credentials
|
Access the HTTP Basic protected layer with valid credentials
|
||||||
@ -178,6 +191,8 @@ class TestAuthManager(unittest.TestCase):
|
|||||||
self.assertTrue(wfs_layer.isValid())
|
self.assertTrue(wfs_layer.isValid())
|
||||||
wms_layer = self._getWMSLayer('testlayer_èé', authcfg=self.auth_config.id())
|
wms_layer = self._getWMSLayer('testlayer_èé', authcfg=self.auth_config.id())
|
||||||
self.assertTrue(wms_layer.isValid())
|
self.assertTrue(wms_layer.isValid())
|
||||||
|
geojson_layer = self._getGeoJsonLayer('testlayer_èé', authcfg=self.auth_config.id())
|
||||||
|
self.assertTrue(geojson_layer.isValid())
|
||||||
|
|
||||||
def testInvalidAuthAccess(self):
|
def testInvalidAuthAccess(self):
|
||||||
"""
|
"""
|
||||||
@ -187,6 +202,8 @@ class TestAuthManager(unittest.TestCase):
|
|||||||
self.assertFalse(wfs_layer.isValid())
|
self.assertFalse(wfs_layer.isValid())
|
||||||
wms_layer = self._getWMSLayer('testlayer_èé')
|
wms_layer = self._getWMSLayer('testlayer_èé')
|
||||||
self.assertFalse(wms_layer.isValid())
|
self.assertFalse(wms_layer.isValid())
|
||||||
|
geojson_layer = self._getGeoJsonLayer('testlayer_èé')
|
||||||
|
self.assertFalse(geojson_layer.isValid())
|
||||||
|
|
||||||
def testInvalidAuthFileDownload(self):
|
def testInvalidAuthFileDownload(self):
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user