_sslTrusted(false)
{}
- QString queryPassword(bool *ok, const QString&) Q_DECL_OVERRIDE {
- if (ok) {
- *ok = true;
- }
- return ::queryPassword(user());
+ void askFromUser() Q_DECL_OVERRIDE {
+ _password = ::queryPassword(user());
+ _ready = true;
+ persist();
+ emit asked();
}
void setSSLTrusted( bool isTrusted ) {
#include "accountmanager.h"
#include "account.h"
#include "creds/abstractcredentials.h"
+#include "logger.h"
#include <QDebug>
#include <QSettings>
, _state(AccountState::Disconnected)
, _connectionStatus(ConnectionValidator::Undefined)
, _waitingForNewCredentials(false)
+ , _credentialsFetchMode(Interactive)
{
qRegisterMetaType<AccountState*>("AccountState*");
SLOT(slotInvalidCredentials()));
connect(account.data(), SIGNAL(credentialsFetched(AbstractCredentials*)),
SLOT(slotCredentialsFetched(AbstractCredentials*)));
+ connect(account.data(), SIGNAL(credentialsAsked(AbstractCredentials*)),
+ SLOT(slotCredentialsAsked(AbstractCredentials*)));
}
AccountState::~AccountState()
_connectionStatus = ConnectionValidator::Undefined;
_connectionErrors.clear();
} else if (oldState == SignedOut && _state == Disconnected) {
- checkConnectivity(AbstractCredentials::Interactive);
+ checkConnectivity(Interactive);
}
}
return isConnected() || _state == ServiceUnavailable;
}
-void AccountState::checkConnectivity(AbstractCredentials::FetchMode credentialsFetchMode)
+void AccountState::checkConnectivity(CredentialFetchMode credentialsFetchMode)
{
if (isSignedOut() || _waitingForNewCredentials) {
return;
qDebug() << "ConnectionValidator already running, ignoring";
return;
}
- ConnectionValidator * conValidator = new ConnectionValidator(account(), credentialsFetchMode);
+ _credentialsFetchMode = credentialsFetchMode;
+ ConnectionValidator * conValidator = new ConnectionValidator(account());
_connectionValidator = conValidator;
connect(conValidator, SIGNAL(connectionResult(ConnectionValidator::Status,QStringList)),
SLOT(slotConnectionValidatorResult(ConnectionValidator::Status,QStringList)));
}
void AccountState::slotCredentialsFetched(AbstractCredentials* credentials)
+{
+ if (!credentials->ready()) {
+ // No exiting credentials found in the keychain
+ if (_credentialsFetchMode == Interactive)
+ credentials->askFromUser();
+ else {
+ Logger::instance()->postOptionalGuiLog(tr("Reauthentication required"), tr("You need to re-login to continue using the account %1.").arg(_account->displayName()));
+ setState(SignedOut);
+ _waitingForNewCredentials = false;
+ }
+ return;
+ }
+
+ _waitingForNewCredentials = false;
+
+ // When new credentials become available we always want to restart the
+ // connection validation, even if it's currently running.
+ delete _connectionValidator;
+
+ checkConnectivity(_credentialsFetchMode);
+}
+
+void AccountState::slotCredentialsAsked(AbstractCredentials* credentials)
{
_waitingForNewCredentials = false;
// When new credentials become available we always want to restart the
// connection validation, even if it's currently running.
- if (_connectionValidator) {
- delete _connectionValidator;
- }
+ delete _connectionValidator;
- // If we made it this far, it means that we either fetched credentials
- // interactively, or that we already aborted for missing/invalid credentials.
- Q_ASSERT(credentials->ready());
- checkConnectivity(AbstractCredentials::Interactive);
+ checkConnectivity(_credentialsFetchMode);
}
std::unique_ptr<QSettings> AccountState::settings()
#include <QPointer>
#include "utility.h"
#include "connectionvalidator.h"
+#include "creds/abstractcredentials.h"
#include <memory>
class QSettings;
class AccountState;
class Account;
-class AbstractCredentials;
/**
* @brief Extra info about an ownCloud server account.
/// An error like invalid credentials where retrying won't help.
ConfigurationError
};
+ enum CredentialFetchMode { Interactive, NonInteractive };
/// The actual current connectivity status.
typedef ConnectionValidator::Status ConnectionStatus;
/// Triggers a ping to the server to update state and
/// connection status and errors.
- void checkConnectivity(AbstractCredentials::FetchMode credentialsFetchMode);
+ void checkConnectivity(CredentialFetchMode credentialsFetchMode);
/** Returns a new settings object for this account, already in the right groups. */
std::unique_ptr<QSettings> settings();
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList& errors);
void slotInvalidCredentials();
void slotCredentialsFetched(AbstractCredentials* creds);
+ void slotCredentialsAsked(AbstractCredentials* creds);
private:
AccountPtr _account;
ConnectionStatus _connectionStatus;
QStringList _connectionErrors;
bool _waitingForNewCredentials;
+ CredentialFetchMode _credentialsFetchMode;
QPointer<ConnectionValidator> _connectionValidator;
};
// when the error is permanent.
if (state != AccountState::SignedOut
&& state != AccountState::ConfigurationError) {
- accountState->checkConnectivity(AbstractCredentials::NonInteractive);
+ accountState->checkConnectivity(AccountState::NonInteractive);
}
}
namespace OCC
{
- QString HttpCredentialsGui::queryPassword(bool *ok, const QString& hint)
+void HttpCredentialsGui::askFromUser()
{
- if (!ok) {
- return QString();
- }
+ // The rest of the code assumes that this will be done asynchronously
+ QMetaObject::invokeMethod(this, "askFromUserAsync", Qt::QueuedConnection);
+}
+void HttpCredentialsGui::askFromUserAsync()
+{
QString msg = tr("Please enter %1 password:\n"
"\n"
"User: %2\n"
"Account: %3\n")
.arg(Theme::instance()->appNameGUI(), _user, _account->displayName());
- if (!hint.isEmpty()) {
- msg += QLatin1String("\n") + hint + QLatin1String("\n");
+ if (!_fetchErrorString.isEmpty()) {
+ msg += QLatin1String("\n") + tr("Reading from keychain failed with error: '%1'").arg(
+ _fetchErrorString) + QLatin1String("\n");
}
- return QInputDialog::getText(0, tr("Enter Password"), msg,
+ bool ok = false;
+ QString pwd = QInputDialog::getText(0, tr("Enter Password"), msg,
QLineEdit::Password, _previousPassword,
- ok);
+ &ok);
+ if (ok) {
+ _password = pwd;
+ _ready = true;
+ persist();
+ }
+ emit asked();
}
} // namespace OCC
public:
explicit HttpCredentialsGui() : HttpCredentials() {}
HttpCredentialsGui(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd) : HttpCredentials(user, password, certificatePath, certificatePasswd) {}
- QString queryPassword(bool *ok, const QString& hint) Q_DECL_OVERRIDE;
+ void askFromUser() Q_DECL_OVERRIDE;
+ Q_INVOKABLE void askFromUserAsync();
};
} // namespace OCC
#include "accessmanager.h"
#include "account.h"
-#include "logger.h"
#include "theme.h"
#include "cookiejar.h"
#include "syncengine.h"
: _ready(true),
_stillValid(true),
_fetchJobInProgress(false),
- _interactiveFetch(true),
_browser(0),
_shibCookie(cookie)
{
return _ready;
}
-void ShibbolethCredentials::fetch(FetchMode mode)
+void ShibbolethCredentials::fetchFromKeychain()
{
if(_fetchJobInProgress) {
return;
}
- _interactiveFetch = mode == Interactive;
if (_user.isEmpty()) {
_user = _account->credentialSetting(QLatin1String(userC)).toString();
}
}
+void ShibbolethCredentials::askFromUser()
+{
+ showLoginWindow();
+}
+
bool ShibbolethCredentials::stillValid(QNetworkReply *reply)
{
Q_UNUSED(reply)
_stillValid = true;
_ready = true;
_fetchJobInProgress = false;
- Q_EMIT fetched();
+ Q_EMIT asked();
}
{
_ready = false;
_fetchJobInProgress = false;
- Q_EMIT fetched();
+ Q_EMIT asked();
}
void ShibbolethCredentials::slotReadJobDone(QKeychain::Job *job)
_stillValid = true;
_fetchJobInProgress = false;
Q_EMIT fetched();
- } else if (_interactiveFetch) {
- showLoginWindow();
} else {
- Logger::instance()->postOptionalGuiLog(tr("Reauthentication required"), tr("You need to re-login to continue using the account %1.").arg(_account->displayName()));
_ready = false;
_fetchJobInProgress = false;
Q_EMIT fetched();
QString user() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
- void fetch(FetchMode mode = Interactive) Q_DECL_OVERRIDE;
+ void fetchFromKeychain() Q_DECL_OVERRIDE;
+ void askFromUser();
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
void invalidateToken() Q_DECL_OVERRIDE;
bool _ready;
bool _stillValid;
bool _fetchJobInProgress;
- bool _interactiveFetch;
QPointer<ShibbolethWebView> _browser;
QNetworkCookie _shibCookie;
QString _user;
SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(_credentials, SIGNAL(fetched()),
SLOT(slotCredentialsFetched()));
+ connect(_credentials, SIGNAL(asked()),
+ SLOT(slotCredentialsAsked()));
}
QUrl Account::davUrl() const
emit credentialsFetched(_credentials);
}
+void Account::slotCredentialsAsked()
+{
+ emit credentialsAsked(_credentials);
+}
+
void Account::handleInvalidCredentials()
{
emit invalidCredentials();
void propagatorNetworkActivity();
void invalidCredentials();
void credentialsFetched(AbstractCredentials* credentials);
+ void credentialsAsked(AbstractCredentials* credentials);
/// Forwards from QNetworkAccessManager::proxyAuthenticationRequired().
void proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*);
protected Q_SLOTS:
void slotHandleSslErrors(QNetworkReply*,QList<QSslError>);
void slotCredentialsFetched();
+ void slotCredentialsAsked();
private:
Account(QObject *parent = 0);
namespace OCC {
-ConnectionValidator::ConnectionValidator(AccountPtr account, AbstractCredentials::FetchMode credentialsFetchMode, QObject *parent)
+ConnectionValidator::ConnectionValidator(AccountPtr account, QObject *parent)
: QObject(parent),
_account(account),
- _credentialsFetchMode(credentialsFetchMode),
_isCheckingServerAndAuth(false)
{
}
#include <QVariantMap>
#include <QNetworkReply>
#include "accountfwd.h"
-#include "creds/abstractcredentials.h"
namespace OCC {
{
Q_OBJECT
public:
- explicit ConnectionValidator(AccountPtr account, AbstractCredentials::FetchMode credentialsFetchMode, QObject *parent = 0);
+ explicit ConnectionValidator(AccountPtr account, QObject *parent = 0);
enum Status {
Undefined,
Connected,
NotConfigured,
ServerVersionMismatch,
- CredentialsWrong,
+ CredentialsMissingOrWrong,
StatusNotFound,
UserCanceledCredentials,
ServiceUnavailable,
QStringList _errors;
AccountPtr _account;
- AbstractCredentials::FetchMode _credentialsFetchMode;
bool _isCheckingServerAndAuth;
};
Q_OBJECT
public:
- enum FetchMode { Interactive, NonInteractive };
AbstractCredentials();
// No need for virtual destructor - QObject already has one.
virtual QString user() const = 0;
virtual QNetworkAccessManager* getQNAM() const = 0;
virtual bool ready() const = 0;
- virtual void fetch(FetchMode mode = Interactive) = 0;
+ virtual void fetchFromKeychain() = 0;
+ virtual void askFromUser() = 0;
virtual bool stillValid(QNetworkReply *reply) = 0;
virtual void persist() = 0;
/** Invalidates auth token, or password for basic auth */
Q_SIGNALS:
void fetched();
+ void asked();
protected:
Account* _account;
return true;
}
-void DummyCredentials::fetch(FetchMode)
+void DummyCredentials::fetchFromKeychain()
{
Q_EMIT(fetched());
}
+void DummyCredentials::askFromUser()
+{
+ Q_EMIT(asked());
+}
+
void DummyCredentials::persist()
{}
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
- void fetch(FetchMode mode = Interactive) Q_DECL_OVERRIDE;
+ void fetchFromKeychain() Q_DECL_OVERRIDE;
+ void askFromUser() Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
void invalidateToken() Q_DECL_OVERRIDE {}
};
#include "account.h"
#include "accessmanager.h"
-#include "logger.h"
#include "utility.h"
#include "theme.h"
#include "syncengine.h"
} // ns
HttpCredentials::HttpCredentials()
- : _user(),
- _password(),
- _certificatePath(),
- _certificatePasswd(),
- _ready(false),
- _fetchJobInProgress(false),
- _interactiveFetch(true)
+ : _ready(false),
+ _fetchJobInProgress(false)
{
}
HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd)
: _user(user),
_password(password),
+ _ready(true),
_certificatePath(certificatePath),
_certificatePasswd(certificatePasswd),
- _ready(true),
- _fetchJobInProgress(false),
- _interactiveFetch(true)
+ _fetchJobInProgress(false)
{
}
return _user;
}
-void HttpCredentials::fetch(FetchMode mode)
+void HttpCredentials::fetchFromKeychain()
{
+ // FIXME: Should this check go if we check in AccountState instead?
if (_fetchJobInProgress) {
return;
}
- _interactiveFetch = mode == Interactive;
// User must be fetched from config file
fetchUser();
QKeychain::Error error = job->error();
+ _fetchJobInProgress = false;
if( !_password.isEmpty() && error == NoError ) {
- _fetchJobInProgress = false;
// All cool, the keychain did not come back with error.
// Still, the password can be empty which indicates a problem and
} else {
// we come here if the password is empty or any other keychain
// error happend.
- // In all error conditions it should
- // ask the user for the password interactively now.
- // interactive password dialog starts here
-
- QString hint;
- if (job->error() != EntryNotFound) {
- hint = tr("Reading from keychain failed with error: '%1'").arg(
- job->errorString());
- }
- bool ok = false;
- QString pwd;
- if (_interactiveFetch)
- pwd = queryPassword(&ok, hint);
- else
- Logger::instance()->postOptionalGuiLog(tr("Reauthentication required"), tr("You need to re-login to continue using the account %1.").arg(_account->displayName()));
- _fetchJobInProgress = false;
- if (ok) {
- _password = pwd;
- _ready = true;
- persist();
- } else {
- _password = QString::null;
- _ready = false;
- }
+ _fetchErrorString = job->error() != EntryNotFound ? job->errorString() : QString();
+
+ _password = QString();
+ _ready = false;
emit fetched();
}
}
QString authType() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
- void fetch(FetchMode mode = Interactive) Q_DECL_OVERRIDE;
+ void fetchFromKeychain() Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
QString user() const Q_DECL_OVERRIDE;
QString password() const;
- virtual QString queryPassword(bool *ok, const QString& hint) = 0;
void invalidateToken() Q_DECL_OVERRIDE;
QString fetchUser();
virtual bool sslIsTrusted() { return false; }
QString _user;
QString _password;
QString _previousPassword;
+ QString _fetchErrorString;
+ bool _ready;
private:
QString _certificatePath;
QString _certificatePasswd;
- bool _ready;
bool _fetchJobInProgress; //True if the keychain job is in progress or the input dialog visible
- bool _interactiveFetch;
};
} // namespace OCC