Skip to content

Commit 4410bf9

Browse files
committed
Move OAuth dialog to HttpCredentialsGui
This fixes a bug where askFromUser did not display a ui and the client got stuck in reconnecting
1 parent 3c1420d commit 4410bf9

File tree

4 files changed

+56
-91
lines changed

4 files changed

+56
-91
lines changed

src/gui/accountsettings.cpp

+1-65
Original file line numberDiff line numberDiff line change
@@ -682,27 +682,19 @@ void AccountSettings::slotAccountStateChanged()
682682
_model->slotUpdateFolderState(folder);
683683
}
684684

685-
auto acceptOAuthLogin = [this]() {
686-
if (_askForOAuthLoginDialog != nullptr) {
687-
_askForOAuthLoginDialog->accept();
688-
}
689-
};
690-
691685
const QString server = QStringLiteral("<a href=\"%1\">%1</a>")
692686
.arg(Utility::escape(safeUrl.toString()));
693687

694688
switch (state) {
695689
case AccountState::PausedDueToMetered:
696690
showConnectionLabel(tr("Sync to %1 is paused due to metered internet connection.").arg(server));
697-
acceptOAuthLogin();
698691
break;
699692
case AccountState::Connected: {
700693
QStringList errors;
701694
if (account->serverSupportLevel() != Account::ServerSupportLevel::Supported) {
702695
errors << tr("The server version %1 is unsupported! Proceed at your own risk.").arg(account->capabilities().status().versionString());
703696
}
704697
showConnectionLabel(tr("Connected to %1.").arg(server), errors);
705-
acceptOAuthLogin();
706698
break;
707699
}
708700
case AccountState::ServiceUnavailable:
@@ -715,63 +707,7 @@ void AccountSettings::slotAccountStateChanged()
715707
showConnectionLabel(tr("Signed out from %1.").arg(server));
716708
break;
717709
case AccountState::AskingCredentials: {
718-
auto cred = qobject_cast<HttpCredentialsGui *>(account->credentials());
719-
if (cred && cred->isUsingOAuth()) {
720-
if (_askForOAuthLoginDialog != nullptr) {
721-
qCDebug(lcAccountSettings) << "ask for OAuth login dialog is shown already";
722-
return;
723-
}
724-
725-
qCDebug(lcAccountSettings) << "showing modal dialog asking user to log in again via OAuth2";
726-
727-
_askForOAuthLoginDialog = new LoginRequiredDialog(LoginRequiredDialog::Mode::OAuth, ocApp()->gui()->settingsDialog());
728-
729-
// make sure it's cleaned up since it's not owned by the account settings (also prevents memory leaks)
730-
_askForOAuthLoginDialog->setAttribute(Qt::WA_DeleteOnClose);
731-
732-
_askForOAuthLoginDialog->setTopLabelText(tr("The account %1 is currently logged out.\n\nPlease authenticate using your browser.").arg(account->displayName()));
733-
734-
auto *contentWidget = qobject_cast<OAuthLoginWidget *>(_askForOAuthLoginDialog->contentWidget());
735-
736-
connect(cred, &HttpCredentialsGui::authorisationLinkChanged, contentWidget,
737-
[cred, contentWidget] { contentWidget->setUrl(cred->authorisationLink()); });
738-
739-
connect(contentWidget, &OAuthLoginWidget::copyUrlToClipboardButtonClicked, _askForOAuthLoginDialog, [](const QUrl &url) {
740-
// TODO: use authorisationLinkAsync
741-
qApp->clipboard()->setText(url.toString());
742-
});
743-
744-
connect(contentWidget, &OAuthLoginWidget::openBrowserButtonClicked, cred, &HttpCredentialsGui::openBrowser);
745-
746-
connect(_askForOAuthLoginDialog, &LoginRequiredDialog::rejected, this, [this]() {
747-
// if a user dismisses the dialog, we have no choice but signing them out
748-
_accountState->signOutByUi();
749-
});
750-
751-
connect(contentWidget, &OAuthLoginWidget::retryButtonClicked, _askForOAuthLoginDialog, [contentWidget, accountPtr = account]() {
752-
auto creds = qobject_cast<HttpCredentialsGui *>(accountPtr->credentials());
753-
creds->restartOAuth();
754-
contentWidget->hideRetryFrame();
755-
});
756-
757-
connect(cred, &HttpCredentialsGui::oAuthErrorOccurred, _askForOAuthLoginDialog, [loginDialog = _askForOAuthLoginDialog, contentWidget, cred]() {
758-
Q_ASSERT(!cred->ready());
759-
760-
ocApp()->gui()->raiseDialog(loginDialog);
761-
contentWidget->showRetryFrame();
762-
});
763-
764-
showConnectionLabel(tr("Reauthorization required."));
765-
766-
_askForOAuthLoginDialog->open();
767-
ocApp()->gui()->raiseDialog(_askForOAuthLoginDialog);
768-
769-
QTimer::singleShot(0, [contentWidget]() {
770-
contentWidget->setFocus(Qt::OtherFocusReason);
771-
});
772-
} else {
773-
showConnectionLabel(tr("Connecting to %1...").arg(server));
774-
}
710+
showConnectionLabel(tr("Updating credentials for %1...").arg(server));
775711
break;
776712
}
777713
case AccountState::Connecting:

src/gui/accountsettings.h

-3
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,6 @@ protected slots:
103103
AccountStatePtr _accountState;
104104
QAction *_toggleSignInOutAction;
105105
QAction *_toggleReconnect;
106-
107-
// needed to make sure we show only one dialog at a time
108-
QPointer<LoginRequiredDialog> _askForOAuthLoginDialog = nullptr;
109106
};
110107

111108
} // namespace OCC

src/gui/creds/httpcredentialsgui.cpp

+52-18
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@
1616
#include "creds/httpcredentialsgui.h"
1717
#include "account.h"
1818
#include "application.h"
19-
#include "basicloginwidget.h"
2019
#include "common/asserts.h"
21-
#include "loginrequireddialog.h"
20+
#include "gui/loginrequireddialog/basicloginwidget.h"
21+
#include "gui/loginrequireddialog/loginrequireddialog.h"
22+
#include "gui/loginrequireddialog/oauthloginwidget.h"
2223
#include "networkjobs.h"
2324
#include "settingsdialog.h"
2425
#include "theme.h"
2526

26-
#include <QBuffer>
27+
#include <QClipboard>
2728
#include <QDesktopServices>
28-
#include <QMessageBox>
29-
#include <QNetworkReply>
29+
#include <QGuiApplication>
3030
#include <QTimer>
3131

3232

@@ -42,21 +42,12 @@ void HttpCredentialsGui::openBrowser()
4242
_asyncAuth->openBrowser();
4343
} else {
4444
qCWarning(lcHttpCredentialsGui) << "There is no authentication job running, did the previous attempt fail?";
45-
askFromUserAsync();
45+
askFromUser();
4646
}
4747
}
4848
}
4949

5050
void HttpCredentialsGui::askFromUser()
51-
{
52-
// This function can be called from AccountState::slotInvalidCredentials,
53-
// which (indirectly, through HttpCredentials::invalidateToken) schedules
54-
// a cache wipe of the qnam. We can only execute a network job again once
55-
// the cache has been cleared, otherwise we'd interfere with the job.
56-
QTimer::singleShot(0, this, &HttpCredentialsGui::askFromUserAsync);
57-
}
58-
59-
void HttpCredentialsGui::askFromUserAsync()
6051
{
6152
if (isUsingOAuth()) {
6253
restartOAuth();
@@ -83,6 +74,11 @@ void HttpCredentialsGui::asyncAuthResult(OAuth::Result r, const QString &token,
8374
_asyncAuth.reset();
8475
switch (r) {
8576
case OAuth::NotSupported:
77+
if (_loginRequiredDialog) {
78+
_loginRequiredDialog->deleteLater();
79+
_loginRequiredDialog.clear();
80+
}
81+
// show basic auth dialog for historic reasons
8682
showDialog();
8783
return;
8884
case OAuth::ErrorInsecureUrl:
@@ -93,6 +89,9 @@ void HttpCredentialsGui::asyncAuthResult(OAuth::Result r, const QString &token,
9389
Q_EMIT oAuthErrorOccurred();
9490
return;
9591
case OAuth::LoggedIn:
92+
if (_loginRequiredDialog) {
93+
_loginRequiredDialog->accept();
94+
}
9695
break;
9796
}
9897

@@ -160,10 +159,45 @@ QUrl HttpCredentialsGui::authorisationLink() const
160159

161160
void HttpCredentialsGui::restartOAuth()
162161
{
162+
qCDebug(lcHttpCredentialsGui) << "showing modal dialog asking user to log in again via OAuth2";
163+
164+
if (!_loginRequiredDialog) {
165+
_loginRequiredDialog = new LoginRequiredDialog(LoginRequiredDialog::Mode::OAuth, ocApp()->gui()->settingsDialog());
166+
167+
// make sure it's cleaned up since it's not owned by the account settings (also prevents memory leaks)
168+
_loginRequiredDialog->setAttribute(Qt::WA_DeleteOnClose);
169+
170+
_loginRequiredDialog->setTopLabelText(
171+
tr("The account %1 is currently logged out.\n\nPlease authenticate using your browser.").arg(_account->displayName()));
172+
173+
auto *contentWidget = qobject_cast<OAuthLoginWidget *>(_loginRequiredDialog->contentWidget());
174+
connect(contentWidget, &OAuthLoginWidget::copyUrlToClipboardButtonClicked, _loginRequiredDialog, [](const QUrl &url) {
175+
// TODO: use authorisationLinkAsync
176+
qApp->clipboard()->setText(url.toString());
177+
});
178+
179+
connect(contentWidget, &OAuthLoginWidget::openBrowserButtonClicked, this, &HttpCredentialsGui::openBrowser);
180+
connect(_loginRequiredDialog, &LoginRequiredDialog::rejected, this, &HttpCredentials::requestLogout);
181+
182+
connect(contentWidget, &OAuthLoginWidget::retryButtonClicked, _loginRequiredDialog, [contentWidget, this]() {
183+
restartOAuth();
184+
contentWidget->hideRetryFrame();
185+
});
186+
187+
connect(this, &HttpCredentialsGui::oAuthErrorOccurred, _loginRequiredDialog, [contentWidget, this]() {
188+
Q_ASSERT(!ready());
189+
ocApp()->gui()->raiseDialog(_loginRequiredDialog);
190+
contentWidget->showRetryFrame();
191+
});
192+
193+
_loginRequiredDialog->open();
194+
ocApp()->gui()->raiseDialog(_loginRequiredDialog);
195+
}
196+
163197
_asyncAuth.reset(new AccountBasedOAuth(_account->sharedFromThis(), this));
164-
connect(_asyncAuth.data(), &OAuth::result,
165-
this, &HttpCredentialsGui::asyncAuthResult);
166-
connect(_asyncAuth.data(), &OAuth::authorisationLinkChanged, this, &HttpCredentialsGui::authorisationLinkChanged);
198+
connect(_asyncAuth.data(), &OAuth::result, this, &HttpCredentialsGui::asyncAuthResult);
199+
connect(_asyncAuth.data(), &OAuth::authorisationLinkChanged, this,
200+
[this] { qobject_cast<OAuthLoginWidget *>(_loginRequiredDialog->contentWidget())->setUrl(authorisationLink()); });
167201
_asyncAuth->startAuthentication();
168202
}
169203

src/gui/creds/httpcredentialsgui.h

+3-5
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
#pragma once
1717
#include "creds/httpcredentials.h"
1818
#include "creds/oauth.h"
19+
1920
#include <QPointer>
20-
#include <QTcpServer>
2121

2222
namespace OCC {
23+
class LoginRequiredDialog;
2324

2425
/**
2526
* @brief The HttpCredentialsGui class
@@ -62,16 +63,13 @@ class HttpCredentialsGui : public HttpCredentials
6263
private slots:
6364
void asyncAuthResult(OAuth::Result, const QString &accessToken, const QString &refreshToken);
6465
void showDialog();
65-
void askFromUserAsync();
6666

6767
signals:
68-
void authorisationLinkChanged();
69-
7068
void oAuthErrorOccurred();
7169

7270
private:
7371
QScopedPointer<AccountBasedOAuth, QScopedPointerObjectDeleteLater<AccountBasedOAuth>> _asyncAuth;
74-
QPointer<QWidget> _loginRequiredDialog;
72+
QPointer<LoginRequiredDialog> _loginRequiredDialog;
7573
};
7674

7775
} // namespace OCC

0 commit comments

Comments
 (0)