mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
[authentication] Add a pair of APIs to export and import configurations to/from XML
This commit is contained in:
parent
abf5c9754c
commit
f916c06a8e
@ -11,6 +11,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsAuthMethodConfig
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
@ -184,6 +185,28 @@ against the config's :py:func:`~QgsAuthMethodConfig.uri` for auto-selecting auth
|
||||
:param accessurl: A URL to process
|
||||
:param resource: Output variable for result
|
||||
:param withpath: Whether to include the URI's path in output
|
||||
%End
|
||||
|
||||
bool writeXml( QDomElement &parentElement, QDomDocument &document );
|
||||
%Docstring
|
||||
Stores the configuration in a DOM
|
||||
|
||||
:param parentElement: parent DOM element
|
||||
:param document: DOM document
|
||||
|
||||
.. seealso:: :py:func:`readXml`
|
||||
|
||||
.. versionadded:: 3.20
|
||||
%End
|
||||
|
||||
bool readXml( const QDomElement &element );
|
||||
%Docstring
|
||||
from a DOM element.
|
||||
|
||||
:param element: is the DOM node corresponding to item (e.g. 'LayoutItem' element)
|
||||
:param document: DOM document
|
||||
|
||||
.. versionadded:: 3.20
|
||||
%End
|
||||
|
||||
};
|
||||
|
@ -298,6 +298,23 @@ Remove an authentication config in the database
|
||||
:param authcfg: Associated authentication config id
|
||||
|
||||
:return: Whether operation succeeded
|
||||
%End
|
||||
|
||||
bool exportAuthenticationConfigsToXml( const QString &filename, const QStringList &authcfgs, const QString &password = QString() );
|
||||
%Docstring
|
||||
Export authentication configurations to an XML file
|
||||
|
||||
:param filename: The file path to save the XML content to
|
||||
:param authcfgs: The list of configuration IDs to export
|
||||
:param password: A password string to encrypt the XML content
|
||||
%End
|
||||
|
||||
bool importAuthenticationConfigsFromXml( const QString &filename, const QString &password = QString() );
|
||||
%Docstring
|
||||
Import authentication configurations from an XML file
|
||||
|
||||
:param filename: The file path from which the XML content will be read
|
||||
:param password: A password string to decrypt the XML content
|
||||
%End
|
||||
|
||||
bool removeAllAuthenticationConfigs();
|
||||
|
@ -157,6 +157,34 @@ bool QgsAuthMethodConfig::uriToResource( const QString &accessurl, QString *reso
|
||||
}
|
||||
|
||||
|
||||
bool QgsAuthMethodConfig::writeXml( QDomElement &parentElement, QDomDocument &document )
|
||||
{
|
||||
QDomElement element = document.createElement( QStringLiteral( "AuthMethodConfig" ) );
|
||||
element.setAttribute( QStringLiteral( "method" ), mMethod );
|
||||
element.setAttribute( QStringLiteral( "id" ), mId );
|
||||
element.setAttribute( QStringLiteral( "name" ), mName );
|
||||
element.setAttribute( QStringLiteral( "version" ), QString::number( mVersion ) );
|
||||
element.setAttribute( QStringLiteral( "uri" ), mUri );
|
||||
element.setAttribute( QStringLiteral( "config" ), configString() );
|
||||
parentElement.appendChild( element );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsAuthMethodConfig::readXml( const QDomElement &element )
|
||||
{
|
||||
if ( element.nodeName() != QLatin1String( "AuthMethodConfig" ) )
|
||||
return false;
|
||||
|
||||
mMethod = element.attribute( QStringLiteral( "method" ) );
|
||||
mId = element.attribute( QStringLiteral( "id" ) );
|
||||
mName = element.attribute( QStringLiteral( "name" ) );
|
||||
mVersion = element.attribute( QStringLiteral( "version" ) ).toInt();
|
||||
mUri = element.attribute( QStringLiteral( "uri" ) );
|
||||
loadConfigString( element.attribute( QStringLiteral( "config" ) ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
@ -18,8 +18,11 @@
|
||||
#define QGSAUTHCONFIG_H
|
||||
|
||||
#include "qgis_core.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <QDomElement>
|
||||
#include <QDomDocument>
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
#include <QSslCertificate>
|
||||
@ -160,6 +163,23 @@ class CORE_EXPORT QgsAuthMethodConfig
|
||||
*/
|
||||
static bool uriToResource( const QString &accessurl, QString *resource, bool withpath = false );
|
||||
|
||||
/**
|
||||
* Stores the configuration in a DOM
|
||||
* \param parentElement parent DOM element
|
||||
* \param document DOM document
|
||||
* \see readXml()
|
||||
* \since QGIS 3.20
|
||||
*/
|
||||
bool writeXml( QDomElement &parentElement, QDomDocument &document );
|
||||
|
||||
/**
|
||||
* from a DOM element.
|
||||
* \param element is the DOM node corresponding to item (e.g. 'LayoutItem' element)
|
||||
* \param document DOM document
|
||||
* \since QGIS 3.20
|
||||
*/
|
||||
bool readXml( const QDomElement &element );
|
||||
|
||||
private:
|
||||
QString mId;
|
||||
QString mName;
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include <QTimer>
|
||||
#include <QVariant>
|
||||
#include <QSqlDriver>
|
||||
#include <QDomElement>
|
||||
#include <QDomDocument>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
#include <QRandomGenerator>
|
||||
@ -1323,6 +1325,118 @@ bool QgsAuthManager::removeAuthenticationConfig( const QString &authcfg )
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsAuthManager::exportAuthenticationConfigsToXml( const QString &filename, const QStringList &authcfgs, const QString &password )
|
||||
{
|
||||
if ( filename.isEmpty() )
|
||||
return false;
|
||||
|
||||
QDomDocument document( QStringLiteral( "qgis_authentication" ) );
|
||||
QDomElement root = document.createElement( QStringLiteral( "qgis_authentication" ) );
|
||||
document.appendChild( root );
|
||||
|
||||
QString civ;
|
||||
if ( !password.isEmpty() )
|
||||
{
|
||||
QString salt;
|
||||
QString hash;
|
||||
QgsAuthCrypto::passwordKeyHash( password, &salt, &hash, &civ );
|
||||
root.setAttribute( QStringLiteral( "salt" ), salt );
|
||||
root.setAttribute( QStringLiteral( "hash" ), hash );
|
||||
root.setAttribute( QStringLiteral( "civ" ), civ );
|
||||
}
|
||||
|
||||
QDomElement configurations = document.createElement( QStringLiteral( "configurations" ) );
|
||||
for ( const QString &authcfg : authcfgs )
|
||||
{
|
||||
QgsAuthMethodConfig authMethodConfig;
|
||||
|
||||
bool ok = loadAuthenticationConfig( authcfg, authMethodConfig, true );
|
||||
if ( ok )
|
||||
{
|
||||
authMethodConfig.writeXml( configurations, document );
|
||||
}
|
||||
}
|
||||
if ( !password.isEmpty() )
|
||||
{
|
||||
QString configurationsString;
|
||||
QTextStream ts( &configurationsString );
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
ts.setCodec( "UTF-8" );
|
||||
#endif
|
||||
configurations.save( ts, 2 );
|
||||
root.appendChild( document.createTextNode( QgsAuthCrypto::encrypt( password, civ, configurationsString ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
root.appendChild( configurations );
|
||||
}
|
||||
|
||||
QFile file( filename );
|
||||
if ( !file.open( QFile::WriteOnly | QIODevice::Truncate ) )
|
||||
return false;
|
||||
|
||||
QTextStream ts( &file );
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
ts.setCodec( "UTF-8" );
|
||||
#endif
|
||||
document.save( ts, 2 );
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsAuthManager::importAuthenticationConfigsFromXml( const QString &filename, const QString &password )
|
||||
{
|
||||
QFile f( filename );
|
||||
if ( !f.open( QFile::ReadOnly ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QDomDocument document( QStringLiteral( "qgis_authentication" ) );
|
||||
if ( !document.setContent( &f ) )
|
||||
{
|
||||
f.close();
|
||||
return false;
|
||||
}
|
||||
f.close();
|
||||
|
||||
QDomElement root = document.documentElement();
|
||||
if ( root.tagName() != QLatin1String( "qgis_authentication" ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QDomElement configurations;
|
||||
if ( root.hasAttribute( QStringLiteral( "salt" ) ) )
|
||||
{
|
||||
QString salt = root.attribute( QStringLiteral( "salt" ) );
|
||||
QString hash = root.attribute( QStringLiteral( "hash" ) );
|
||||
QString civ = root.attribute( QStringLiteral( "civ" ) );
|
||||
if ( !QgsAuthCrypto::verifyPasswordKeyHash( password, salt, hash ) )
|
||||
return false;
|
||||
|
||||
document.setContent( QgsAuthCrypto::decrypt( password, civ, root.text() ) );
|
||||
configurations = document.firstChild().toElement();
|
||||
}
|
||||
else
|
||||
{
|
||||
configurations = root.firstChildElement( QStringLiteral( "configurations" ) );
|
||||
}
|
||||
|
||||
QDomElement configuration = configurations.firstChildElement();
|
||||
while ( !configuration.isNull() )
|
||||
{
|
||||
QgsAuthMethodConfig authMethodConfig;
|
||||
authMethodConfig.readXml( configuration );
|
||||
qDebug() << configuration.nodeName();
|
||||
qDebug() << authMethodConfig.id();
|
||||
storeAuthenticationConfig( authMethodConfig );
|
||||
|
||||
configuration = configuration.nextSiblingElement();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsAuthManager::removeAllAuthenticationConfigs()
|
||||
{
|
||||
QMutexLocker locker( mMutex.get() );
|
||||
|
@ -300,6 +300,21 @@ class CORE_EXPORT QgsAuthManager : public QObject
|
||||
*/
|
||||
bool removeAuthenticationConfig( const QString &authcfg );
|
||||
|
||||
/**
|
||||
* Export authentication configurations to an XML file
|
||||
* \param filename The file path to save the XML content to
|
||||
* \param authcfgs The list of configuration IDs to export
|
||||
* \param password A password string to encrypt the XML content
|
||||
*/
|
||||
bool exportAuthenticationConfigsToXml( const QString &filename, const QStringList &authcfgs, const QString &password = QString() );
|
||||
|
||||
/**
|
||||
* Import authentication configurations from an XML file
|
||||
* \param filename The file path from which the XML content will be read
|
||||
* \param password A password string to decrypt the XML content
|
||||
*/
|
||||
bool importAuthenticationConfigsFromXml( const QString &filename, const QString &password = QString() );
|
||||
|
||||
/**
|
||||
* Clear all authentication configs from table in database and from provider caches
|
||||
* \returns Whether operation succeeded
|
||||
|
@ -323,6 +323,21 @@ void TestQgsAuthManager::testAuthConfigs()
|
||||
QVERIFY( authm->storeAuthenticationConfig( config ) );
|
||||
idcfgmap.insert( config.id(), config );
|
||||
}
|
||||
|
||||
QCOMPARE( authm->availableAuthMethodConfigs().size(), 3 );
|
||||
|
||||
// Password-less export / import
|
||||
QVERIFY( authm->exportAuthenticationConfigsToXml( mTempDir + QStringLiteral( "/configs.xml" ), idcfgmap.keys() ) );
|
||||
QVERIFY( authm->removeAllAuthenticationConfigs() );
|
||||
QVERIFY( authm->importAuthenticationConfigsFromXml( mTempDir + QStringLiteral( "/configs.xml" ) ) );
|
||||
|
||||
QCOMPARE( authm->availableAuthMethodConfigs().size(), 3 );
|
||||
|
||||
// Password-protected export / import
|
||||
QVERIFY( authm->exportAuthenticationConfigsToXml( mTempDir + QStringLiteral( "/configs.xml" ), idcfgmap.keys(), QStringLiteral( "1234" ) ) );
|
||||
QVERIFY( authm->removeAllAuthenticationConfigs() );
|
||||
QVERIFY( authm->importAuthenticationConfigsFromXml( mTempDir + QStringLiteral( "/configs.xml" ), QStringLiteral( "1234" ) ) );
|
||||
|
||||
QgsAuthMethodConfigsMap authmap( authm->availableAuthMethodConfigs() );
|
||||
QCOMPARE( authmap.size(), 3 );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user