Handle the fact that the user might cancel the password dialog

Add a new state of the account in which the credidentials are invalid,
but we are still trying to get the user enter his password.

Make sure that fetched() is ALWAYS emitted after we call fetch on the
credidentials, so we can know that the user pressed cancel. In that
case, go in the SignedOut state.

Fixes #1353
This commit is contained in:
Olivier Goffart 2014-01-28 11:06:40 +01:00
parent f408593d27
commit e31000d759
9 changed files with 44 additions and 45 deletions

View file

@ -238,9 +238,8 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
_password = pwd; _password = pwd;
_ready = true; _ready = true;
persist(account); persist(account);
Q_EMIT fetched();
break;
} }
emit fetched();
} }
qDebug() << "Error while reading password" << job->errorString(); qDebug() << "Error while reading password" << job->errorString();
} }

View file

@ -67,7 +67,8 @@ class Account : public QObject {
public: public:
enum State { Disconnected = 0, /// no network connection enum State { Disconnected = 0, /// no network connection
Connected, /// account is online Connected, /// account is online
SignedOut /// Disconnected + credential token has been discarded SignedOut, /// Disconnected + credential token has been discarded
InvalidCredidential /// The credidential are invalids and we are asking for them to the user
}; };
static QString davPath() { return "remote.php/webdav/"; } static QString davPath() { return "remote.php/webdav/"; }

View file

@ -210,14 +210,20 @@ void Application::slotCheckConnection()
Account *account = AccountManager::instance()->account(); Account *account = AccountManager::instance()->account();
if( account ) { if( account ) {
if (account->state() == Account::InvalidCredidential
|| account->state() == Account::SignedOut) {
//Do not try to connect if we are logged out
return;
}
AbstractCredentials* credentials(account->credentials()); AbstractCredentials* credentials(account->credentials());
if (! credentials->ready()) { if (! credentials->ready()) {
connect( credentials, SIGNAL(fetched()), connect( credentials, SIGNAL(fetched()),
this, SLOT(slotCredentialsFetched())); this, SLOT(slotCredentialsFetched()), Qt::UniqueConnection);
credentials->fetch(account); credentials->fetch(account);
} else { } else {
runValidator(); slotCredentialsFetched();
} }
} else { } else {
// let gui open the setup wizard // let gui open the setup wizard
@ -228,14 +234,21 @@ void Application::slotCheckConnection()
void Application::slotCredentialsFetched() void Application::slotCredentialsFetched()
{ {
Account *account = AccountManager::instance()->account(); Account *account = AccountManager::instance()->account();
disconnect(account->credentials(), SIGNAL(fetched()), Q_ASSERT(account);
this, SLOT(slotCredentialsFetched())); disconnect(account->credentials(), SIGNAL(fetched()), this, SLOT(slotCredentialsFetched()));
runValidator(); if (!account->credentials()->ready()) {
// User canceled the connection or did not give a password
account->setState(Account::SignedOut);
return;
}
if (account->state() == Account::InvalidCredidential) {
// Then we ask again for the credidentials if they are wrong again
account->setState(Account::Disconnected);
} }
void Application::runValidator() if (_conValidator)
{ _conValidator->deleteLater();
_conValidator = new ConnectionValidator(AccountManager::instance()->account()); _conValidator = new ConnectionValidator(account);
connect( _conValidator, SIGNAL(connectionResult(ConnectionValidator::Status)), connect( _conValidator, SIGNAL(connectionResult(ConnectionValidator::Status)),
this, SLOT(slotConnectionValidatorResult(ConnectionValidator::Status)) ); this, SLOT(slotConnectionValidatorResult(ConnectionValidator::Status)) );
_conValidator->checkConnection(); _conValidator->checkConnection();

View file

@ -73,20 +73,19 @@ protected slots:
void slotConnectionValidatorResult(ConnectionValidator::Status); void slotConnectionValidatorResult(ConnectionValidator::Status);
void slotStartUpdateDetector(); void slotStartUpdateDetector();
void slotUseMonoIconsChanged( bool ); void slotUseMonoIconsChanged( bool );
void slotCredentialsFetched();
void slotLogin(); void slotLogin();
void slotLogout(); void slotLogout();
void slotCleanup(); void slotCleanup();
void slotAccountChanged(Account *newAccount, Account *oldAccount); void slotAccountChanged(Account *newAccount, Account *oldAccount);
void slotCredentialsFetched();
private: private:
void setHelp(); void setHelp();
void runValidator();
QPointer<ownCloudGui> _gui; QPointer<ownCloudGui> _gui;
QPointer<SocketApi> _socketApi; QPointer<SocketApi> _socketApi;
ConnectionValidator *_conValidator; QPointer<ConnectionValidator> _conValidator;
Theme *_theme; Theme *_theme;

View file

@ -129,7 +129,6 @@ void ConnectionValidator::slotCheckAuthentication()
// simply GET the webdav root, will fail if credentials are wrong. // simply GET the webdav root, will fail if credentials are wrong.
// continue in slotAuthCheck here :-) // continue in slotAuthCheck here :-)
PropfindJob *job = new PropfindJob(_account, "/", this); PropfindJob *job = new PropfindJob(_account, "/", this);
job->setIgnoreCredentialFailure(true);
job->setProperties(QList<QByteArray>() << "getlastmodified"); job->setProperties(QList<QByteArray>() << "getlastmodified");
connect(job, SIGNAL(result(QVariantMap)), SLOT(slotAuthSuccess())); connect(job, SIGNAL(result(QVariantMap)), SLOT(slotAuthSuccess()));
connect(job, SIGNAL(networkError(QNetworkReply*)), SLOT(slotAuthFailed(QNetworkReply*))); connect(job, SIGNAL(networkError(QNetworkReply*)), SLOT(slotAuthFailed(QNetworkReply*)));

View file

@ -25,6 +25,7 @@
#include <QTimer> #include <QTimer>
#include <QMutex> #include <QMutex>
#include <QDebug> #include <QDebug>
#include <QCoreApplication>
#include "json.h" #include "json.h"
@ -89,17 +90,9 @@ void AbstractNetworkJob::setPath(const QString &path)
_path = path; _path = path;
} }
void AbstractNetworkJob::slotError(QNetworkReply::NetworkError)
{
qDebug() << metaObject()->className() << "Error:" << _reply->errorString();
emit networkError(_reply);
}
void AbstractNetworkJob::setupConnections(QNetworkReply *reply) void AbstractNetworkJob::setupConnections(QNetworkReply *reply)
{ {
connect(reply, SIGNAL(finished()), SLOT(slotFinished())); connect(reply, SIGNAL(finished()), SLOT(slotFinished()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));
} }
QNetworkReply* AbstractNetworkJob::davRequest(const QByteArray &verb, const QString &relPath, QNetworkReply* AbstractNetworkJob::davRequest(const QByteArray &verb, const QString &relPath,
@ -137,25 +130,21 @@ void AbstractNetworkJob::slotFinished()
{ {
if( _reply->error() != QNetworkReply::NoError ) { if( _reply->error() != QNetworkReply::NoError ) {
qDebug() << Q_FUNC_INFO << _reply->error() << _reply->errorString(); qDebug() << Q_FUNC_INFO << _reply->error() << _reply->errorString();
emit networkError(_reply);
} }
static QMutex mutex;
AbstractCredentials *creds = _account->credentials();
if (creds->stillValid(_reply) || _ignoreCredentialFailure) {
finished(); finished();
} else { AbstractCredentials *creds = _account->credentials();
// If other jobs that still were created from before if (!creds->stillValid(_reply) &&! _ignoreCredentialFailure
// the account was put offline by the code below, && _account->state() != Account::InvalidCredidential) {
// we do want them to fail silently while we // invalidate & forget token/password
// query the user _account->credentials()->invalidateToken(_account);
if (mutex.tryLock()) {
Account *a = account(); _account->setState(Account::InvalidCredidential);
bool fetched = creds->fetchFromUser(a);
if (fetched) { // but try to re-sign in.
a->setState(Account::Connected); connect( creds, SIGNAL(fetched()),
} qApp, SLOT(slotCredentialsFetched()), Qt::UniqueConnection);
mutex.unlock(); creds->fetch(_account); // this triggers Application::runValidator when the credidentials are fetched
}
} }
deleteLater(); deleteLater();
} }

View file

@ -73,7 +73,6 @@ protected:
private slots: private slots:
void slotFinished(); void slotFinished();
void slotError(QNetworkReply::NetworkError);
virtual void slotTimeout() {} virtual void slotTimeout() {}
private: private:

View file

@ -86,7 +86,6 @@ void OwncloudSetupWizard::startWizard()
account = new Account; account = new Account;
account->setCredentials(CredentialsFactory::create("dummy")); account->setCredentials(CredentialsFactory::create("dummy"));
} else { } else {
account->credentials()->fetch(account);
_ocWizard->setConfigExists(true); _ocWizard->setConfigExists(true);
} }
account->setSslErrorHandler(new SslDialogErrorHandler); account->setSslErrorHandler(new SslDialogErrorHandler);
@ -450,7 +449,7 @@ void DetermineAuthTypeJob::start()
void DetermineAuthTypeJob::finished() void DetermineAuthTypeJob::finished()
{ {
QUrl redirection = reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); QUrl redirection = reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
qDebug() << redirection.toString(); qDebug() << Q_FUNC_INFO << redirection.toString();
if (_redirects >= maxRedirects()) { if (_redirects >= maxRedirects()) {
redirection.clear(); redirection.clear();
} }

View file

@ -64,7 +64,8 @@ void QuotaInfo::slotRequestFailed()
void QuotaInfo::slotCheckQuota() void QuotaInfo::slotCheckQuota()
{ {
if (!_account.isNull() && _account->credentials() && _account->credentials()->ready()) { if (!_account.isNull() && _account->credentials() && _account->credentials()->ready()
&& _account->state() == Account::Connected) {
CheckQuotaJob *job = new CheckQuotaJob(_account, "/", this); CheckQuotaJob *job = new CheckQuotaJob(_account, "/", this);
connect(job, SIGNAL(quotaRetrieved(qint64,qint64)), SLOT(slotUpdateLastQuota(qint64,qint64))); connect(job, SIGNAL(quotaRetrieved(qint64,qint64)), SLOT(slotUpdateLastQuota(qint64,qint64)));
connect(job, SIGNAL(networkError(QNetworkReply*)), SLOT(slotRequestFailed())); connect(job, SIGNAL(networkError(QNetworkReply*)), SLOT(slotRequestFailed()));