Commit 100b23a5 authored by Shashwat Jolly's avatar Shashwat Jolly
Browse files

Fix password change handling and login asynchronously

Create a new LoginJob to handle async login
parent cd2b08e6
Pipeline #32387 passed with stage
in 57 minutes and 32 seconds
......@@ -16,6 +16,7 @@ set(etesyncresource_SRCS
etesyncclientstate.cpp
journalsfetchjob.cpp
entriesfetchjob.cpp
loginjob.cpp
contacthandler.cpp
basehandler.cpp
calendartaskbasehandler.cpp
......
......@@ -17,8 +17,6 @@
#include "entriesfetchjob.h"
#include <kio/job.h>
#include <QtConcurrent>
#include "etesync_debug.h"
......
......@@ -104,12 +104,15 @@ void EteSyncResource::configure(WId windowId)
}
const int result = wizard.exec();
if (result == QDialog::Accepted) {
synchronize();
mClientState->saveSettings();
mCredentialsRequired = false;
qCDebug(ETESYNC_LOG) << "Setting online";
setOnline(true);
synchronize();
Q_EMIT configurationDialogAccepted();
} else {
qCDebug(ETESYNC_LOG) << "Setting offline";
setOnline(false);
Q_EMIT configurationDialogRejected();
}
}
......@@ -119,11 +122,10 @@ void EteSyncResource::retrieveCollections()
qCDebug(ETESYNC_LOG) << "Retrieving collections";
if (credentialsRequired()) {
deferTask();
return;
}
setCollectionStreamingEnabled(true);
mJournalsCache.clear();
mClientState->refreshUserInfo();
......@@ -177,7 +179,6 @@ void EteSyncResource::slotCollectionsRetrieved(KJob *job)
mJournalsCacheUpdateTime = QDateTime::currentDateTime();
free(journals);
collectionsRetrieved(list);
collectionsRetrievalDone();
}
/**
......@@ -226,8 +227,6 @@ bool EteSyncResource::credentialsRequired()
qCDebug(ETESYNC_LOG) << "Credentials required";
showErrorDialog(i18n("Your EteSync credentials were changed. Please click OK to re-enter your credentials."), i18n(CharPtr(etesync_get_error_message()).get()), i18n("Credentials Changed"));
configure(winIdForDialogs());
setOnline(false);
deferTask();
}
return mCredentialsRequired;
}
......@@ -236,7 +235,7 @@ void EteSyncResource::slotTokenRefreshed(bool successful)
{
if (!successful) {
if (etesync_get_error_code() == ETESYNC_ERROR_CODE_HTTP) {
qCDebug(ETESYNC_LOG) << "HTTP Error while tokenRefresh - calling reconfigure";
qCDebug(ETESYNC_LOG) << "HTTP Error while tokenRefresh";
mCredentialsRequired = true;
}
}
......@@ -344,6 +343,7 @@ void EteSyncResource::retrieveItems(const Akonadi::Collection &collection)
}
if (credentialsRequired()) {
deferTask();
return;
}
......@@ -429,6 +429,7 @@ void EteSyncResource::itemAdded(const Akonadi::Item &item,
qCDebug(ETESYNC_LOG) << "Journal UID" << collection.remoteId();
if (credentialsRequired()) {
deferTask();
return;
}
......@@ -448,6 +449,7 @@ void EteSyncResource::itemChanged(const Akonadi::Item &item,
qCDebug(ETESYNC_LOG) << "Journal UID" << item.parentCollection().remoteId();
if (credentialsRequired()) {
deferTask();
return;
}
......@@ -465,6 +467,7 @@ void EteSyncResource::itemRemoved(const Akonadi::Item &item)
qCDebug(ETESYNC_LOG) << "Item removed" << item.mimeType();
if (credentialsRequired()) {
deferTask();
return;
}
......@@ -482,6 +485,7 @@ void EteSyncResource::collectionAdded(const Akonadi::Collection &collection, con
qCDebug(ETESYNC_LOG) << "Collection added" << collection.mimeType();
if (credentialsRequired()) {
deferTask();
return;
}
......@@ -499,6 +503,7 @@ void EteSyncResource::collectionChanged(const Akonadi::Collection &collection)
qCDebug(ETESYNC_LOG) << "Collection changed" << collection.mimeType();
if (credentialsRequired()) {
deferTask();
return;
}
......@@ -516,6 +521,7 @@ void EteSyncResource::collectionRemoved(const Akonadi::Collection &collection)
qCDebug(ETESYNC_LOG) << "Collection removed" << collection.mimeType();
if (credentialsRequired()) {
deferTask();
return;
}
......
......@@ -17,8 +17,6 @@
#include "journalsfetchjob.h"
#include <kio/job.h>
#include <QtConcurrent>
using namespace EteSyncAPI;
......
/*
* Copyright (C) 2020 by Shashwat Jolly <shashwat.jolly@gmail.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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "loginjob.h"
#include <QtConcurrent>
#include "etesync_debug.h"
using namespace EteSyncAPI;
LoginJob::LoginJob(EteSyncClientState *clientState, const QString &serverUrl, const QString &username, const QString &password, QObject *parent)
: KJob(parent), mClientState(clientState), mServerUrl(serverUrl), mUsername(username), mPassword(password)
{
}
void LoginJob::start()
{
QtConcurrent::run(this, &LoginJob::login);
}
void LoginJob::login()
{
mLoginResult = mClientState->initToken(mServerUrl, mUsername, mPassword);
if (!mLoginResult) {
qCDebug(ETESYNC_LOG) << "Returning error from LoginJob";
setError(etesync_get_error_code());
CharPtr err(etesync_get_error_message());
setErrorText(QStringFromCharPtr(err));
emitResult();
return;
}
mUserInfoResult = mClientState->initUserInfo();
if (!mUserInfoResult) {
qCDebug(ETESYNC_LOG) << "Returning error from LoginJob";
setError(etesync_get_error_code());
CharPtr err(etesync_get_error_message());
setErrorText(QStringFromCharPtr(err));
emitResult();
return;
}
emitResult();
}
\ No newline at end of file
/*
* Copyright (C) 2020 by Shashwat Jolly <shashwat.jolly@gmail.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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef LOGINJOB_H
#define LOGINJOB_H
#include <KJob>
#include "etesyncadapter.h"
#include "etesyncclientstate.h"
namespace EteSyncAPI {
class LoginJob : public KJob
{
Q_OBJECT
public:
explicit LoginJob(EteSyncClientState *clientState, const QString &serverUrl, const QString &username, const QString &password, QObject *parent = nullptr);
void start() override;
bool getLoginResult() const
{
return mLoginResult;
}
bool getUserInfoResult() const
{
return mUserInfoResult;
}
private:
void login();
EteSyncClientState *mClientState = nullptr;
QString mServerUrl;
QString mUsername;
QString mPassword;
bool mLoginResult;
bool mUserInfoResult;
};
} // namespace EteSyncAPI
#endif
......@@ -28,6 +28,9 @@
#include <QPushButton>
#include "etesync_debug.h"
#include "loginjob.h"
using namespace EteSyncAPI;
SetupWizard::SetupWizard(EteSyncClientState *clientState, QWidget *parent)
: QWizard(parent), mClientState(clientState)
......@@ -36,6 +39,36 @@ SetupWizard::SetupWizard(EteSyncClientState *clientState, QWidget *parent)
setWindowIcon(QIcon::fromTheme(QStringLiteral("akonadi-etesync")));
setPage(W_LoginPage, new LoginPage);
setPage(W_EncryptionPasswordPage, new EncryptionPasswordPage);
disconnect(button(QWizard::NextButton), SIGNAL(clicked()), this, SLOT(next()));
connect(button(QWizard::NextButton), SIGNAL(clicked()), this, SLOT(manualNext()));
disconnect(button(QWizard::FinishButton), SIGNAL(clicked()), this, SLOT(accept()));
connect(button(QWizard::FinishButton), SIGNAL(clicked()), this, SLOT(manualNext()));
}
void SetupWizard::manualNext()
{
qCDebug(ETESYNC_LOG) << "Manual next";
if (currentId() == W_LoginPage) {
static_cast<LoginPage *>(page(W_LoginPage))->showProgressBar();
const QString username = field(QStringLiteral("credentialsUserName")).toString();
const QString password = field(QStringLiteral("credentialsPassword")).toString();
const QString advancedServerUrl = field(QStringLiteral("credentialsServerUrl")).toString();
const QString serverUrl = advancedServerUrl.isEmpty() ? QStringLiteral("https://api.etesync.com") : advancedServerUrl;
auto job = new LoginJob(mClientState, serverUrl, username, password, this);
connect(job, &LoginJob::finished, this, [this](KJob *job) {
qCDebug(ETESYNC_LOG) << "Login finished";
static_cast<LoginPage *>(page(W_LoginPage))->setLoginResult(static_cast<LoginJob *>(job)->getLoginResult());
static_cast<LoginPage *>(page(W_LoginPage))->setUserInfoResult(static_cast<LoginJob *>(job)->getUserInfoResult());
static_cast<LoginPage *>(page(W_LoginPage))->setErrorCode(job->error());
static_cast<LoginPage *>(page(W_LoginPage))->setErrorMessage(job->errorText());
static_cast<LoginPage *>(page(W_LoginPage))->hideProgressBar();
nextId() == -1 ? QWizard::accept() : QWizard::next();
});
job->start();
return;
}
nextId() == -1 ? QWizard::accept() : QWizard::next();
}
LoginPage::LoginPage(QWidget *parent)
......@@ -68,14 +101,19 @@ LoginPage::LoginPage(QWidget *parent)
layout->labelForField(mServerUrl)->setVisible(false);
mProgressBar = new QProgressBar;
mProgressBar->setVisible(false);
mProgressBar->setRange(0, 0);
layout->addWidget(mProgressBar);
connect(mAdvancedSettings, SIGNAL(toggled(bool)), mServerUrl, SLOT(setVisible(bool)));
connect(mAdvancedSettings, SIGNAL(toggled(bool)), layout->labelForField(mServerUrl), SLOT(setVisible(bool)));
}
void LoginPage::initializePage()
{
qCDebug(ETESYNC_LOG) << "Login page - isInitialized" << mIsInitialized;
mIsInitialized = static_cast<SetupWizard *>(wizard())->mClientState->isInitialized();
qCDebug(ETESYNC_LOG) << "Login page - isInitialized" << mIsInitialized;
if (mIsInitialized) {
mAdvancedSettings->setVisible(false);
setField(QStringLiteral("credentialsServerUrl"), static_cast<SetupWizard *>(wizard())->mClientState->serverUrl());
......@@ -94,33 +132,26 @@ int LoginPage::nextId() const
bool LoginPage::validatePage()
{
const QString username = field(QStringLiteral("credentialsUserName")).toString();
const QString password = field(QStringLiteral("credentialsPassword")).toString();
const QString advancedServerUrl = field(QStringLiteral("credentialsServerUrl")).toString();
const QString serverUrl = advancedServerUrl.isEmpty() ? QStringLiteral("https://api.etesync.com") : advancedServerUrl;
const bool loginResult = static_cast<SetupWizard *>(wizard())->mClientState->initToken(serverUrl, username, password);
if (!loginResult) {
auto err = etesync_get_error_code();
qCDebug(ETESYNC_LOG) << "loginResult error" << err;
if (err == EteSyncErrorCode::ETESYNC_ERROR_CODE_UNAUTHORIZED || err == EteSyncErrorCode::ETESYNC_ERROR_CODE_HTTP) {
if (!mLoginResult) {
qCDebug(ETESYNC_LOG) << "loginResult error" << mErrorCode;
if (mErrorCode == EteSyncErrorCode::ETESYNC_ERROR_CODE_UNAUTHORIZED || mErrorCode == EteSyncErrorCode::ETESYNC_ERROR_CODE_HTTP) {
mLoginLabel->setText(i18n("Incorrect login credentials. Please try again."));
} else if (err == EteSyncErrorCode::ETESYNC_ERROR_CODE_ENCODING) {
} else if (mErrorCode == EteSyncErrorCode::ETESYNC_ERROR_CODE_ENCODING) {
mLoginLabel->setText(i18n("Please ensure that the server URL is correct. The URL should start with http:// or https://."));
} else if (err == EteSyncErrorCode::ETESYNC_ERROR_CODE_CONNECTION) {
} else if (mErrorCode == EteSyncErrorCode::ETESYNC_ERROR_CODE_CONNECTION) {
mLoginLabel->setText(i18n("Could not connect to the server. Please ensure that the server URL is correct."));
} else {
mLoginLabel->setText(i18n(CharPtr(etesync_get_error_message()).get()));
mLoginLabel->setText(i18n(charArrFromQString(mErrorMessage)));
}
return false;
}
const bool userInfoResult = static_cast<SetupWizard *>(wizard())->mClientState->initUserInfo();
if (!userInfoResult) {
if (etesync_get_error_code() == EteSyncErrorCode::ETESYNC_ERROR_CODE_NOT_FOUND) {
if (!mUserInfoResult) {
if (mErrorCode == EteSyncErrorCode::ETESYNC_ERROR_CODE_NOT_FOUND) {
wizard()->setProperty("initAccount", true);
return true;
}
mLoginLabel->setText(i18n(CharPtr(etesync_get_error_message()).get()));
mLoginLabel->setText(i18n(charArrFromQString(mErrorMessage)));
return false;
}
return true;
......
......@@ -20,6 +20,7 @@
#define SETUPWIZARD_H
#include <QLabel>
#include <QProgressBar>
#include <QWizard>
#include <QWizardPage>
......@@ -51,6 +52,9 @@ public:
};
EteSyncClientState *mClientState = nullptr;
public Q_SLOTS:
void manualNext();
};
class LoginPage : public QWizardPage
......@@ -61,13 +65,48 @@ public:
void initializePage() override;
bool validatePage() override;
void showProgressBar()
{
mProgressBar->setVisible(true);
}
void hideProgressBar()
{
mProgressBar->setVisible(false);
}
void setLoginResult(bool loginResult)
{
mLoginResult = loginResult;
}
void setUserInfoResult(bool userInfoResult)
{
mUserInfoResult = userInfoResult;
}
void setErrorCode(int errorCode)
{
mErrorCode = errorCode;
}
void setErrorMessage(QString errorMessage)
{
mErrorMessage = errorMessage;
}
private:
QLineEdit *mUserName = nullptr;
KPasswordLineEdit *mPassword = nullptr;
QCheckBox *mAdvancedSettings = nullptr;
QLineEdit *mServerUrl = nullptr;
QLabel *mLoginLabel = nullptr;
QProgressBar *mProgressBar;
bool mIsInitialized = false;
bool mLoginResult = false;
bool mUserInfoResult = false;
int mErrorCode;
QString mErrorMessage;
};
class EncryptionPasswordPage : public QWizardPage
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment