Skip to content

Commit

Permalink
SIP changes to support python storage implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Jul 9, 2024
1 parent 81c2460 commit a30666d
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@



class QgsAuthConfigurationStorage: QObject /Abstract/
class QgsAuthConfigurationStorage: QObject
{
%Docstring(signature="appended")
Abstract class that defines the interface for all authentication configuration storage implementations.
Expand Down Expand Up @@ -190,6 +190,14 @@ certIdentity get a certificate identity by ``id`` (sha hash)
:return: the certificate
%End

virtual const QPair<QSslCertificate, QString> loadCertIdentityBundle( const QString &id ) const = 0;
%Docstring
Returns a certificate identity bundle by ``id`` (sha hash).

:param id: sha shash

:return: a pair with the certificate and its SSL key as an encrypted string
%End

virtual const QList<QSslCertificate> certIdentities() const = 0;
%Docstring
Expand Down Expand Up @@ -325,8 +333,28 @@ Check if certificate trust policy exists
%End


virtual const QList<QgsAuthConfigurationStorage::MasterPasswordConfig> masterPasswords( ) const = 0;
%Docstring
Returns the list of (encrypted) master passwords stored in the database.

:return: list of master passwords
%End

virtual bool storeMasterPassword( const QgsAuthConfigurationStorage::MasterPasswordConfig &config ) = 0;
%Docstring
Store a master password in the database.

:param config: Master password configuration.

:return: ``True`` if operation succeeded
%End

virtual bool clearMasterPasswords() = 0;
%Docstring
Remove all master passwords from the database.

:return: ``True`` if operation succeeded
%End

virtual bool erase() = 0;
%Docstring
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@



class QgsAuthConfigurationStorage: QObject /Abstract/
class QgsAuthConfigurationStorage: QObject
{
%Docstring(signature="appended")
Abstract class that defines the interface for all authentication configuration storage implementations.
Expand Down Expand Up @@ -190,6 +190,14 @@ certIdentity get a certificate identity by ``id`` (sha hash)
:return: the certificate
%End

virtual const QPair<QSslCertificate, QString> loadCertIdentityBundle( const QString &id ) const = 0;
%Docstring
Returns a certificate identity bundle by ``id`` (sha hash).

:param id: sha shash

:return: a pair with the certificate and its SSL key as an encrypted string
%End

virtual const QList<QSslCertificate> certIdentities() const = 0;
%Docstring
Expand Down Expand Up @@ -325,8 +333,28 @@ Check if certificate trust policy exists
%End


virtual const QList<QgsAuthConfigurationStorage::MasterPasswordConfig> masterPasswords( ) const = 0;
%Docstring
Returns the list of (encrypted) master passwords stored in the database.

:return: list of master passwords
%End

virtual bool storeMasterPassword( const QgsAuthConfigurationStorage::MasterPasswordConfig &config ) = 0;
%Docstring
Store a master password in the database.

:param config: Master password configuration.

:return: ``True`` if operation succeeded
%End

virtual bool clearMasterPasswords() = 0;
%Docstring
Remove all master passwords from the database.

:return: ``True`` if operation succeeded
%End

virtual bool erase() = 0;
%Docstring
Expand Down
14 changes: 7 additions & 7 deletions src/core/auth/qgsauthconfigurationstorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,33 @@ QgsAuthConfigurationStorage::QgsAuthConfigurationStorage( const QMap<QString, QS
: mConfiguration( configuration )
{
// Forward all specific signals to the generic one
connect( this, &QgsAuthConfigurationStorage::methodConfigChanged, this, [ = ]
connect( this, &QgsAuthConfigurationStorage::methodConfigChanged, this, [ this ]
{
emit storageChanged( id() );
} );
connect( this, &QgsAuthConfigurationStorage::masterPasswordChanged, this, [ = ]
connect( this, &QgsAuthConfigurationStorage::masterPasswordChanged, this, [ this ]
{
emit storageChanged( id() );
} );
connect( this, &QgsAuthConfigurationStorage::authSettingsChanged, this, [ = ]
connect( this, &QgsAuthConfigurationStorage::authSettingsChanged, this, [ this ]
{
emit storageChanged( id() );
} );

#ifndef QT_NO_SSL
connect( this, &QgsAuthConfigurationStorage::certIdentityChanged, this, [ = ]
connect( this, &QgsAuthConfigurationStorage::certIdentityChanged, this, [ this ]
{
emit storageChanged( id() );
} );
connect( this, &QgsAuthConfigurationStorage::certAuthorityChanged, this, [ = ]
connect( this, &QgsAuthConfigurationStorage::certAuthorityChanged, this, [ this ]
{
emit storageChanged( id() );
} );
connect( this, &QgsAuthConfigurationStorage::sslCertCustomConfigChanged, this, [ = ]
connect( this, &QgsAuthConfigurationStorage::sslCertCustomConfigChanged, this, [ this ]
{
emit storageChanged( id() );
} );
connect( this, &QgsAuthConfigurationStorage::sslCertTrustPolicyChanged, this, [ = ]
connect( this, &QgsAuthConfigurationStorage::sslCertTrustPolicyChanged, this, [ this ]
{
emit storageChanged( id() );
} );
Expand Down
14 changes: 5 additions & 9 deletions src/core/auth/qgsauthconfigurationstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
* Abstract class that defines the interface for all authentication configuration storage implementations.
* \since QGIS 3.40
*/
class CORE_EXPORT QgsAuthConfigurationStorage: public QObject SIP_ABSTRACT
class CORE_EXPORT QgsAuthConfigurationStorage: public QObject
{
Q_OBJECT

Expand Down Expand Up @@ -185,9 +185,8 @@ class CORE_EXPORT QgsAuthConfigurationStorage: public QObject SIP_ABSTRACT
* Returns a certificate identity bundle by \a id (sha hash).
* \param id sha shash
* \return a pair with the certificate and its SSL key as an encrypted string
* \note not available in Python bindings
*/
virtual const QPair<QSslCertificate, QString> loadCertIdentityBundle( const QString &id ) const SIP_SKIP = 0;
virtual const QPair<QSslCertificate, QString> loadCertIdentityBundle( const QString &id ) const = 0;

/**
* \brief certIdentities get certificate identities
Expand Down Expand Up @@ -288,24 +287,21 @@ class CORE_EXPORT QgsAuthConfigurationStorage: public QObject SIP_ABSTRACT
/**
* Returns the list of (encrypted) master passwords stored in the database.
* \returns list of master passwords
* \note not available in Python bindings
*/
virtual const QList<QgsAuthConfigurationStorage::MasterPasswordConfig> masterPasswords( ) const SIP_SKIP = 0;
virtual const QList<QgsAuthConfigurationStorage::MasterPasswordConfig> masterPasswords( ) const = 0;

/**
* Store a master password in the database.
* \param config Master password configuration.
* \returns TRUE if operation succeeded
* \note not available in Python bindings
*/
virtual bool storeMasterPassword( const QgsAuthConfigurationStorage::MasterPasswordConfig &config ) SIP_SKIP = 0;
virtual bool storeMasterPassword( const QgsAuthConfigurationStorage::MasterPasswordConfig &config ) = 0;

/**
* Remove all master passwords from the database.
* \returns TRUE if operation succeeded
* \note not available in Python bindings
*/
virtual bool clearMasterPasswords() SIP_SKIP = 0;
virtual bool clearMasterPasswords() = 0;

/**
* Completely erase the storage removing all configurations/certs/settings etc.
Expand Down
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ if (ENABLE_PGTEST)
ADD_PYTHON_TEST(PyQgsDatabaseSchemaModel test_qgsdatabaseschemamodel.py)
ADD_PYTHON_TEST(PyQgsDatabaseTableModel test_qgsdatabasetablemodel.py)
ADD_PYTHON_TEST(PyQgsAuthManagerStoragePsql test_authmanager_storage_psql.py)
ADD_PYTHON_TEST(PyQgsAuthManagerStorageCustom test_authmanager_storage_custom.py)
if (WITH_GUI)
ADD_PYTHON_TEST(PyQgsPostgresProvider test_provider_postgres.py)
ADD_PYTHON_TEST(PyQgsDatabaseSchemaComboBox test_qgsdatabaseschemacombobox.py)
Expand Down
104 changes: 104 additions & 0 deletions tests/src/python/qgsauthconfigurationcustomstorage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""A custom storage for QgsAuthManager that stores the authentication
configurations in memory.
WARNING: For testing purposes only.
"""

import json
import uuid
from qgis.core import (
Qgis,
QgsAuthConfigurationStorage,
QgsAuthMethodConfig,
QgsAuthConfigSslServer,
QgsAuthCertUtils,
)
from qgis.PyQt.QtNetwork import QSslCertificate


class QgsAuthConfigurationCustomStorage(QgsAuthConfigurationStorage):
"""Only for testing purposes: supports authentication
configuration storage in memory"""

def __init__(self, params: dict = {}):
super().__init__(params)
self.configs = {}
self.payloads = {}
self._initialized = False
self._id = str(uuid.uuid4())
self.is_encrypted = params.get('is_encrypted', 'true') in ['true', 'True', '1', 'TRUE', 'on', 'ON', 'YES', 'yes']

def settingsParams(self):
return {
'is_encrypted': 'Whether the storage is encrypted or not'
}

def isEncrypted(self):
return self.is_encrypted

def name(self):
return 'Custom'

def description(self):
return 'Custom storage'

def type(self):
return 'custom'

def id(self):
return self._id

def capabilities(self):
return (Qgis.AuthConfigurationStorageCapability.ReadConfiguration |
Qgis.AuthConfigurationStorageCapability.DeleteConfiguration |
Qgis.AuthConfigurationStorageCapability.CreateConfiguration |
Qgis.AuthConfigurationStorageCapability.UpdateConfiguration |
Qgis.AuthConfigurationStorageCapability.ClearStorage)

def isReady(self):
return self._initialized

def initialize(self):
self._initialized = True
return True

def authMethodConfigs(self, allowedMethods=[]):
if len(allowedMethods) == 0:
return self.configs.values()
return [c for c in self.configs.values() if c.method() in allowedMethods]

def storeMethodConfig(self, config: QgsAuthMethodConfig, payload: str):
if not config.id():
return False

self.configs[config.id()] = config
self.payloads[config.id()] = payload
return True

def removeMethodConfig(self, id: str):
if id in self.configs:
del self.configs[id]
del self.payloads[id]
return True
return False

def clearMethodConfigs(self):
self.configs.clear()
self.payloads.clear()
return True

def loadMethodConfig(self, id: str, full=False):
if full:
return self.configs.get(id, QgsAuthMethodConfig()), self.payloads[id]
else:
config = self.configs.get(id, QgsAuthMethodConfig())
config.clearConfigMap()
return self.configs.get(id, QgsAuthMethodConfig()), ''

def authMethodConfigsWithPayload(self) -> str:
configs = {}
for id, config in self.configs.items():
configs[id] = config
configs[id].setConfig('encrypted_payload', self.payloads[id])
return configs
Loading

0 comments on commit a30666d

Please sign in to comment.