Skip to content

Commit

Permalink
Followup 89de757, fix broken authentication/username/password
Browse files Browse the repository at this point in the history
support in WMS and other providers

These providers rely on the QgsDataSourceUri param methods for storing and retrieving
authentication details, so the change made to use the dedicated username/password/auth
setters in 89de757 broke all auth support for these providers.

Ensure that the param system is fully compatible and aliased to the dedicated
username/password/authcfg getters and setters

(cherry picked from commit 0b1c0fd)
  • Loading branch information
nyalldawson authored and nirvn committed Dec 6, 2019
1 parent d7dd190 commit e0040af
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 6 deletions.
82 changes: 76 additions & 6 deletions src/core/qgsdatasourceuri.cpp
Expand Up @@ -591,19 +591,40 @@ QByteArray QgsDataSourceUri::encodedUri() const
{
url.addQueryItem( it.key(), it.value() );
}

if ( !mUsername.isEmpty() )
url.addQueryItem( QStringLiteral( "username" ), mUsername );

if ( !mPassword.isEmpty() )
url.addQueryItem( QStringLiteral( "password" ), mPassword );

if ( !mAuthConfigId.isEmpty() )
url.addQueryItem( QStringLiteral( "authcfg" ), mAuthConfigId );

return url.encodedQuery();
}

void QgsDataSourceUri::setEncodedUri( const QByteArray &uri )
{
mParams.clear();
mUsername.clear();
mPassword.clear();
mAuthConfigId.clear();

QUrl url;
url.setEncodedQuery( uri );

const auto constQueryItems = url.queryItems();
for ( const QPair<QString, QString> &item : constQueryItems )
{
mParams.insertMulti( item.first, item.second );
if ( item.first == QLatin1String( "username" ) )
mUsername = item.second;
else if ( item.first == QLatin1String( "password" ) )
mPassword = item.second;
else if ( item.first == QLatin1String( "authcfg" ) )
mAuthConfigId = item.second;
else
mParams.insertMulti( item.first, item.second );
}
}

Expand Down Expand Up @@ -732,35 +753,84 @@ QString QgsDataSourceUri::encodeSslMode( QgsDataSourceUri::SslMode sslMode )

void QgsDataSourceUri::setParam( const QString &key, const QString &value )
{
// may be multiple
mParams.insertMulti( key, value );
// maintain old API
if ( key == QLatin1String( "username" ) )
mUsername = value;
else if ( key == QLatin1String( "password" ) )
mPassword = value;
else if ( key == QLatin1String( "authcfg" ) )
mAuthConfigId = value;
else
{
// may be multiple
mParams.insertMulti( key, value );
}
}

void QgsDataSourceUri::setParam( const QString &key, const QStringList &value )
{
const auto constValue = value;
for ( const QString &val : constValue )
for ( const QString &val : value )
{
mParams.insertMulti( key, val );
setParam( key, val );
}
}

int QgsDataSourceUri::removeParam( const QString &key )
{
if ( key == QLatin1String( "username" ) && !mUsername.isEmpty() )
{
mUsername.clear();
return 1;
}
else if ( key == QLatin1String( "password" ) && !mPassword.isEmpty() )
{
mPassword.clear();
return 1;
}
else if ( key == QLatin1String( "authcfg" ) && !mAuthConfigId.isEmpty() )
{
mAuthConfigId.clear();
return 1;
}

return mParams.remove( key );
}

QString QgsDataSourceUri::param( const QString &key ) const
{
// maintain old api
if ( key == QLatin1String( "username" ) && !mUsername.isEmpty() )
return mUsername;
else if ( key == QLatin1String( "password" ) && !mPassword.isEmpty() )
return mPassword;
else if ( key == QLatin1String( "authcfg" ) && !mAuthConfigId.isEmpty() )
return mAuthConfigId;

return mParams.value( key );
}

QStringList QgsDataSourceUri::params( const QString &key ) const
{
// maintain old api
if ( key == QLatin1String( "username" ) && !mUsername.isEmpty() )
return QStringList() << mUsername;
else if ( key == QLatin1String( "password" ) && !mPassword.isEmpty() )
return QStringList() << mPassword;
else if ( key == QLatin1String( "authcfg" ) && !mAuthConfigId.isEmpty() )
return QStringList() << mAuthConfigId;

return mParams.values( key );
}

bool QgsDataSourceUri::hasParam( const QString &key ) const
{
// maintain old api
if ( key == QLatin1String( "username" ) && !mUsername.isEmpty() )
return true;
else if ( key == QLatin1String( "password" ) && !mPassword.isEmpty() )
return true;
else if ( key == QLatin1String( "authcfg" ) && !mAuthConfigId.isEmpty() )
return true;

return mParams.contains( key );
}
64 changes: 64 additions & 0 deletions tests/src/core/testqgsdatasourceuri.cpp
Expand Up @@ -27,6 +27,7 @@ class TestQgsDataSourceUri: public QObject
private slots:
void checkparser();
void checkparser_data();
void checkAuthParams();
};

void TestQgsDataSourceUri::checkparser_data()
Expand Down Expand Up @@ -177,5 +178,68 @@ void TestQgsDataSourceUri::checkparser()
QCOMPARE( ds.param( "myparam" ), myparam );
}

void TestQgsDataSourceUri::checkAuthParams()
{
// some providers rely on the QgsDataSourceUri params for storing and retrieving username, password and authentication.
// Test here that the direct setters and getters for username/password/authcfg are compatible with providers which utilize the parameter system

QgsDataSourceUri uri;
QVERIFY( uri.param( QStringLiteral( "username" ) ).isEmpty() );
QVERIFY( uri.param( QStringLiteral( "password" ) ).isEmpty() );
QVERIFY( uri.param( QStringLiteral( "authcfg" ) ).isEmpty() );

uri.setUsername( QStringLiteral( "kaladin" ) );
uri.setPassword( QStringLiteral( "stormblessed" ) );
uri.setAuthConfigId( QStringLiteral( "syl" ) );

QCOMPARE( uri.param( QStringLiteral( "username" ) ), QStringLiteral( "kaladin" ) );
QCOMPARE( uri.param( QStringLiteral( "password" ) ), QStringLiteral( "stormblessed" ) );
QCOMPARE( uri.param( QStringLiteral( "authcfg" ) ), QStringLiteral( "syl" ) );

// round trip through encodedUri should not lose username/password/authcfg
QByteArray encoded = uri.encodedUri();
QgsDataSourceUri uri2;
uri2.setEncodedUri( encoded );

QCOMPARE( uri2.param( QStringLiteral( "username" ) ), QStringLiteral( "kaladin" ) );
QCOMPARE( uri2.username(), QStringLiteral( "kaladin" ) );
QCOMPARE( uri2.param( QStringLiteral( "password" ) ), QStringLiteral( "stormblessed" ) );
QCOMPARE( uri2.password(), QStringLiteral( "stormblessed" ) );
QCOMPARE( uri2.param( QStringLiteral( "authcfg" ) ), QStringLiteral( "syl" ) );
QCOMPARE( uri2.authConfigId(), QStringLiteral( "syl" ) );

QgsDataSourceUri uri3;
uri3.setParam( QStringLiteral( "username" ), QStringLiteral( "kaladin" ) );
uri3.setParam( QStringLiteral( "password" ), QStringLiteral( "stormblessed" ) );
uri3.setParam( QStringLiteral( "authcfg" ), QStringLiteral( "syl" ) );
QCOMPARE( uri3.param( QStringLiteral( "username" ) ), QStringLiteral( "kaladin" ) );
QCOMPARE( uri3.params( QStringLiteral( "username" ) ), QStringList() << QStringLiteral( "kaladin" ) );
QCOMPARE( uri3.username(), QStringLiteral( "kaladin" ) );
QCOMPARE( uri3.param( QStringLiteral( "password" ) ), QStringLiteral( "stormblessed" ) );
QCOMPARE( uri3.params( QStringLiteral( "password" ) ), QStringList() << QStringLiteral( "stormblessed" ) );
QCOMPARE( uri3.password(), QStringLiteral( "stormblessed" ) );
QCOMPARE( uri3.param( QStringLiteral( "authcfg" ) ), QStringLiteral( "syl" ) );
QCOMPARE( uri3.params( QStringLiteral( "authcfg" ) ), QStringList() << QStringLiteral( "syl" ) );
QCOMPARE( uri3.authConfigId(), QStringLiteral( "syl" ) );

QVERIFY( uri.hasParam( QStringLiteral( "username" ) ) );
uri.removeParam( QStringLiteral( "username" ) );
QVERIFY( !uri.hasParam( QStringLiteral( "username" ) ) );
QVERIFY( uri.param( QStringLiteral( "username" ) ).isEmpty() );
QVERIFY( uri.username().isEmpty() );
QVERIFY( uri.hasParam( QStringLiteral( "password" ) ) );
uri.removeParam( QStringLiteral( "password" ) );
QVERIFY( !uri.hasParam( QStringLiteral( "password" ) ) );
QVERIFY( uri.param( QStringLiteral( "password" ) ).isEmpty() );
QVERIFY( uri.password().isEmpty() );
QVERIFY( uri.hasParam( QStringLiteral( "authcfg" ) ) );
uri.removeParam( QStringLiteral( "authcfg" ) );
QVERIFY( !uri.hasParam( QStringLiteral( "authcfg" ) ) );
QVERIFY( uri.param( QStringLiteral( "authcfg" ) ).isEmpty() );
QVERIFY( uri.authConfigId().isEmpty() );

}


QGSTEST_MAIN( TestQgsDataSourceUri )
#include "testqgsdatasourceuri.moc"

0 comments on commit e0040af

Please sign in to comment.