From e18546fec6ad9623a110b3001cb0622c830c749f Mon Sep 17 00:00:00 2001 From: Mathieu Pellerin Date: Wed, 16 Oct 2024 07:57:43 +0700 Subject: [PATCH] When loading a project with pending authentication requests, do not set an active layer to avoid potential crash --- src/core/qfieldappauthrequesthandler.cpp | 27 ++++++++++++++ src/core/qfieldappauthrequesthandler.h | 7 ++++ src/qml/qgismobileapp.qml | 46 +++++++++++------------- 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/src/core/qfieldappauthrequesthandler.cpp b/src/core/qfieldappauthrequesthandler.cpp index 7df4d183e5..6fa4757dc2 100644 --- a/src/core/qfieldappauthrequesthandler.cpp +++ b/src/core/qfieldappauthrequesthandler.cpp @@ -39,6 +39,24 @@ void QFieldAppAuthRequestHandler::enterCredentials( const QString &realm, const QgsCredentials::instance()->put( realm, username, password ); } +bool QFieldAppAuthRequestHandler::hasPendingAuthRequest() const +{ + if ( mBrowserAuthenticationOngoing ) + { + return true; + } + + int pendingCount = mRealms.size(); + for ( const RealmEntry &realm : mRealms ) + { + if ( realm.canceled ) + { + pendingCount--; + } + } + return pendingCount > 0; +} + QString QFieldAppAuthRequestHandler::getFirstUnhandledRealm() const { auto entry = std::find_if( mRealms.begin(), mRealms.end(), []( const RealmEntry &entry ) { return !entry.canceled; } ); @@ -59,6 +77,7 @@ bool QFieldAppAuthRequestHandler::handleLayerLogins() if ( mRealms.at( i ).realm == realm ) { mRealms.replace( i, RealmEntry( realm, true ) ); + emit hasPendingAuthRequestChanged(); break; } } @@ -71,6 +90,7 @@ bool QFieldAppAuthRequestHandler::handleLayerLogins() if ( mRealms.at( i ).realm == realm ) { mRealms.removeAt( i ); + emit hasPendingAuthRequestChanged(); break; } } @@ -116,6 +136,7 @@ void QFieldAppAuthRequestHandler::authNeeded( const QString &realm ) RealmEntry unhandledRealm( realm ); mRealms << unhandledRealm; + emit hasPendingAuthRequestChanged(); } void QFieldAppAuthRequestHandler::handleAuthRequest( QNetworkReply *reply, QAuthenticator *auth ) @@ -176,17 +197,23 @@ void QFieldAppAuthRequestHandler::handleAuthRequest( QNetworkReply *reply, QAuth void QFieldAppAuthRequestHandler::handleAuthRequestOpenBrowser( const QUrl &url ) { + mBrowserAuthenticationOngoing = true; + emit hasPendingAuthRequestChanged(); emit showLoginBrowser( url.toString() ); } void QFieldAppAuthRequestHandler::handleAuthRequestCloseBrowser() { emit hideLoginBrowser(); + mBrowserAuthenticationOngoing = false; + emit hasPendingAuthRequestChanged(); } void QFieldAppAuthRequestHandler::abortAuthBrowser() { QgsNetworkAccessManager::instance()->abortAuthBrowser(); + mBrowserAuthenticationOngoing = false; + emit hasPendingAuthRequestChanged(); } QString QFieldAppAuthRequestHandler::getCredentialTitle( const QString &realm ) diff --git a/src/core/qfieldappauthrequesthandler.h b/src/core/qfieldappauthrequesthandler.h index 8cbfc7e397..9ac1b9ee1e 100644 --- a/src/core/qfieldappauthrequesthandler.h +++ b/src/core/qfieldappauthrequesthandler.h @@ -38,6 +38,8 @@ class QFieldAppAuthRequestHandler : public QObject, public QgsCredentials, publi { Q_OBJECT + Q_PROPERTY( bool hasPendingAuthRequest READ hasPendingAuthRequest NOTIFY hasPendingAuthRequestChanged ) + public: QFieldAppAuthRequestHandler(); @@ -58,12 +60,16 @@ class QFieldAppAuthRequestHandler : public QObject, public QgsCredentials, publi //! abort an ongoing external browser authentication request Q_INVOKABLE void abortAuthBrowser(); + //! returns the number of pending authentication requests + bool hasPendingAuthRequest() const; + signals: void showLoginDialog( const QString &realm, const QString &title ); void loginDialogClosed( const QString &realm, const bool canceled ); void reloadEverything(); void showLoginBrowser( const QString &url ); void hideLoginBrowser(); + void hasPendingAuthRequestChanged(); protected: bool request( const QString &realm, QString &username, QString &password, const QString &message = QString() ) override; @@ -95,6 +101,7 @@ class QFieldAppAuthRequestHandler : public QObject, public QgsCredentials, publi }; QList mRealms; + bool mBrowserAuthenticationOngoing = false; }; #endif // QFIELDAPPAUTHREQUESTHANDLER_H diff --git a/src/qml/qgismobileapp.qml b/src/qml/qgismobileapp.qml index 0f767f825b..5715a17b9c 100644 --- a/src/qml/qgismobileapp.qml +++ b/src/qml/qgismobileapp.qml @@ -3342,6 +3342,11 @@ ApplicationWindow { } function onLoadProjectTriggered(path, name) { + messageLogModel.suppress({ + "WFS": [""], + "WMS": [""], + "PostGIS": ["fe_sendauth: no password supplied"] + }); qfieldLocalDataPickerScreen.visible = false; qfieldLocalDataPickerScreen.focus = false; welcomeScreen.visible = false; @@ -3360,6 +3365,17 @@ ApplicationWindow { function onLoadProjectEnded(path, name) { mapCanvasMap.unfreeze('projectload'); busyOverlay.state = "hidden"; + dashBoard.layerTree.unfreeze(true); + if (qfieldAuthRequestHandler.hasPendingAuthRequest) { + qfieldAuthRequestHandler.handleLayerLogins(); + } else { + // project in need of handling layer credentials + messageLogModel.unsuppress({ + "WFS": [], + "WMS": [], + "PostGIS": [] + }); + } projectInfo.filePath = path; stateMachine.state = projectInfo.stateMode; platformUtilities.setHandleVolumeKeys(qfieldSettings.digitizingVolumeKeys && stateMachine.state != 'browse'); @@ -3370,7 +3386,10 @@ ApplicationWindow { activeLayer = defaultActiveLayer; } } - dashBoard.activeLayer = activeLayer; + if (!qfieldAuthRequestHandler.hasPendingAuthRequest) { + // only set active layer when not handling layer credentials + dashBoard.activeLayer = activeLayer; + } drawingTemplateModel.projectFilePath = path; mapCanvasBackground.color = mapCanvas.mapSettings.backgroundColor; const titleDecorationConfiguration = projectInfo.getTitleDecorationConfiguration(); @@ -3447,7 +3466,7 @@ ApplicationWindow { projectInfo.hasInsertRights = true; projectInfo.hasEditRights = true; } - if (stateMachine.state === "digitize") { + if (stateMachine.state === "digitize" && !qfieldAuthRequestHandler.hasPendingAuthRequest) { dashBoard.ensureEditableLayerSelected(); } var distanceString = iface.readProjectEntry("Measurement", "/DistanceUnits", ""); @@ -3536,29 +3555,6 @@ ApplicationWindow { Item { id: layerLogin - Connections { - target: iface - function onLoadProjectTriggered(path) { - messageLogModel.suppress({ - "WFS": [""], - "WMS": [""], - "PostGIS": ["fe_sendauth: no password supplied"] - }); - } - - function onLoadProjectEnded() { - dashBoard.layerTree.unfreeze(true); - if (!qfieldAuthRequestHandler.handleLayerLogins()) { - //project loaded without more layer handling needed - messageLogModel.unsuppress({ - "WFS": [], - "WMS": [], - "PostGIS": [] - }); - } - } - } - Connections { target: qfieldAuthRequestHandler