mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-15 00:07:25 -05:00
Merge pull request #43193 from nirvn/auth_imex
[authentication] Add a pair of APIs to export and import configurations to/from XML
This commit is contained in:
commit
e3cb3e5a01
@ -11,6 +11,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsAuthMethodConfig
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
@ -184,6 +185,27 @@ 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)
|
||||
|
||||
.. versionadded:: 3.20
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
@ -298,6 +298,27 @@ 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
|
||||
|
||||
.. versionadded:: 3.20
|
||||
%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
|
||||
|
||||
.. versionadded:: 3.20
|
||||
%End
|
||||
|
||||
bool removeAllAuthenticationConfigs();
|
||||
|
||||
@ -33,6 +33,13 @@ Widget for editing authentication configurations directly in database
|
||||
void toggleTitleVisibility( bool visible );
|
||||
%Docstring
|
||||
Hide the widget's title, e.g. when embedding
|
||||
%End
|
||||
|
||||
QStringList selectedAuthenticationConfigIds() const;
|
||||
%Docstring
|
||||
Returns the list of selected authentication configuration IDs
|
||||
|
||||
.. versionadded:: 3.20
|
||||
%End
|
||||
|
||||
public slots:
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsauthconfig.h"
|
||||
#include "qgsauthcertutils.h"
|
||||
#include "qgsxmlutils.h"
|
||||
|
||||
#include <QtCrypto>
|
||||
|
||||
@ -23,8 +25,6 @@
|
||||
#include <QCryptographicHash>
|
||||
#include <QUrl>
|
||||
|
||||
#include "qgsauthcertutils.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// QgsAuthMethodConfig
|
||||
@ -157,6 +157,50 @@ 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 );
|
||||
|
||||
QDomElement configElements = document.createElement( QStringLiteral( "Config" ) );
|
||||
QgsStringMap::const_iterator i = mConfigMap.constBegin();
|
||||
while ( i != mConfigMap.constEnd() )
|
||||
{
|
||||
configElements.setAttribute( i.key(), i.value() );
|
||||
++i;
|
||||
}
|
||||
element.appendChild( configElements );
|
||||
|
||||
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" ) );
|
||||
|
||||
clearConfigMap();
|
||||
QDomNamedNodeMap configAttributes = element.firstChildElement().attributes();
|
||||
for ( int i = 0; i < configAttributes.length(); i++ )
|
||||
{
|
||||
QDomAttr configAttribute = configAttributes.item( i ).toAttr();
|
||||
setConfig( configAttribute.name(), configAttribute.value() );
|
||||
}
|
||||
|
||||
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,22 @@ 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)
|
||||
* \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,116 @@ 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 file( filename );
|
||||
if ( !file.open( QFile::ReadOnly ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QDomDocument document( QStringLiteral( "qgis_authentication" ) );
|
||||
if ( !document.setContent( &file ) )
|
||||
{
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
file.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 );
|
||||
storeAuthenticationConfig( authMethodConfig );
|
||||
|
||||
configuration = configuration.nextSiblingElement();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsAuthManager::removeAllAuthenticationConfigs()
|
||||
{
|
||||
QMutexLocker locker( mMutex.get() );
|
||||
|
||||
@ -300,6 +300,23 @@ 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
|
||||
* \since QGIS 3.20
|
||||
*/
|
||||
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
|
||||
* \since QGIS 3.20
|
||||
*/
|
||||
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
|
||||
|
||||
@ -90,6 +90,8 @@ QgsAuthConfigEditor::QgsAuthConfigEditor( QWidget *parent, bool showUtilities, b
|
||||
checkSelection();
|
||||
|
||||
// set up utility actions menu
|
||||
mActionImportAuthenticationConfigs = new QAction( tr( "Import authentication configurations from file" ), this );
|
||||
mActionExportSelectedAuthenticationConfigs = new QAction( tr( "Export selected authentication configurations to file" ), this );
|
||||
mActionSetMasterPassword = new QAction( QStringLiteral( "Input master password" ), this );
|
||||
mActionClearCachedMasterPassword = new QAction( QStringLiteral( "Clear cached master password" ), this );
|
||||
mActionResetMasterPassword = new QAction( QStringLiteral( "Reset master password" ), this );
|
||||
@ -97,6 +99,8 @@ QgsAuthConfigEditor::QgsAuthConfigEditor( QWidget *parent, bool showUtilities, b
|
||||
mActionRemoveAuthConfigs = new QAction( QStringLiteral( "Remove all authentication configurations" ), this );
|
||||
mActionEraseAuthDatabase = new QAction( QStringLiteral( "Erase authentication database" ), this );
|
||||
|
||||
connect( mActionImportAuthenticationConfigs, &QAction::triggered, this, &QgsAuthConfigEditor::importAuthenticationConfigs );
|
||||
connect( mActionExportSelectedAuthenticationConfigs, &QAction::triggered, this, &QgsAuthConfigEditor::exportSelectedAuthenticationConfigs );
|
||||
connect( mActionSetMasterPassword, &QAction::triggered, this, &QgsAuthConfigEditor::setMasterPassword );
|
||||
connect( mActionClearCachedMasterPassword, &QAction::triggered, this, &QgsAuthConfigEditor::clearCachedMasterPassword );
|
||||
connect( mActionResetMasterPassword, &QAction::triggered, this, &QgsAuthConfigEditor::resetMasterPassword );
|
||||
@ -112,6 +116,9 @@ QgsAuthConfigEditor::QgsAuthConfigEditor( QWidget *parent, bool showUtilities, b
|
||||
mAuthUtilitiesMenu->addAction( mActionClearCachedAuthConfigs );
|
||||
mAuthUtilitiesMenu->addAction( mActionRemoveAuthConfigs );
|
||||
mAuthUtilitiesMenu->addSeparator();
|
||||
mAuthUtilitiesMenu->addAction( mActionImportAuthenticationConfigs );
|
||||
mAuthUtilitiesMenu->addAction( mActionExportSelectedAuthenticationConfigs );
|
||||
mAuthUtilitiesMenu->addSeparator();
|
||||
mAuthUtilitiesMenu->addAction( mActionEraseAuthDatabase );
|
||||
|
||||
btnAuthUtilities->setMenu( mAuthUtilitiesMenu );
|
||||
@ -119,6 +126,16 @@ QgsAuthConfigEditor::QgsAuthConfigEditor( QWidget *parent, bool showUtilities, b
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAuthConfigEditor::importAuthenticationConfigs()
|
||||
{
|
||||
QgsAuthGuiUtils::importAuthenticationConfigs( messageBar() );
|
||||
}
|
||||
|
||||
void QgsAuthConfigEditor::exportSelectedAuthenticationConfigs()
|
||||
{
|
||||
QgsAuthGuiUtils::exportSelectedAuthenticationConfigs( selectedAuthenticationConfigIds(), messageBar() );
|
||||
}
|
||||
|
||||
void QgsAuthConfigEditor::setMasterPassword()
|
||||
{
|
||||
QgsAuthGuiUtils::setMasterPassword( messageBar() );
|
||||
@ -163,6 +180,17 @@ void QgsAuthConfigEditor::toggleTitleVisibility( bool visible )
|
||||
}
|
||||
}
|
||||
|
||||
QStringList QgsAuthConfigEditor::selectedAuthenticationConfigIds() const
|
||||
{
|
||||
QStringList ids;
|
||||
QModelIndexList selection = tableViewConfigs->selectionModel()->selectedRows( 0 );
|
||||
for ( QModelIndex index : selection )
|
||||
{
|
||||
ids << index.sibling( index.row(), 0 ).data().toString();
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
void QgsAuthConfigEditor::setShowUtilitiesButton( bool show )
|
||||
{
|
||||
if ( !mDisabled )
|
||||
@ -255,16 +283,18 @@ void QgsAuthConfigEditor::btnRemoveConfig_clicked()
|
||||
if ( selection.empty() )
|
||||
return;
|
||||
|
||||
QModelIndex indx = selection.at( 0 );
|
||||
QString name = indx.sibling( indx.row(), 1 ).data().toString();
|
||||
|
||||
if ( QMessageBox::warning( this, tr( "Remove Configuration" ),
|
||||
tr( "Are you sure you want to remove '%1'?\n\n"
|
||||
"Operation can NOT be undone!" ).arg( name ),
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
QMessageBox::Cancel ) == QMessageBox::Ok )
|
||||
for ( QModelIndex index : selection )
|
||||
{
|
||||
mConfigModel->removeRow( indx.row() );
|
||||
QString name = index.sibling( index.row(), 1 ).data().toString();
|
||||
|
||||
if ( QMessageBox::warning( this, tr( "Remove Configuration" ),
|
||||
tr( "Are you sure you want to remove '%1'?\n\n"
|
||||
"Operation can NOT be undone!" ).arg( name ),
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
QMessageBox::Cancel ) == QMessageBox::Ok )
|
||||
{
|
||||
mConfigModel->removeRow( index.row() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -48,6 +48,12 @@ class GUI_EXPORT QgsAuthConfigEditor : public QWidget, private Ui::QgsAuthConfig
|
||||
//! Hide the widget's title, e.g. when embedding
|
||||
void toggleTitleVisibility( bool visible );
|
||||
|
||||
/**
|
||||
* Returns the list of selected authentication configuration IDs
|
||||
* \since QGIS 3.20
|
||||
*/
|
||||
QStringList selectedAuthenticationConfigIds() const;
|
||||
|
||||
public slots:
|
||||
//! Sets whether to show the widget's utilities button, e.g. when embedding
|
||||
void setShowUtilitiesButton( bool show = true );
|
||||
@ -59,6 +65,12 @@ class GUI_EXPORT QgsAuthConfigEditor : public QWidget, private Ui::QgsAuthConfig
|
||||
//! Repopulate the view with table contents
|
||||
void refreshTableView();
|
||||
|
||||
//! Import authentication configurations from a XML file
|
||||
void importAuthenticationConfigs();
|
||||
|
||||
//! Exports selected authentication configurations to a XML file
|
||||
void exportSelectedAuthenticationConfigs();
|
||||
|
||||
//! Sets the cached master password (and verifies it if its hash is in authentication database)
|
||||
void setMasterPassword();
|
||||
|
||||
@ -100,6 +112,8 @@ class GUI_EXPORT QgsAuthConfigEditor : public QWidget, private Ui::QgsAuthConfig
|
||||
QSqlTableModel *mConfigModel = nullptr;
|
||||
|
||||
QMenu *mAuthUtilitiesMenu = nullptr;
|
||||
QAction *mActionImportAuthenticationConfigs = nullptr;
|
||||
QAction *mActionExportSelectedAuthenticationConfigs = nullptr;
|
||||
QAction *mActionSetMasterPassword = nullptr;
|
||||
QAction *mActionClearCachedMasterPassword = nullptr;
|
||||
QAction *mActionResetMasterPassword = nullptr;
|
||||
|
||||
@ -142,6 +142,8 @@ void QgsAuthEditorWidgets::setupUtilitiesMenu()
|
||||
this, &QgsAuthEditorWidgets::authMessageOut );
|
||||
|
||||
// set up utility actions menu
|
||||
mActionImportAuthenticationConfigs = new QAction( tr( "Import authentication configurations from file" ), this );
|
||||
mActionExportSelectedAuthenticationConfigs = new QAction( tr( "Export selected authentication configurations to file" ), this );
|
||||
mActionSetMasterPassword = new QAction( tr( "Input master password" ), this );
|
||||
mActionClearCachedMasterPassword = new QAction( tr( "Clear cached master password" ), this );
|
||||
mActionResetMasterPassword = new QAction( tr( "Reset master password" ), this );
|
||||
@ -168,6 +170,8 @@ void QgsAuthEditorWidgets::setupUtilitiesMenu()
|
||||
mActionPasswordHelperLoggingEnable->setCheckable( true );
|
||||
mActionPasswordHelperLoggingEnable->setChecked( QgsApplication::authManager()->passwordHelperLoggingEnabled() );
|
||||
|
||||
connect( mActionImportAuthenticationConfigs, &QAction::triggered, this, &QgsAuthEditorWidgets::importAuthenticationConfigs );
|
||||
connect( mActionExportSelectedAuthenticationConfigs, &QAction::triggered, this, &QgsAuthEditorWidgets::exportSelectedAuthenticationConfigs );
|
||||
connect( mActionSetMasterPassword, &QAction::triggered, this, &QgsAuthEditorWidgets::setMasterPassword );
|
||||
connect( mActionClearCachedMasterPassword, &QAction::triggered, this, &QgsAuthEditorWidgets::clearCachedMasterPassword );
|
||||
connect( mActionResetMasterPassword, &QAction::triggered, this, &QgsAuthEditorWidgets::resetMasterPassword );
|
||||
@ -206,11 +210,27 @@ void QgsAuthEditorWidgets::setupUtilitiesMenu()
|
||||
mAuthUtilitiesMenu->addAction( mActionClearCachedAuthConfigs );
|
||||
mAuthUtilitiesMenu->addAction( mActionRemoveAuthConfigs );
|
||||
mAuthUtilitiesMenu->addSeparator();
|
||||
mAuthUtilitiesMenu->addAction( mActionImportAuthenticationConfigs );
|
||||
mAuthUtilitiesMenu->addAction( mActionExportSelectedAuthenticationConfigs );
|
||||
mAuthUtilitiesMenu->addSeparator();
|
||||
mAuthUtilitiesMenu->addAction( mActionEraseAuthDatabase );
|
||||
|
||||
btnAuthUtilities->setMenu( mAuthUtilitiesMenu );
|
||||
}
|
||||
|
||||
void QgsAuthEditorWidgets::importAuthenticationConfigs()
|
||||
{
|
||||
QgsAuthGuiUtils::importAuthenticationConfigs( messageBar() );
|
||||
}
|
||||
|
||||
void QgsAuthEditorWidgets::exportSelectedAuthenticationConfigs()
|
||||
{
|
||||
if ( !wdgtConfigEditor )
|
||||
return;
|
||||
|
||||
QgsAuthGuiUtils::exportSelectedAuthenticationConfigs( wdgtConfigEditor->selectedAuthenticationConfigIds(), messageBar() );
|
||||
}
|
||||
|
||||
void QgsAuthEditorWidgets::setMasterPassword()
|
||||
{
|
||||
QgsAuthGuiUtils::setMasterPassword( messageBar() );
|
||||
|
||||
@ -70,6 +70,12 @@ class GUI_EXPORT QgsAuthEditorWidgets : public QWidget, private Ui::QgsAuthEdito
|
||||
void btnCertManager_clicked();
|
||||
void btnAuthPlugins_clicked();
|
||||
|
||||
//! Import authentication configurations from a XML file
|
||||
void importAuthenticationConfigs();
|
||||
|
||||
//! Exports selected authentication configurations to a XML file
|
||||
void exportSelectedAuthenticationConfigs();
|
||||
|
||||
//! Sets the cached master password (and verifies it if its hash is in authentication database)
|
||||
void setMasterPassword();
|
||||
|
||||
@ -109,6 +115,8 @@ class GUI_EXPORT QgsAuthEditorWidgets : public QWidget, private Ui::QgsAuthEdito
|
||||
QgsMessageBar *messageBar();
|
||||
|
||||
QMenu *mAuthUtilitiesMenu = nullptr;
|
||||
QAction *mActionExportSelectedAuthenticationConfigs = nullptr;
|
||||
QAction *mActionImportAuthenticationConfigs = nullptr;
|
||||
QAction *mActionSetMasterPassword = nullptr;
|
||||
QAction *mActionClearCachedMasterPassword = nullptr;
|
||||
QAction *mActionResetMasterPassword = nullptr;
|
||||
@ -121,6 +129,7 @@ class GUI_EXPORT QgsAuthEditorWidgets : public QWidget, private Ui::QgsAuthEdito
|
||||
QAction *mActionPasswordHelperLoggingEnable = nullptr;
|
||||
QAction *mActionClearAccessCacheNow = nullptr;
|
||||
QAction *mActionAutoClearAccessCache = nullptr;
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSAUTHEDITORWIDGETS_H
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include "qgsauthguiutils.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
|
||||
@ -75,6 +76,81 @@ bool QgsAuthGuiUtils::isDisabled( QgsMessageBar *msgbar )
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsAuthGuiUtils::exportSelectedAuthenticationConfigs( QStringList authenticationConfigIds, QgsMessageBar *msgbar )
|
||||
{
|
||||
QString password = QInputDialog::getText( msgbar, QObject::tr( "Export Authentication Configurations" ),
|
||||
QObject::tr( "Enter a password encrypt the configuration file:" ), QLineEdit::Password );
|
||||
if ( password.isEmpty() )
|
||||
{
|
||||
if ( QMessageBox::warning( msgbar,
|
||||
QObject::tr( "Export Authentication Configurations" ),
|
||||
QObject::tr( "Exporting authentication configurations with a blank password will result in a plain text file which may contain sensitive information. Are you sure you want to do this?" ),
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
QMessageBox::Cancel ) == QMessageBox::Cancel )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QString filename = QFileDialog::getSaveFileName( msgbar, QObject::tr( "Export Authentication Configurations" ), QDir::homePath(),
|
||||
QObject::tr( "XML files (*.xml *.XML)" ) );
|
||||
if ( filename.isEmpty() )
|
||||
return;
|
||||
|
||||
bool ok = QgsApplication::authManager()->exportAuthenticationConfigsToXml( filename, authenticationConfigIds, password );
|
||||
if ( !ok )
|
||||
{
|
||||
msgbar->pushMessage( QgsApplication::authManager()->authManTag(),
|
||||
QObject::tr( "Export of authentication configurations failed." ),
|
||||
Qgis::Critical );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAuthGuiUtils::importAuthenticationConfigs( QgsMessageBar *msgbar )
|
||||
{
|
||||
|
||||
QString filename = QFileDialog::getOpenFileName( msgbar, QObject::tr( "Export Authentication Configurations" ), QDir::homePath(),
|
||||
QObject::tr( "XML files (*.xml *.XML)" ) );
|
||||
if ( filename.isEmpty() )
|
||||
return;
|
||||
|
||||
|
||||
QFile file( filename );
|
||||
if ( !file.open( QFile::ReadOnly ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QDomDocument document( QStringLiteral( "qgis_authentication" ) );
|
||||
if ( !document.setContent( &file ) )
|
||||
{
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
file.close();
|
||||
|
||||
QDomElement root = document.documentElement();
|
||||
if ( root.tagName() != QLatin1String( "qgis_authentication" ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QString password;
|
||||
if ( root.hasAttribute( QStringLiteral( "salt" ) ) )
|
||||
{
|
||||
password = QInputDialog::getText( msgbar, QObject::tr( "Import Authentication Configurations" ),
|
||||
QObject::tr( "Enter the password to decrypt the configurations file:" ), QLineEdit::Password );
|
||||
}
|
||||
|
||||
bool ok = QgsApplication::authManager()->importAuthenticationConfigsFromXml( filename, password );
|
||||
if ( !ok )
|
||||
{
|
||||
msgbar->pushMessage( QgsApplication::authManager()->authManTag(),
|
||||
QObject::tr( "Import of authentication configurations failed." ),
|
||||
Qgis::Critical );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAuthGuiUtils::setMasterPassword( QgsMessageBar *msgbar )
|
||||
{
|
||||
if ( QgsAuthGuiUtils::isDisabled( msgbar ) )
|
||||
|
||||
@ -60,6 +60,18 @@ class GUI_EXPORT QgsAuthGuiUtils
|
||||
//! Verify the authentication system is active, else notify user
|
||||
static bool isDisabled( QgsMessageBar *msgbar );
|
||||
|
||||
/**
|
||||
* Import authentication configurations from a XML file
|
||||
* \since QGIS 3.20
|
||||
*/
|
||||
static void importAuthenticationConfigs( QgsMessageBar *msgbar );
|
||||
|
||||
/**
|
||||
* Exports selected authentication configurations to a XML file
|
||||
* \since QGIS 3.20
|
||||
*/
|
||||
static void exportSelectedAuthenticationConfigs( QStringList authenticationConfigIds, QgsMessageBar *msgbar );
|
||||
|
||||
//! Sets the cached master password (and verifies it if its hash is in authentication database)
|
||||
static void setMasterPassword( QgsMessageBar *msgbar );
|
||||
|
||||
|
||||
@ -128,7 +128,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
|
||||
@ -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