Skip to content

Commit

Permalink
Harden enum access
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Dec 4, 2024
1 parent dd944cf commit f532021
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 113 deletions.
71 changes: 42 additions & 29 deletions src/auth/oauth2/core/qgsauthoauth2config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ void QgsAuthOAuth2Config::setToDefaults()
{
setId( QString() );
setVersion( 1 );
setConfigType( QgsAuthOAuth2Config::Custom );
setGrantFlow( QgsAuthOAuth2Config::AuthCode );
setConfigType( QgsAuthOAuth2Config::ConfigType::Custom );
setGrantFlow( QgsAuthOAuth2Config::GrantFlow::AuthCode );
setName( QString() );
setDescription( QString() );
setRequestUrl( QString() );
Expand All @@ -267,7 +267,7 @@ void QgsAuthOAuth2Config::setToDefaults()
setScope( QString() );
setApiKey( QString() );
setPersistToken( false );
setAccessMethod( QgsAuthOAuth2Config::Header );
setAccessMethod( QgsAuthOAuth2Config::AccessMethod::Header );
setCustomHeader( QString() );
setRequestTimeout( 30 ); // in seconds
setQueryPairs( QVariantMap() );
Expand Down Expand Up @@ -299,15 +299,15 @@ void QgsAuthOAuth2Config::validateConfigId( bool needsId )
{
const bool oldvalid = mValid;

if ( mGrantFlow == AuthCode || mGrantFlow == Implicit )
if ( mGrantFlow == GrantFlow::AuthCode || mGrantFlow == GrantFlow::Implicit )
{
mValid = ( !requestUrl().isEmpty() && !tokenUrl().isEmpty() && !clientId().isEmpty() && ( ( mGrantFlow == AuthCode || mGrantFlow == Pkce ) ? !clientSecret().isEmpty() : true ) && redirectPort() > 0 && ( needsId ? !id().isEmpty() : true ) );
mValid = ( !requestUrl().isEmpty() && !tokenUrl().isEmpty() && !clientId().isEmpty() && ( ( mGrantFlow == GrantFlow::AuthCode || mGrantFlow == GrantFlow::Pkce ) ? !clientSecret().isEmpty() : true ) && redirectPort() > 0 && ( needsId ? !id().isEmpty() : true ) );
}
else if ( mGrantFlow == Pkce ) // No client secret for PKCE
else if ( mGrantFlow == GrantFlow::Pkce ) // No client secret for PKCE
{
mValid = ( !requestUrl().isEmpty() && !tokenUrl().isEmpty() && !clientId().isEmpty() && redirectPort() > 0 && ( needsId ? !id().isEmpty() : true ) );
}
else if ( mGrantFlow == ResourceOwner )
else if ( mGrantFlow == GrantFlow::ResourceOwner )
{
mValid = ( !tokenUrl().isEmpty() && !username().isEmpty() && !password().isEmpty() && ( needsId ? !id().isEmpty() : true ) );
}
Expand All @@ -324,7 +324,7 @@ bool QgsAuthOAuth2Config::loadConfigTxt(

switch ( format )
{
case JSON:
case ConfigFormat::JSON:
{
const QVariant variant = QgsJsonUtils::parseJson( configtxt.toStdString(), errStr );
if ( !errStr.isEmpty() )
Expand All @@ -341,11 +341,19 @@ bool QgsAuthOAuth2Config::loadConfigTxt(
if ( variantMap.contains( QStringLiteral( "clientSecret" ) ) )
setClientSecret( variantMap.value( QStringLiteral( "clientSecret" ) ).toString() );
if ( variantMap.contains( QStringLiteral( "configType" ) ) )
setConfigType( static_cast<ConfigType>( variantMap.value( QStringLiteral( "configType" ) ).toInt() ) );
{
const int configTypeInt = variantMap.value( QStringLiteral( "configType" ) ).toInt();
if ( configTypeInt >= 0 && configTypeInt <= static_cast<int>( ConfigType::Last ) )
setConfigType( static_cast<ConfigType>( configTypeInt ) );
}
if ( variantMap.contains( QStringLiteral( "description" ) ) )
setDescription( variantMap.value( QStringLiteral( "description" ) ).toString() );
if ( variantMap.contains( QStringLiteral( "grantFlow" ) ) )
setGrantFlow( static_cast<GrantFlow>( variantMap.value( QStringLiteral( "grantFlow" ) ).toInt() ) );
{
const int grantFlowInt = variantMap.value( QStringLiteral( "grantFlow" ) ).toInt();
if ( grantFlowInt >= 0 && grantFlowInt <= static_cast<int>( GrantFlow::Last ) )
setGrantFlow( static_cast<GrantFlow>( grantFlowInt ) );
}
if ( variantMap.contains( QStringLiteral( "id" ) ) )
setId( variantMap.value( QStringLiteral( "id" ) ).toString() );
if ( variantMap.contains( QStringLiteral( "name" ) ) )
Expand All @@ -365,7 +373,12 @@ bool QgsAuthOAuth2Config::loadConfigTxt(
if ( variantMap.contains( QStringLiteral( "refreshTokenUrl" ) ) )
setRefreshTokenUrl( variantMap.value( QStringLiteral( "refreshTokenUrl" ) ).toString() );
if ( variantMap.contains( QStringLiteral( "accessMethod" ) ) )
setAccessMethod( static_cast<AccessMethod>( variantMap.value( QStringLiteral( "accessMethod" ) ).toInt() ) );
{
const int accessMethodInt = variantMap.value( QStringLiteral( "accessMethod" ) ).toInt();
if ( accessMethodInt >= 0 && accessMethodInt <= static_cast<int>( AccessMethod::Last ) )
setAccessMethod( static_cast<AccessMethod>( accessMethodInt ) );
}

if ( variantMap.contains( QStringLiteral( "customHeader" ) ) )
setCustomHeader( variantMap.value( QStringLiteral( "customHeader" ) ).toString() );
if ( variantMap.contains( QStringLiteral( "requestTimeout" ) ) )
Expand Down Expand Up @@ -406,7 +419,7 @@ QByteArray QgsAuthOAuth2Config::saveConfigTxt(

switch ( format )
{
case JSON:
case ConfigFormat::JSON:
{
QVariantMap variant;
variant.insert( "accessMethod", static_cast<int>( accessMethod() ) );
Expand Down Expand Up @@ -489,7 +502,7 @@ QByteArray QgsAuthOAuth2Config::serializeFromVariant(
bool res = false;
switch ( format )
{
case JSON:
case ConfigFormat::JSON:
out = QByteArray::fromStdString( QgsJsonUtils::jsonFromVariant( variant ).dump( pretty ? 4 : -1 ) );
res = true;
break;
Expand All @@ -514,7 +527,7 @@ QVariantMap QgsAuthOAuth2Config::variantFromSerialized(

switch ( format )
{
case JSON:
case ConfigFormat::JSON:
{
const QVariant var = QgsJsonUtils::parseJson( serial.toStdString(), errStr );
if ( !errStr.isEmpty() )
Expand Down Expand Up @@ -609,7 +622,7 @@ QList<QgsAuthOAuth2Config *> QgsAuthOAuth2Config::loadOAuth2Configs(

switch ( format )
{
case JSON:
case ConfigFormat::JSON:
namefilters << QStringLiteral( "*.json" );
break;
default:
Expand Down Expand Up @@ -689,7 +702,7 @@ QgsStringMap QgsAuthOAuth2Config::mapOAuth2Configs(

switch ( format )
{
case JSON:
case ConfigFormat::JSON:
namefilters << QStringLiteral( "*.json" );
break;
default:
Expand Down Expand Up @@ -790,7 +803,7 @@ QgsStringMap QgsAuthOAuth2Config::mappedOAuth2ConfigsCache( QObject *parent, con
continue;
}
const QgsStringMap newconfigs = QgsAuthOAuth2Config::mapOAuth2Configs(
configdirinfo.canonicalFilePath(), parent, QgsAuthOAuth2Config::JSON, &ok
configdirinfo.canonicalFilePath(), parent, QgsAuthOAuth2Config::ConfigFormat::JSON, &ok
);
if ( ok )
{
Expand Down Expand Up @@ -822,44 +835,44 @@ QString QgsAuthOAuth2Config::configTypeString( QgsAuthOAuth2Config::ConfigType c
{
switch ( configtype )
{
case QgsAuthOAuth2Config::Custom:
case QgsAuthOAuth2Config::ConfigType::Custom:
return tr( "Custom" );
case QgsAuthOAuth2Config::Predefined:
default:
case QgsAuthOAuth2Config::ConfigType::Predefined:
return tr( "Predefined" );
}
BUILTIN_UNREACHABLE
}

// static
QString QgsAuthOAuth2Config::grantFlowString( QgsAuthOAuth2Config::GrantFlow flow )
{
switch ( flow )
{
case QgsAuthOAuth2Config::AuthCode:
case QgsAuthOAuth2Config::GrantFlow::AuthCode:
return tr( "Authorization Code" );
case QgsAuthOAuth2Config::Implicit:
case QgsAuthOAuth2Config::GrantFlow::Implicit:
return tr( "Implicit" );
case QgsAuthOAuth2Config::Pkce:
case QgsAuthOAuth2Config::GrantFlow::Pkce:
return tr( "Authorization Code PKCE" );
case QgsAuthOAuth2Config::ResourceOwner:
default:
case QgsAuthOAuth2Config::GrantFlow::ResourceOwner:
return tr( "Resource Owner" );
}
BUILTIN_UNREACHABLE
}

// static
QString QgsAuthOAuth2Config::accessMethodString( QgsAuthOAuth2Config::AccessMethod method )
{
switch ( method )
{
case QgsAuthOAuth2Config::Header:
case QgsAuthOAuth2Config::AccessMethod::Header:
return tr( "Header" );
case QgsAuthOAuth2Config::Form:
case QgsAuthOAuth2Config::AccessMethod::Form:
return tr( "Form (POST only)" );
case QgsAuthOAuth2Config::Query:
default:
case QgsAuthOAuth2Config::AccessMethod::Query:
return tr( "URL Query" );
}
BUILTIN_UNREACHABLE
}

// static
Expand Down
80 changes: 42 additions & 38 deletions src/auth/oauth2/core/qgsauthoauth2config.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,64 +30,68 @@
class QgsAuthOAuth2Config : public QObject
{
Q_OBJECT
Q_ENUMS( ConfigType )
Q_ENUMS( GrantFlow )
Q_ENUMS( ConfigFormat )
Q_ENUMS( AccessMethod )
Q_PROPERTY( QString id READ id WRITE setId NOTIFY idChanged )
Q_PROPERTY( int version READ version WRITE setVersion NOTIFY versionChanged )
Q_PROPERTY( ConfigType configType READ configType WRITE setConfigType NOTIFY configTypeChanged )
Q_PROPERTY( GrantFlow grantFlow READ grantFlow WRITE setGrantFlow NOTIFY grantFlowChanged )
Q_PROPERTY( QString name READ name WRITE setName NOTIFY nameChanged )
Q_PROPERTY( QString description READ description WRITE setDescription NOTIFY descriptionChanged )
Q_PROPERTY( QString requestUrl READ requestUrl WRITE setRequestUrl NOTIFY requestUrlChanged )
Q_PROPERTY( QString tokenUrl READ tokenUrl WRITE setTokenUrl NOTIFY tokenUrlChanged )
Q_PROPERTY( QString refreshTokenUrl READ refreshTokenUrl WRITE setRefreshTokenUrl NOTIFY refreshTokenUrlChanged )
Q_PROPERTY( QString redirectHost READ redirectHost WRITE setRedirectHost NOTIFY redirectHostChanged )
Q_PROPERTY( QString redirectUrl READ redirectUrl WRITE setRedirectUrl NOTIFY redirectUrlChanged )
Q_PROPERTY( int redirectPort READ redirectPort WRITE setRedirectPort NOTIFY redirectPortChanged )
Q_PROPERTY( QString clientId READ clientId WRITE setClientId NOTIFY clientIdChanged )
Q_PROPERTY( QString clientSecret READ clientSecret WRITE setClientSecret NOTIFY clientSecretChanged )
Q_PROPERTY( QString username READ username WRITE setUsername NOTIFY usernameChanged )
Q_PROPERTY( QString password READ password WRITE setPassword NOTIFY passwordChanged )
Q_PROPERTY( QString scope READ scope WRITE setScope NOTIFY scopeChanged )
Q_PROPERTY( QString apiKey READ apiKey WRITE setApiKey NOTIFY apiKeyChanged )
Q_PROPERTY( bool persistToken READ persistToken WRITE setPersistToken NOTIFY persistTokenChanged )
Q_PROPERTY( AccessMethod accessMethod READ accessMethod WRITE setAccessMethod NOTIFY accessMethodChanged )
Q_PROPERTY( int requestTimeout READ requestTimeout WRITE setRequestTimeout NOTIFY requestTimeoutChanged )
Q_PROPERTY( QVariantMap queryPairs READ queryPairs WRITE setQueryPairs NOTIFY queryPairsChanged )
Q_PROPERTY( QString customHeader READ customHeader WRITE setCustomHeader NOTIFY customHeaderChanged )

public:
//! Configuration type
enum ConfigType
enum class ConfigType : int
{
Predefined,
Custom,
Last = Custom
};
Q_ENUM( ConfigType )

//! OAuth2 grant flow
enum GrantFlow
enum class GrantFlow : int
{
AuthCode, //!< See http://tools.ietf.org/html/rfc6749#section-4.1
Implicit, //!< See http://tools.ietf.org/html/rfc6749#section-4.2
ResourceOwner, //!< See http://tools.ietf.org/html/rfc6749#section-4.3
Pkce, //!< See https://www.rfc-editor.org/rfc/rfc7636
Last = Pkce
};
Q_ENUM( GrantFlow )

//! Configuration format for serialize/unserialize operations
enum ConfigFormat
enum class ConfigFormat : int
{
JSON,
};
Q_ENUM( ConfigFormat )

//! Access method
enum AccessMethod
enum class AccessMethod : int
{
Header,
Form,
Query,
Last = Query
};
Q_ENUM( AccessMethod )

Q_PROPERTY( QString id READ id WRITE setId NOTIFY idChanged )
Q_PROPERTY( int version READ version WRITE setVersion NOTIFY versionChanged )
Q_PROPERTY( ConfigType configType READ configType WRITE setConfigType NOTIFY configTypeChanged )
Q_PROPERTY( GrantFlow grantFlow READ grantFlow WRITE setGrantFlow NOTIFY grantFlowChanged )
Q_PROPERTY( QString name READ name WRITE setName NOTIFY nameChanged )
Q_PROPERTY( QString description READ description WRITE setDescription NOTIFY descriptionChanged )
Q_PROPERTY( QString requestUrl READ requestUrl WRITE setRequestUrl NOTIFY requestUrlChanged )
Q_PROPERTY( QString tokenUrl READ tokenUrl WRITE setTokenUrl NOTIFY tokenUrlChanged )
Q_PROPERTY( QString refreshTokenUrl READ refreshTokenUrl WRITE setRefreshTokenUrl NOTIFY refreshTokenUrlChanged )
Q_PROPERTY( QString redirectHost READ redirectHost WRITE setRedirectHost NOTIFY redirectHostChanged )
Q_PROPERTY( QString redirectUrl READ redirectUrl WRITE setRedirectUrl NOTIFY redirectUrlChanged )
Q_PROPERTY( int redirectPort READ redirectPort WRITE setRedirectPort NOTIFY redirectPortChanged )
Q_PROPERTY( QString clientId READ clientId WRITE setClientId NOTIFY clientIdChanged )
Q_PROPERTY( QString clientSecret READ clientSecret WRITE setClientSecret NOTIFY clientSecretChanged )
Q_PROPERTY( QString username READ username WRITE setUsername NOTIFY usernameChanged )
Q_PROPERTY( QString password READ password WRITE setPassword NOTIFY passwordChanged )
Q_PROPERTY( QString scope READ scope WRITE setScope NOTIFY scopeChanged )
Q_PROPERTY( QString apiKey READ apiKey WRITE setApiKey NOTIFY apiKeyChanged )
Q_PROPERTY( bool persistToken READ persistToken WRITE setPersistToken NOTIFY persistTokenChanged )
Q_PROPERTY( AccessMethod accessMethod READ accessMethod WRITE setAccessMethod NOTIFY accessMethodChanged )
Q_PROPERTY( int requestTimeout READ requestTimeout WRITE setRequestTimeout NOTIFY requestTimeoutChanged )
Q_PROPERTY( QVariantMap queryPairs READ queryPairs WRITE setQueryPairs NOTIFY queryPairsChanged )
Q_PROPERTY( QString customHeader READ customHeader WRITE setCustomHeader NOTIFY customHeaderChanged )

//! Construct a QgsAuthOAuth2Config instance
explicit QgsAuthOAuth2Config( QObject *parent = nullptr );
Expand Down Expand Up @@ -180,10 +184,10 @@ class QgsAuthOAuth2Config : public QObject
void validateConfigId( bool needsId = false );

//! Load a string (e.g. JSON) of a config
bool loadConfigTxt( const QByteArray &configtxt, ConfigFormat format = JSON );
bool loadConfigTxt( const QByteArray &configtxt, ConfigFormat format = ConfigFormat::JSON );

//! Save a config to a string (e.g. JSON)
QByteArray saveConfigTxt( ConfigFormat format = JSON, bool pretty = false, bool *ok = nullptr ) const;
QByteArray saveConfigTxt( ConfigFormat format = ConfigFormat::JSON, bool pretty = false, bool *ok = nullptr ) const;

//! Configuration as a QVariant map
QVariantMap mappedProperties() const;
Expand All @@ -196,7 +200,7 @@ class QgsAuthOAuth2Config : public QObject
* \param ok is set to FALSE in case something goes wrong, TRUE otherwise
* \return serialized config
*/
static QByteArray serializeFromVariant( const QVariantMap &variant, ConfigFormat format = JSON, bool pretty = false, bool *ok = nullptr );
static QByteArray serializeFromVariant( const QVariantMap &variant, ConfigFormat format = ConfigFormat::JSON, bool pretty = false, bool *ok = nullptr );

/**
* Unserialize the configuration in \a serial according to \a format
Expand All @@ -205,24 +209,24 @@ class QgsAuthOAuth2Config : public QObject
* \param ok is set to FALSE in case something goes wrong, TRUE otherwise
* \return config map
*/
static QVariantMap variantFromSerialized( const QByteArray &serial, ConfigFormat format = JSON, bool *ok = nullptr );
static QVariantMap variantFromSerialized( const QByteArray &serial, ConfigFormat format = ConfigFormat::JSON, bool *ok = nullptr );

//! Write config object out to a formatted file (e.g. JSON)
static bool writeOAuth2Config( const QString &filepath, QgsAuthOAuth2Config *config, ConfigFormat format = JSON, bool pretty = false );
static bool writeOAuth2Config( const QString &filepath, QgsAuthOAuth2Config *config, ConfigFormat format = ConfigFormat::JSON, bool pretty = false );

//! Load and parse a directory of configs (e.g. JSON) to objects
static QList<QgsAuthOAuth2Config *> loadOAuth2Configs(
const QString &configdirectory,
QObject *parent = nullptr,
ConfigFormat format = JSON,
ConfigFormat format = ConfigFormat::JSON,
bool *ok = nullptr
);

//! Load and parse a directory of configs (e.g. JSON) to a map
static QgsStringMap mapOAuth2Configs(
const QString &configdirectory,
QObject *parent = nullptr,
ConfigFormat format = JSON,
ConfigFormat format = ConfigFormat::JSON,
bool *ok = nullptr
);

Expand Down
12 changes: 6 additions & 6 deletions src/auth/oauth2/core/qgsauthoauth2method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ bool QgsAuthOAuth2Method::updateNetworkRequest( QNetworkRequest &request, const

switch ( accessmethod )
{
case QgsAuthOAuth2Config::Header:
case QgsAuthOAuth2Config::AccessMethod::Header:
{
const QString header = o2->oauth2config()->customHeader().isEmpty() ? QString( O2_HTTP_AUTHORIZATION_HEADER ) : o2->oauth2config()->customHeader();
request.setRawHeader( header.toLatin1(), QStringLiteral( "Bearer %1" ).arg( o2->token() ).toLatin1() );
Expand All @@ -328,13 +328,13 @@ bool QgsAuthOAuth2Method::updateNetworkRequest( QNetworkRequest &request, const
#endif
break;
}
case QgsAuthOAuth2Config::Form:
case QgsAuthOAuth2Config::AccessMethod::Form:
// FIXME: what to do here if the parent request is not POST?
// probably have to skip this until auth system support is moved into QgsNetworkAccessManager
msg = QStringLiteral( "Update request FAILED for authcfg %1: form POST token update is unsupported" ).arg( authcfg );
QgsMessageLog::logMessage( msg, AUTH_METHOD_KEY, Qgis::MessageLevel::Warning );
break;
case QgsAuthOAuth2Config::Query:
case QgsAuthOAuth2Config::AccessMethod::Query:
if ( !query.hasQueryItem( O2_OAUTH2_ACCESS_TOKEN ) )
{
query.addQueryItem( O2_OAUTH2_ACCESS_TOKEN, o2->token() );
Expand Down Expand Up @@ -616,7 +616,7 @@ QgsO2 *QgsAuthOAuth2Method::getOAuth2Bundle( const QString &authcfg, bool fullco
//QgsDebugMsgLevel( QStringLiteral( "LOAD oauth2config configtxt: \n\n%1\n\n" ).arg( QString( configtxt ) ), 2 );
//###################### DO NOT LEAVE ME UNCOMMENTED #####################

if ( !config->loadConfigTxt( configtxt, QgsAuthOAuth2Config::JSON ) )
if ( !config->loadConfigTxt( configtxt, QgsAuthOAuth2Config::ConfigFormat::JSON ) )
{
QgsDebugError( QStringLiteral( "FAILED to load OAuth2 config into object" ) );
return nullptr;
Expand Down Expand Up @@ -653,7 +653,7 @@ QgsO2 *QgsAuthOAuth2Method::getOAuth2Bundle( const QString &authcfg, bool fullco
return nullptr;
}

if ( !config->loadConfigTxt( definedtxt, QgsAuthOAuth2Config::JSON ) )
if ( !config->loadConfigTxt( definedtxt, QgsAuthOAuth2Config::ConfigFormat::JSON ) )
{
QgsDebugError( QStringLiteral( "FAILED to load config text for defined ID: %1" ).arg( definedid ) );
return nullptr;
Expand All @@ -662,7 +662,7 @@ QgsO2 *QgsAuthOAuth2Method::getOAuth2Bundle( const QString &authcfg, bool fullco
const QByteArray querypairstxt = configmap.value( QStringLiteral( "querypairs" ) ).toUtf8();
if ( !querypairstxt.isNull() && !querypairstxt.isEmpty() )
{
const QVariantMap querypairsmap = QgsAuthOAuth2Config::variantFromSerialized( querypairstxt, QgsAuthOAuth2Config::JSON, &ok );
const QVariantMap querypairsmap = QgsAuthOAuth2Config::variantFromSerialized( querypairstxt, QgsAuthOAuth2Config::ConfigFormat::JSON, &ok );
if ( !ok )
{
QgsDebugError( QStringLiteral( "No query pairs to load OAuth2 config: FAILED to parse" ) );
Expand Down
Loading

0 comments on commit f532021

Please sign in to comment.