Skip to content

Commit

Permalink
[FEATURE][processing] Add a new parameter type for authentication config
Browse files Browse the repository at this point in the history
This adds a new available parameter type for processing algorithms,
QgsProcessingParameterAuthConfig, allowing selection from available
authentication configurations (and creation of new ones).

It allows creation of processing algorithm which can fully take
advantage of QGIS' mature authentication handling, avoiding the
need to use insecure string parameters for users to input
sensitive logon credentials.

QgsProcessingParameterAuthConfig parameters are evaluated using
QgsProcessingAlgorithm.parameterAsString(), which returns the
selected authentication configuration ID.
  • Loading branch information
nyalldawson committed Dec 14, 2018
1 parent 8f06b5a commit 11ea28a
Show file tree
Hide file tree
Showing 14 changed files with 519 additions and 15 deletions.
Expand Up @@ -161,6 +161,8 @@ their acceptable ranges, defaults, etc.
sipType = sipType_QgsProcessingParameterString;
else if ( sipCpp->type() == QgsProcessingParameterExpression::typeName() )
sipType = sipType_QgsProcessingParameterExpression;
else if ( sipCpp->type() == QgsProcessingParameterAuthConfig::typeName() )
sipType = sipType_QgsProcessingParameterAuthConfig;
else if ( sipCpp->type() == QgsProcessingParameterVectorLayer::typeName() )
sipType = sipType_QgsProcessingParameterVectorLayer;
else if ( sipCpp->type() == QgsProcessingParameterField::typeName() )
Expand Down Expand Up @@ -1767,6 +1769,50 @@ Creates a new parameter using the definition from a script code.

};


class QgsProcessingParameterAuthConfig : QgsProcessingParameterDefinition
{
%Docstring
A string parameter for authentication configuration configuration ID values.

This parameter allows for users to select from available authentication configurations,
or create new authentication configurations as required.

QgsProcessingParameterAuthConfig should be evaluated by calling :py:func:`QgsProcessingAlgorithm.parameterAsString()`

.. versionadded:: 3.6
%End

%TypeHeaderCode
#include "qgsprocessingparameters.h"
%End
public:

QgsProcessingParameterAuthConfig( const QString &name, const QString &description = QString(), const QVariant &defaultValue = QVariant(),
bool optional = false );
%Docstring
Constructor for QgsProcessingParameterAuthConfig.
%End

static QString typeName();
%Docstring
Returns the type name for the parameter class.
%End
virtual QgsProcessingParameterDefinition *clone() const /Factory/;

virtual QString type() const;
virtual QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const;

virtual QString asScriptCode() const;


static QgsProcessingParameterAuthConfig *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) /Factory/;
%Docstring
Creates a new parameter using the definition from a script code.
%End

};

class QgsProcessingParameterExpression : QgsProcessingParameterDefinition
{
%Docstring
Expand Down
6 changes: 5 additions & 1 deletion python/processing/algfactory.py
Expand Up @@ -31,6 +31,7 @@
from qgis.core import (QgsProcessingParameterDefinition,
QgsProcessingAlgorithm,
QgsProcessingParameterString,
QgsProcessingParameterAuthConfig,
QgsProcessingParameterNumber,
QgsProcessingParameterDistance,
QgsProcessingParameterFeatureSource,
Expand Down Expand Up @@ -222,7 +223,7 @@ def _get_parameter_value(self, parm, parameters, name, context):
"""
Extract the real value from the parameter.
"""
if isinstance(parm, QgsProcessingParameterString):
if isinstance(parm, (QgsProcessingParameterString, QgsProcessingParameterAuthConfig)):
value = self.parameterAsString(parameters, name, context)
return value
elif isinstance(parm, QgsProcessingParameterNumber):
Expand Down Expand Up @@ -312,6 +313,7 @@ class ProcessingAlgFactory():
MATRIX = "MATRIX",
POINT = "POINT",
RANGE = "RANGE",
AUTH_CFG = "AUTH_CFG"

def __init__(self):
self._current = None
Expand Down Expand Up @@ -436,6 +438,7 @@ def input(self, type, *args, **kwargs):
alg.POINT: QgsProcessingParameterPoint
alg.RANGE: QgsProcessingParameterRange
alg.VECTOR_LAYER: QgsProcessingParameterVectorLayer
alg.AUTH_CFG: QgsProcessingParameterAuthConfig
:param type: The type of the input. This should be a type define on `alg` like alg.STRING, alg.DISTANCE
Expand Down Expand Up @@ -481,6 +484,7 @@ def dec(f):
ProcessingAlgFactory.POINT: QgsProcessingParameterPoint,
ProcessingAlgFactory.RANGE: QgsProcessingParameterRange,
ProcessingAlgFactory.VECTOR_LAYER: QgsProcessingParameterVectorLayer,
ProcessingAlgFactory.AUTH_CFG: QgsProcessingParameterAuthConfig,
}

output_type_mapping = {
Expand Down
3 changes: 2 additions & 1 deletion src/core/processing/models/qgsprocessingmodelalgorithm.cpp
Expand Up @@ -452,7 +452,8 @@ QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> QgsProcessingMode
<< QgsProcessingParameterBoolean::typeName()
<< QgsProcessingParameterExpression::typeName()
<< QgsProcessingParameterField::typeName()
<< QgsProcessingParameterString::typeName(),
<< QgsProcessingParameterString::typeName()
<< QgsProcessingParameterAuthConfig::typeName(),
QStringList() << QgsProcessingOutputNumber::typeName()
<< QgsProcessingOutputString::typeName() );
Q_FOREACH ( const QgsProcessingModelChildParameterSource &source, sources )
Expand Down
60 changes: 60 additions & 0 deletions src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -1463,6 +1463,8 @@ QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromVariantM
def.reset( new QgsProcessingParameterEnum( name ) );
else if ( type == QgsProcessingParameterString::typeName() )
def.reset( new QgsProcessingParameterString( name ) );
else if ( type == QgsProcessingParameterAuthConfig::typeName() )
def.reset( new QgsProcessingParameterAuthConfig( name ) );
else if ( type == QgsProcessingParameterExpression::typeName() )
def.reset( new QgsProcessingParameterExpression( name ) );
else if ( type == QgsProcessingParameterVectorLayer::typeName() )
Expand Down Expand Up @@ -1543,6 +1545,8 @@ QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromScriptCo
return QgsProcessingParameterEnum::fromScriptCode( name, description, isOptional, definition );
else if ( type == QStringLiteral( "string" ) )
return QgsProcessingParameterString::fromScriptCode( name, description, isOptional, definition );
else if ( type == QStringLiteral( "authcfg" ) )
return QgsProcessingParameterAuthConfig::fromScriptCode( name, description, isOptional, definition );
else if ( type == QStringLiteral( "expression" ) )
return QgsProcessingParameterExpression::fromScriptCode( name, description, isOptional, definition );
else if ( type == QStringLiteral( "field" ) )
Expand Down Expand Up @@ -3008,6 +3012,62 @@ QgsProcessingParameterString *QgsProcessingParameterString::fromScriptCode( cons
return new QgsProcessingParameterString( name, description, defaultValue, multiLine, isOptional );
}

//
// QgsProcessingParameterAuthConfig
//

QgsProcessingParameterAuthConfig::QgsProcessingParameterAuthConfig( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
{

}

QgsProcessingParameterDefinition *QgsProcessingParameterAuthConfig::clone() const
{
return new QgsProcessingParameterAuthConfig( *this );
}

QString QgsProcessingParameterAuthConfig::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
{
if ( !value.isValid() )
return QStringLiteral( "None" );

QString s = value.toString();
return QgsProcessingUtils::stringToPythonLiteral( s );
}

QString QgsProcessingParameterAuthConfig::asScriptCode() const
{
QString code = QStringLiteral( "##%1=" ).arg( mName );
if ( mFlags & FlagOptional )
code += QStringLiteral( "optional " );
code += QStringLiteral( "authcfg " );

code += mDefault.toString();
return code.trimmed();
}

QgsProcessingParameterAuthConfig *QgsProcessingParameterAuthConfig::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
{
QString def = definition;

if ( def.startsWith( '"' ) || def.startsWith( '\'' ) )
def = def.mid( 1 );
if ( def.endsWith( '"' ) || def.endsWith( '\'' ) )
def.chop( 1 );

QVariant defaultValue = def;
if ( def == QStringLiteral( "None" ) )
defaultValue = QVariant();

return new QgsProcessingParameterAuthConfig( name, description, defaultValue, isOptional );
}


//
// QgsProcessingParameterExpression
//

QgsProcessingParameterExpression::QgsProcessingParameterExpression( const QString &name, const QString &description, const QVariant &defaultValue, const QString &parentLayerParameterName, bool optional )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
, mParentLayerParameterName( parentLayerParameterName )
Expand Down
53 changes: 47 additions & 6 deletions src/core/processing/qgsprocessingparameters.h
@@ -1,10 +1,10 @@
/***************************************************************************
qgsprocessingparameters.h
-------------------------
begin : April 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
qgsprocessingparameters.h
-------------------------
begin : April 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
Expand Down Expand Up @@ -234,6 +234,8 @@ class CORE_EXPORT QgsProcessingParameterDefinition
sipType = sipType_QgsProcessingParameterString;
else if ( sipCpp->type() == QgsProcessingParameterExpression::typeName() )
sipType = sipType_QgsProcessingParameterExpression;
else if ( sipCpp->type() == QgsProcessingParameterAuthConfig::typeName() )
sipType = sipType_QgsProcessingParameterAuthConfig;
else if ( sipCpp->type() == QgsProcessingParameterVectorLayer::typeName() )
sipType = sipType_QgsProcessingParameterVectorLayer;
else if ( sipCpp->type() == QgsProcessingParameterField::typeName() )
Expand Down Expand Up @@ -1723,6 +1725,45 @@ class CORE_EXPORT QgsProcessingParameterString : public QgsProcessingParameterDe

};


/**
* \class QgsProcessingParameterAuthConfig
* \ingroup core
* A string parameter for authentication configuration configuration ID values.
*
* This parameter allows for users to select from available authentication configurations,
* or create new authentication configurations as required.
*
* QgsProcessingParameterAuthConfig should be evaluated by calling QgsProcessingAlgorithm::parameterAsString().
*
* \since QGIS 3.6
*/
class CORE_EXPORT QgsProcessingParameterAuthConfig : public QgsProcessingParameterDefinition
{
public:

/**
* Constructor for QgsProcessingParameterAuthConfig.
*/
QgsProcessingParameterAuthConfig( const QString &name, const QString &description = QString(), const QVariant &defaultValue = QVariant(),
bool optional = false );

/**
* Returns the type name for the parameter class.
*/
static QString typeName() { return QStringLiteral( "authcfg" ); }
QgsProcessingParameterDefinition *clone() const override SIP_FACTORY;
QString type() const override { return typeName(); }
QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const override;
QString asScriptCode() const override;

/**
* Creates a new parameter using the definition from a script code.
*/
static QgsProcessingParameterAuthConfig *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) SIP_FACTORY;

};

/**
* \class QgsProcessingParameterExpression
* \ingroup core
Expand Down
35 changes: 35 additions & 0 deletions src/core/processing/qgsprocessingparametertypeimpl.h
Expand Up @@ -744,6 +744,41 @@ class CORE_EXPORT QgsProcessingParameterTypeString : public QgsProcessingParamet
}
};

/**
* A authentication configuration parameter for processing algorithms.
*
* \ingroup core
* \note No Python bindings available. Get your copy from QgsApplication.processingRegistry().parameterType('authcfg')
* \since QGIS 3.6
*/
class CORE_EXPORT QgsProcessingParameterTypeAuthConfig : public QgsProcessingParameterType
{
QgsProcessingParameterDefinition *create( const QString &name ) const override SIP_FACTORY
{
return new QgsProcessingParameterAuthConfig( name );
}

QString description() const override
{
return QCoreApplication::translate( "Processing", "A authentication configuration parameter." );
}

QString name() const override
{
return QCoreApplication::translate( "Processing", "Authentication Configuration" );
}

QString id() const override
{
return QStringLiteral( "authcfg" );
}

QStringList acceptedPythonTypes() const override
{
return QStringList() << QStringLiteral( "str" );
}
};

/**
* A parameter for processing algorithms which accepts multiple map layers.
*
Expand Down
1 change: 1 addition & 0 deletions src/core/processing/qgsprocessingregistry.cpp
Expand Up @@ -40,6 +40,7 @@ QgsProcessingRegistry::QgsProcessingRegistry( QObject *parent SIP_TRANSFERTHIS )
addParameterType( new QgsProcessingParameterTypeFileDestination() );
addParameterType( new QgsProcessingParameterTypeFolderDestination() );
addParameterType( new QgsProcessingParameterTypeString() );
addParameterType( new QgsProcessingParameterTypeAuthConfig() );
addParameterType( new QgsProcessingParameterTypeMultipleLayers() );
addParameterType( new QgsProcessingParameterTypeFeatureSource() );
addParameterType( new QgsProcessingParameterTypeNumber() );
Expand Down
1 change: 1 addition & 0 deletions src/gui/processing/qgsprocessingguiregistry.cpp
Expand Up @@ -33,6 +33,7 @@ QgsProcessingGuiRegistry::QgsProcessingGuiRegistry()
addParameterWidgetFactory( new QgsProcessingNumericWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingDistanceWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingRangeWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingAuthConfigWidgetWrapper() );
}

QgsProcessingGuiRegistry::~QgsProcessingGuiRegistry()
Expand Down

0 comments on commit 11ea28a

Please sign in to comment.