From ecebd90dcbdb04d1d77d76c0ac4985b3fb362e1f Mon Sep 17 00:00:00 2001 From: Scharel Clemens Date: Tue, 14 Jan 2020 17:04:09 +0100 Subject: [PATCH] Further implemented Flow v2 Login --- qml/pages/LoginDialog.qml | 9 ++++- qml/pages/LoginWebView.qml | 21 ++++------- src/notesapi.cpp | 50 ++++++++++++++++++++++++-- src/notesapi.h | 16 +++++++++ translations/harbour-nextcloudnotes.ts | 38 ++++++++++---------- 5 files changed, 96 insertions(+), 38 deletions(-) diff --git a/qml/pages/LoginDialog.qml b/qml/pages/LoginDialog.qml index 8bdada8..d617c65 100644 --- a/qml/pages/LoginDialog.qml +++ b/qml/pages/LoginDialog.qml @@ -38,6 +38,10 @@ Dialog { notesApi.host = value("server", "", String) } + Timer { + id: loginPollTimer + } + SilicaFlickable { anchors.fill: parent contentHeight: column.height + Theme.paddingLarge @@ -118,7 +122,10 @@ Dialog { id: loginButton anchors.horizontalCenter: parent.horizontalCenter text: qsTr("Login") - onClicked: pageStack.push(Qt.resolvedUrl("LoginWebView.qml"), { server: serverField.text }) + onClicked: { + + //pageStack.push(Qt.resolvedUrl("LoginWebView.qml"), { loginUrl: serverField.text }) + } } SectionHeader { diff --git a/qml/pages/LoginWebView.qml b/qml/pages/LoginWebView.qml index fb80298..b8fe580 100644 --- a/qml/pages/LoginWebView.qml +++ b/qml/pages/LoginWebView.qml @@ -3,8 +3,7 @@ import Sailfish.Silica 1.0 Page { id: loginWebView - property string server - property url ncurl: (account.allowUnecrypted ? "http://" : "https://") + server + "/index.php/login/flow" + property url loginUrl Component.onCompleted: { var req = new XMLHttpRequest() @@ -22,28 +21,20 @@ Page { } SilicaWebView { - id: ncFlowWebView + id: ncFlow2WebView anchors.fill: parent - //url: ncurl - //experimental.userAgent: "SailfishBrowser 1 - Sailfish" //"Mozilla/5.0 (U; Linux; Maemo; Jolla; Sailfish; like Android 4.3) " + "AppleWebKit/" + wkversion + " (KHTML, like Gecko) WebPirate/" + version + " like Mobile Safari/" + wkversion + " (compatible)" - onNavigationRequested: { - console.log(url) - if (url.toString().indexOf("nc://login") === 0) { - var credentials = url.split("/", 1) - console.log(credentials) - } - } + url: loginUrl header: PageHeader { - title: ncFlowWebView.title - description: loginWebView.ncurl + title: ncFlow2WebView.title + description: url BusyIndicator { anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.rightMargin: Theme.horizontalPageMargin size: BusyIndicatorSize.Medium - running: ncFlowWebView.loading + running: ncFlow2WebView.loading } } } diff --git a/src/notesapi.cpp b/src/notesapi.cpp index 7dc462c..82ed2ab 100644 --- a/src/notesapi.cpp +++ b/src/notesapi.cpp @@ -148,13 +148,26 @@ bool NotesApi::ready() const { bool NotesApi::busy() const { bool busy = false; - for (int i = 0; i < m_replies.size(); ++i) { - busy |= m_replies[i]->isRunning(); + QVector replies; + replies << m_replies << m_status_replies << m_login_replies; + for (int i = 0; i < replies.size(); ++i) { + busy |= replies[i]->isRunning(); } return busy; } void NotesApi::getStatus() { + QUrl url = m_url; + url.setPath("/index.php/login/v2"); + if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { + qDebug() << "POST" << url.toDisplayString(); + m_request.setUrl(url); + m_login_replies << m_manager.post(m_request, QByteArray()); + emit busyChanged(busy()); + } +} + +void NotesApi::initiateFlowV2Login() { QUrl url = m_url; url.setPath("/status.php"); if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { @@ -266,6 +279,11 @@ void NotesApi::replyFinished(QNetworkReply *reply) { emit error(NoError); QByteArray data = reply->readAll(); QJsonDocument json = QJsonDocument::fromJson(data); + if (m_login_replies.contains(reply)) { + if (json.isObject()) { + updateLogin(json.object()); + } + } if (m_status_replies.contains(reply)) { if (json.isObject()) { updateStatus(json.object()); @@ -285,8 +303,9 @@ void NotesApi::replyFinished(QNetworkReply *reply) { emit error(AuthenticationError); else emit error(CommunicationError); - m_replies.removeAll(reply); + m_login_replies.removeAll(reply); m_status_replies.removeAll(reply); + m_replies.removeAll(reply); reply->deleteLater(); emit busyChanged(busy()); } @@ -353,6 +372,31 @@ void NotesApi::updateStatus(const QJsonObject &status) { } } +void NotesApi::updateLogin(const QJsonObject &login) { + QUrl url; + QString token; + if (!login.isEmpty()) { + url = login.value("login").toString(); + if (m_login_loginUrl != url && url.isValid()) { + m_login_loginUrl = url; + emit loginLoginUrlChanged(m_login_loginUrl); + } + QJsonObject poll = login.value("poll").toObject(); + if (!poll.isEmpty()) { + url = poll.value("endpoint").toString() ; + if (m_login_pollUrl != url && urlValid()) { + m_login_pollUrl = url; + emit loginPollUrlChanged(m_login_pollUrl); + } + token = poll.value("token").toString(); + if (m_login_pollToken != token) { + m_login_pollToken = token; + emit loginPollTokenChanged(m_login_pollToken); + } + } + } +} + const QString NotesApi::errorMessage(int error) const { QString message; switch (error) { diff --git a/src/notesapi.h b/src/notesapi.h index 39a8190..aed730c 100644 --- a/src/notesapi.h +++ b/src/notesapi.h @@ -83,8 +83,15 @@ public: QString statusProductName() const { return m_status_productname; } Q_PROPERTY(bool statusExtendedSupport READ statusExtendedSupport NOTIFY statusExtendedSupportChanged) bool statusExtendedSupport() const { return m_status_extendedSupport; } + Q_PROPERTY(QUrl loginPollUrl READ loginPollUrl NOTIFY loginPollUrlChanged) + QUrl loginPollUrl() const { return m_login_pollUrl; } + Q_PROPERTY(QString loginPollToken READ loginPollToken NOTIFY loginPollTokenChanged) + QString loginPollToken() const { return m_login_pollToken; } + Q_PROPERTY(QUrl loginLoginUrl READ loginLoginUrl NOTIFY loginLoginUrlChanged) + QUrl loginLoginUrl() const { return m_login_loginUrl; } Q_INVOKABLE void getStatus(); + Q_INVOKABLE void initiateFlowV2Login(); Q_INVOKABLE void getAllNotes(QStringList excludeFields = QStringList()); Q_INVOKABLE void getNote(double noteId, QStringList excludeFields = QStringList()); Q_INVOKABLE void createNote(QVariantMap fields = QVariantMap()); @@ -126,6 +133,9 @@ signals: void statusEditionChanged(QString edition); void statusProductNameChanged(QString productName); void statusExtendedSupportChanged(bool extendedSupport); + void loginPollUrlChanged(QUrl url); + void loginPollTokenChanged(QString token); + void loginLoginUrlChanged(QUrl url); void error(int error); public slots: @@ -159,6 +169,12 @@ private: QString m_status_edition; QString m_status_productname; bool m_status_extendedSupport; + + void updateLogin(const QJsonObject &login); + QVector m_login_replies; + QUrl m_login_pollUrl; + QString m_login_pollToken; + QUrl m_login_loginUrl; }; #endif // NOTESAPI_H diff --git a/translations/harbour-nextcloudnotes.ts b/translations/harbour-nextcloudnotes.ts index ebcdde5..2d58b6c 100644 --- a/translations/harbour-nextcloudnotes.ts +++ b/translations/harbour-nextcloudnotes.ts @@ -125,58 +125,58 @@ LoginDialog - - + + Login - + Save - + Account name - + Nextcloud server - + Username - + Password - + Security - + <strong>CAUTION: Your password will be saved without any encryption on the device!</strong><br>Please consider creating a dedicated app password! Open your Nextcloud in a browser and go to <i>Settings</i> → <i>Security</i>. - + Do not check certificates - + Enable this option to allow selfsigned certificates - + Allow unencrypted connections @@ -263,37 +263,37 @@ NotesApi - + No network connection available - + Failed to communicate with the Nextcloud server - + An error happened while reading from the local storage - + An error happened while writing to the local storage - + An error occured while establishing an encrypted connection - + Could not authenticate to the Nextcloud instance - + Unknown error