diff options
author | Fabian Müller <fmueller@owncloud.com> | 2022-05-23 16:28:09 +0300 |
---|---|---|
committer | Hannah von Reth <vonreth@kde.org> | 2022-07-06 14:36:05 +0300 |
commit | 20b0d2c7d22fbbf03bcbf787f2f4db0e91e9545f (patch) | |
tree | 93ea0673d055744d0f5103f0f9cf6027754a038d /src | |
parent | 01ee11e448a10717d5c3db70a2aca420ddf95fd2 (diff) |
Use modal dialog to re-authorize OAuth2 accounts
This replaces the "Open browser" button within the account settings.
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/gui/accountsettings.cpp | 52 | ||||
-rw-r--r-- | src/gui/accountsettings.h | 3 | ||||
-rw-r--r-- | src/gui/accountsettings.ui | 11 | ||||
-rw-r--r-- | src/gui/askforoauthlogindialog.cpp | 54 | ||||
-rw-r--r-- | src/gui/askforoauthlogindialog.h | 42 | ||||
-rw-r--r-- | src/gui/askforoauthlogindialog.ui | 106 | ||||
-rw-r--r-- | src/gui/creds/httpcredentialsgui.cpp | 15 | ||||
-rw-r--r-- | src/gui/creds/httpcredentialsgui.h | 3 |
9 files changed, 264 insertions, 24 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 733e0401f..9444cc7ef 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -24,6 +24,7 @@ set(client_UI_SRCS proxyauthdialog.ui notificationwidget.ui logbrowser.ui + askforoauthlogindialog.ui ) set(client_SRCS @@ -79,6 +80,7 @@ set(client_SRCS translations.cpp creds/httpcredentialsgui.cpp updateurldialog.cpp + askforoauthlogindialog.cpp models/activitylistmodel.cpp models/expandingheaderview.cpp diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index 2fd40b121..9659bf0ab 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -39,22 +39,24 @@ #include <math.h> +#include <QAction> +#include <QClipboard> #include <QDesktopServices> #include <QDir> +#include <QIcon> +#include <QKeySequence> #include <QListWidgetItem> #include <QMessageBox> -#include <QAction> -#include <QVBoxLayout> +#include <QToolTip> #include <QTreeView> -#include <QKeySequence> -#include <QIcon> +#include <QVBoxLayout> #include <QVariant> -#include <QToolTip> -#include <qstringlistmodel.h> #include <qpropertyanimation.h> +#include <qstringlistmodel.h> #include "account.h" #include "askexperimentalvirtualfilesfeaturemessagebox.h" +#include "askforoauthlogindialog.h" namespace OCC { @@ -186,11 +188,6 @@ AccountSettings::AccountSettings(AccountStatePtr accountState, QWidget *parent) connect(&_quotaInfo, &QuotaInfo::quotaUpdated, this, &AccountSettings::slotUpdateQuota); - - ui->openBrowserButton->setVisible(false); - connect(ui->openBrowserButton, &QToolButton::clicked, this, [this]{ - qobject_cast<HttpCredentialsGui *>(_accountState->account()->credentials())->openBrowser(); - }); } @@ -797,7 +794,9 @@ void AccountSettings::slotAccountStateChanged() errors << tr("The server version %1 is unsupported! Proceed at your own risk.").arg(account->capabilities().status().versionString()); } showConnectionLabel(tr("Connected to %1.").arg(serverWithUser), errors); - ui->openBrowserButton->setVisible(false); + if (_askForOAuthLoginDialog != nullptr) { + _askForOAuthLoginDialog->accept(); + } break; } case AccountState::ServiceUnavailable: @@ -812,10 +811,31 @@ void AccountSettings::slotAccountStateChanged() case AccountState::AskingCredentials: { auto cred = qobject_cast<HttpCredentialsGui *>(account->credentials()); if (cred && cred->isUsingOAuth()) { - connect(cred, &HttpCredentialsGui::authorisationLinkChanged, - this, &AccountSettings::slotAccountStateChanged, Qt::UniqueConnection); - showConnectionLabel(tr("Obtaining authorization from the browser.")); - ui->openBrowserButton->setVisible(true); + if (_askForOAuthLoginDialog != nullptr) { + qCDebug(lcAccountSettings) << "ask for OAuth login dialog is shown already"; + return; + } + + qCDebug(lcAccountSettings) << "showing modal dialog asking user to log in again via OAuth2"; + + _askForOAuthLoginDialog = new AskForOAuthLoginDialog(_accountState->account(), this); + + // make sure to clean up the memory and to null the QPointer once finished + _askForOAuthLoginDialog->setAttribute(Qt::WA_DeleteOnClose); + + connect( + cred, &HttpCredentialsGui::authorisationLinkChanged, + this, &AccountSettings::slotAccountStateChanged, + Qt::UniqueConnection); + + connect(_askForOAuthLoginDialog, &AskForOAuthLoginDialog::rejected, this, [this]() { + // if a user dismisses the dialog, we have no choice but signing them out + _accountState->signOutByUi(); + }); + + showConnectionLabel(tr("Reauthorization required.")); + + _askForOAuthLoginDialog->show(); } else { showConnectionLabel(tr("Connecting to %1...").arg(serverWithUser)); } diff --git a/src/gui/accountsettings.h b/src/gui/accountsettings.h index 819d7367b..e23e5f2dd 100644 --- a/src/gui/accountsettings.h +++ b/src/gui/accountsettings.h @@ -104,6 +104,9 @@ private: QuotaInfo _quotaInfo; QAction *_toggleSignInOutAction; QAction *_addAccountAction; + + // needed to make sure we show only one dialog at a time + QPointer<QDialog> _askForOAuthLoginDialog = nullptr; }; } // namespace OCC diff --git a/src/gui/accountsettings.ui b/src/gui/accountsettings.ui index b9904a3f2..9e88c37dd 100644 --- a/src/gui/accountsettings.ui +++ b/src/gui/accountsettings.ui @@ -40,13 +40,6 @@ </widget> </item> <item> - <widget class="QToolButton" name="openBrowserButton"> - <property name="text"> - <string>Re-open Browser</string> - </property> - </widget> - </item> - <item> <widget class="QToolButton" name="_accountToolbox"> <property name="text"> <string>...</string> @@ -280,6 +273,8 @@ </item> </layout> </widget> - <resources/> + <resources> + <include location="../../client.qrc"/> + </resources> <connections/> </ui> diff --git a/src/gui/askforoauthlogindialog.cpp b/src/gui/askforoauthlogindialog.cpp new file mode 100644 index 000000000..1eaff71a3 --- /dev/null +++ b/src/gui/askforoauthlogindialog.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) Fabian Müller <fmueller@owncloud.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "askforoauthlogindialog.h" +#include "application.h" +#include "creds/httpcredentialsgui.h" +#include "theme.h" +#include "ui_askforoauthlogindialog.h" + +#include <QClipboard> + +namespace OCC { + +AskForOAuthLoginDialog::AskForOAuthLoginDialog(AccountPtr accountPtr, QWidget *parent) + : QDialog(parent) + , _ui(new ::Ui::AskForOAuthLoginDialog) +{ + _ui->setupUi(this); + + _ui->label->setText(tr("The account %1 has been logged out by the server.\n\nPlease use your browser to log into %2.").arg(accountPtr->displayName(), Theme::instance()->appNameGUI())); + _ui->iconLabel->setPixmap(Theme::instance()->applicationIcon().pixmap(64, 64)); + + setModal(true); + + setFixedSize(this->sizeHint()); + + connect(_ui->openBrowserButton, &QPushButton::clicked, this, [this, accountPtr]() { + qobject_cast<HttpCredentialsGui *>(accountPtr->credentials())->openBrowser(); + _ui->openBrowserButton->setText(tr("Reopen browser")); + }); + connect(_ui->copyUrlToClipboardButton, &QPushButton::clicked, this, [accountPtr]() { + // TODO: use authorisationLinkAsync + auto link = qobject_cast<HttpCredentialsGui *>(accountPtr->credentials())->authorisationLink().toString(); + ocApp()->clipboard()->setText(link); + }); +} + +AskForOAuthLoginDialog::~AskForOAuthLoginDialog() +{ + delete _ui; +} + +} // OCC diff --git a/src/gui/askforoauthlogindialog.h b/src/gui/askforoauthlogindialog.h new file mode 100644 index 000000000..4b63c180c --- /dev/null +++ b/src/gui/askforoauthlogindialog.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) Fabian Müller <fmueller@owncloud.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#pragma once + +#include "account.h" +#include <QDialog> + +namespace Ui { +class AskForOAuthLoginDialog; +} + +namespace OCC { + +class AskForOAuthLoginDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AskForOAuthLoginDialog(AccountPtr accountPtr, QWidget *parent = nullptr); + ~AskForOAuthLoginDialog() override; + +Q_SIGNALS: + void openBrowserButtonClicked(); + void copyUrlToClipboardButtonClicked(); + +private: + ::Ui::AskForOAuthLoginDialog *_ui; +}; + +} // OCC diff --git a/src/gui/askforoauthlogindialog.ui b/src/gui/askforoauthlogindialog.ui new file mode 100644 index 000000000..9d83c0970 --- /dev/null +++ b/src/gui/askforoauthlogindialog.ui @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AskForOAuthLoginDialog</class> + <widget class="QDialog" name="AskForOAuthLoginDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>435</width> + <height>135</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Login required</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" stretch="1,0"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="iconLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string notr="true">icon (placeholder)</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="minimumSize"> + <size> + <width>300</width> + <height>50</height> + </size> + </property> + <property name="text"> + <string notr="true">The account has been logged out [...] <placeholder></string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="openBrowserButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Open browser</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="copyUrlToClipboardButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Copy URL to clipboard</string> + </property> + <property name="icon"> + <iconset resource="../resources/client.qrc"> + <normaloff>:/client/resources/light/clipboard.svg</normaloff>:/client/resources/light/clipboard.svg</iconset> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources> + <include location="../resources/client.qrc"/> + </resources> + <connections/> +</ui> diff --git a/src/gui/creds/httpcredentialsgui.cpp b/src/gui/creds/httpcredentialsgui.cpp index 136339a27..601178f01 100644 --- a/src/gui/creds/httpcredentialsgui.cpp +++ b/src/gui/creds/httpcredentialsgui.cpp @@ -166,4 +166,19 @@ QString HttpCredentialsGui::requestAppPasswordText(const Account *account) return tr("<a href=\"%1\">Click here</a> to request an app password from the web interface.") .arg(Utility::concatUrlPath(baseUrl, QStringLiteral("/index.php/settings/personal?sectionid=security#apppasswords")).toString()); } + +QUrl HttpCredentialsGui::authorisationLink() const +{ + OC_ASSERT(isUsingOAuth()); + if (isUsingOAuth()) { + if (_asyncAuth) { + return _asyncAuth->authorisationLink(); + } else { + qCWarning(lcHttpCredentialsGui) << "There is no authentication job running, did the previous attempt fail?"; + return {}; + } + } + return {}; +} + } // namespace OCC diff --git a/src/gui/creds/httpcredentialsgui.h b/src/gui/creds/httpcredentialsgui.h index 2332735f3..d567ac8a3 100644 --- a/src/gui/creds/httpcredentialsgui.h +++ b/src/gui/creds/httpcredentialsgui.h @@ -45,6 +45,9 @@ public: } void openBrowser(); + + QUrl authorisationLink() const; + /** * This will query the server and either uses OAuth via _asyncAuth->start() * or call showDialog to ask the password |