Commit 595bf8f9 authored by Shashwat Jolly's avatar Shashwat Jolly

Handle token expiry when password is changed

Also fix bug where setup wizard asked for encryption password even when there was an error fetching userinfo
parent 7ce90beb
......@@ -76,9 +76,15 @@ bool EteSyncClientState::initToken(const QString &serverUrl, const QString &user
// Initialise EteSync client state
mClient = etesync_new(QStringLiteral("Akonadi EteSync Resource"), mServerUrl);
if (!mClient) {
qCDebug(ETESYNC_LOG) << "Could not initialize EteSync client";
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
return false;
}
mToken = etesync_auth_get_token(mClient.get(), mUsername, mPassword);
if (mToken.isEmpty()) {
qCDebug(ETESYNC_LOG) << "Empty token";
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
return false;
}
qCDebug(ETESYNC_LOG) << "Received token" << mToken;
......@@ -88,14 +94,17 @@ bool EteSyncClientState::initToken(const QString &serverUrl, const QString &user
void EteSyncClientState::refreshToken()
{
qCDebug(ETESYNC_LOG) << "Refreshing token";
mToken = etesync_auth_get_token(mClient.get(), mUsername, mPassword);
if (mToken.isEmpty()) {
qCDebug(ETESYNC_LOG) << "Empty token";
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
tokenRefreshed(false);
return;
}
qCDebug(ETESYNC_LOG) << "Received token" << mToken;
etesync_set_auth_token(mClient.get(), mToken);
tokenRefreshed();
tokenRefreshed(true);
}
void EteSyncClientState::refreshUserInfo()
......@@ -151,27 +160,38 @@ bool EteSyncClientState::initKeypair(const QString &encryptionPassword)
return true;
}
void EteSyncClientState::initAccount(const QString &encryptionPassword)
bool EteSyncClientState::initAccount(const QString &encryptionPassword)
{
mEncryptionPassword = encryptionPassword;
mDerived = etesync_crypto_derive_key(mClient.get(), mUsername, mEncryptionPassword);
if (mDerived.isEmpty()) {
qCDebug(ETESYNC_LOG) << "Could not derive key from encryption password";
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
return false;
}
mUserInfo = etesync_user_info_new(mUsername, ETESYNC_CURRENT_VERSION);
mKeypair = EteSyncAsymmetricKeyPairPtr(etesync_crypto_generate_keypair(mClient.get()));
EteSyncCryptoManagerPtr userInfoCryptoManager = etesync_user_info_get_crypto_manager(mUserInfo.get(), mDerived);
etesync_user_info_set_keypair(mUserInfo.get(), userInfoCryptoManager.get(), mKeypair.get());
if (etesync_user_info_set_keypair(mUserInfo.get(), userInfoCryptoManager.get(), mKeypair.get())) {
qCDebug(ETESYNC_LOG) << "Could not create set user info keypair";
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
return false;
}
EteSyncUserInfoManagerPtr userInfoManager(etesync_user_info_manager_new(mClient.get()));
if (etesync_user_info_manager_create(userInfoManager.get(), mUserInfo.get())) {
qCDebug(ETESYNC_LOG) << "Could not create user info";
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
return;
return false;
};
createDefaultJournal(QStringLiteral(ETESYNC_COLLECTION_TYPE_CALENDAR), i18n("My Calendar"));
createDefaultJournal(QStringLiteral(ETESYNC_COLLECTION_TYPE_ADDRESS_BOOK), i18n("My Contacts"));
createDefaultJournal(QStringLiteral(ETESYNC_COLLECTION_TYPE_TASKS), i18n("My Tasks"));
const auto calendarResult = createDefaultJournal(QStringLiteral(ETESYNC_COLLECTION_TYPE_CALENDAR), i18n("My Calendar"));
const auto contactsResult = createDefaultJournal(QStringLiteral(ETESYNC_COLLECTION_TYPE_ADDRESS_BOOK), i18n("My Contacts"));
const auto tasksResult = createDefaultJournal(QStringLiteral(ETESYNC_COLLECTION_TYPE_TASKS), i18n("My Tasks"));
return calendarResult && contactsResult && tasksResult;
}
void EteSyncClientState::createDefaultJournal(const QString &journalType, const QString &journalName)
bool EteSyncClientState::createDefaultJournal(const QString &journalType, const QString &journalName)
{
const QString journalUid = QStringFromCharPtr(CharPtr(etesync_gen_uid()));
EteSyncJournalPtr journal = etesync_journal_new(journalUid, ETESYNC_CURRENT_VERSION);
......@@ -183,14 +203,15 @@ void EteSyncClientState::createDefaultJournal(const QString &journalType, const
if (etesync_journal_set_info(journal.get(), cryptoManager.get(), info.get())) {
qCDebug(ETESYNC_LOG) << "Could not set journal info";
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
return;
return false;
};
if (etesync_journal_manager_create(mJournalManager.get(), journal.get())) {
qCDebug(ETESYNC_LOG) << "Could not create journal";
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
return;
return false;
}
return true;
}
void EteSyncClientState::saveSettings()
......
......@@ -32,7 +32,7 @@ public:
bool initToken(const QString &serverUrl, const QString &username, const QString &password);
bool initUserInfo();
bool initKeypair(const QString &encryptionPassword);
void initAccount(const QString &encryptionPassword);
bool initAccount(const QString &encryptionPassword);
void saveSettings();
void invalidateToken();
void refreshUserInfo();
......@@ -67,10 +67,10 @@ public Q_SLOTS:
Q_SIGNALS:
void clientInitialised(bool successful);
void tokenRefreshed();
void tokenRefreshed(bool successful);
private:
void createDefaultJournal(const QString &journalType, const QString &journalName);
bool createDefaultJournal(const QString &journalType, const QString &journalName);
EteSyncPtr mClient;
QString mDerived;
QString mToken;
......
......@@ -31,6 +31,7 @@
#include <KCalendarCore/Event>
#include <KCalendarCore/Todo>
#include <KLocalizedString>
#include <KMessageBox>
#include <QDBusConnection>
#include "entriesfetchjob.h"
......@@ -107,6 +108,7 @@ void EteSyncResource::configure(WId windowId)
synchronize();
mClientState->saveSettings();
Q_EMIT configurationDialogAccepted();
setOnline(true);
} else {
Q_EMIT configurationDialogRejected();
}
......@@ -152,7 +154,7 @@ void EteSyncResource::slotCollectionsRetrieved(KJob *job)
{
if (job->error()) {
qCWarning(ETESYNC_LOG) << "Error in fetching journals";
qCWarning(ETESYNC_LOG) << "EteSync error" << etesync_get_error_message();
qCWarning(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
handleError();
return;
}
......@@ -175,7 +177,7 @@ void EteSyncResource::slotCollectionsRetrieved(KJob *job)
/**
* Handles all EteSync errors (except CONFLICT).
* To be called immediatey after an EteSync operation.
* To be called immediately after an EteSync operation.
* CONFLICT error has been handled seperately in BaseHandler.
*/
bool EteSyncResource::handleError()
......@@ -183,9 +185,9 @@ bool EteSyncResource::handleError()
switch (etesync_get_error_code()) {
case ETESYNC_ERROR_CODE_UNAUTHORIZED: {
qCDebug(ETESYNC_LOG) << "Invalid token";
qCDebug(ETESYNC_LOG) << "EteSync error" << etesync_get_error_message();
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
deferTask();
connect(mClientState.get(), &EteSyncClientState::tokenRefreshed, this, &EteSyncResource::taskDone);
connect(mClientState.get(), &EteSyncClientState::tokenRefreshed, this, &EteSyncResource::slotTokenRefreshed);
scheduleCustomTask(mClientState.get(), "refreshToken", QVariant(), ResourceBase::Prepend);
return true;
}
......@@ -198,7 +200,7 @@ bool EteSyncResource::handleError()
case ETESYNC_ERROR_CODE_INVALID_DATA:
case ETESYNC_ERROR_CODE_CONNECTION:
case ETESYNC_ERROR_CODE_HTTP: {
qCDebug(ETESYNC_LOG) << "EteSync error" << etesync_get_error_message();
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
qCDebug(ETESYNC_LOG) << "Cancelling task";
cancelTask();
return true;
......@@ -207,6 +209,29 @@ bool EteSyncResource::handleError()
return false;
}
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";
showErrorDialog(QStringLiteral("Your EteSync credentials were changed. Please click OK to re-enter your credentials."), QStringFromCharPtr(CharPtr(etesync_get_error_message())), QStringLiteral("Credentials Changed"));
qCDebug(ETESYNC_LOG) << "Setting offline";
setOnline(false);
configure(winIdForDialogs());
}
}
taskDone();
}
void EteSyncResource::showErrorDialog(const QString &errorText, const QString &errorDetails, const QString &title)
{
QWidget *parent = QWidget::find(winIdForDialogs());
QDialog *dialog = new QDialog(parent, Qt::Dialog);
dialog->setAttribute(Qt::WA_NativeWindow, true);
KWindowSystem::setMainWindow(dialog->windowHandle(), winIdForDialogs());
KMessageBox::detailedSorry(dialog, errorText, errorDetails, title);
}
void EteSyncResource::setupCollection(Collection &collection, EteSyncJournal *journal)
{
if (!journal) {
......
......@@ -78,6 +78,8 @@ private Q_SLOTS:
void initialiseDone(bool successful);
void slotItemsRetrieved(KJob *job);
void slotCollectionsRetrieved(KJob *job);
void slotTokenRefreshed(bool successful);
void showErrorDialog(const QString &errorText, const QString &errorDetails = QString(), const QString &title = QStringLiteral("Something went wrong"));
private:
EteSyncClientState::Ptr mClientState;
......
......@@ -74,7 +74,6 @@ LoginPage::LoginPage(QWidget *parent)
int LoginPage::nextId() const
{
// Implement token job
return SetupWizard::W_EncryptionPasswordPage;
}
......@@ -86,14 +85,25 @@ bool LoginPage::validatePage()
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) {
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
if (etesync_get_error_code() == EteSyncErrorCode::ETESYNC_ERROR_CODE_UNAUTHORIZED) {
auto err = etesync_get_error_code();
if (err == EteSyncErrorCode::ETESYNC_ERROR_CODE_UNAUTHORIZED || err == EteSyncErrorCode::ETESYNC_ERROR_CODE_HTTP) {
mLoginLabel->setText(i18n("Incorrect login credentials. Please try again."));
} else {
mLoginLabel->setText(i18n(etesync_get_error_message()));
mLoginLabel->setText(i18n(CharPtr(etesync_get_error_message()).get()));
}
return false;
}
return loginResult;
const bool userInfoResult = static_cast<SetupWizard *>(wizard())->mClientState->initUserInfo();
if (!userInfoResult) {
if (etesync_get_error_code() == EteSyncErrorCode::ETESYNC_ERROR_CODE_NOT_FOUND) {
wizard()->setProperty("initAccount", true);
return true;
}
mLoginLabel->setText(i18n(CharPtr(etesync_get_error_message()).get()));
return false;
}
return true;
}
EncryptionPasswordPage::EncryptionPasswordPage(QWidget *parent)
......@@ -120,28 +130,26 @@ int EncryptionPasswordPage::nextId() const
void EncryptionPasswordPage::initializePage()
{
const bool userInfoResult = static_cast<SetupWizard *>(wizard())->mClientState->initUserInfo();
if (!userInfoResult) {
if (etesync_get_error_code() == EteSyncErrorCode::ETESYNC_ERROR_CODE_NOT_FOUND) {
setSubTitle(i18n("Please set your encryption password below, and make sure you got it right, as it can't be recovered if lost!"));
mInitAccount = true;
} else {
qCDebug(ETESYNC_LOG) << "EteSync error" << QStringFromCharPtr(CharPtr(etesync_get_error_message()));
setSubTitle(i18n("An error occured! Please try again."));
}
const auto initAccount = wizard()->property("initAccount");
if (initAccount.isValid() && initAccount.toBool()) {
setSubTitle(i18n("Welcome to EteSync! Please set your encryption password below, and make sure you got it right, as it can't be recovered if lost!"));
}
}
bool EncryptionPasswordPage::validatePage()
{
const QString encryptionPassword = field(QStringLiteral("credentialsEncryptionPassword")).toString();
if (mInitAccount) {
static_cast<SetupWizard *>(wizard())->mClientState->initAccount(encryptionPassword);
return true;
const auto initAccount = wizard()->property("initAccount");
if (initAccount.isValid() && initAccount.toBool()) {
return static_cast<SetupWizard *>(wizard())->mClientState->initAccount(encryptionPassword);
}
const bool keypairResult = static_cast<SetupWizard *>(wizard())->mClientState->initKeypair(encryptionPassword);
if (!keypairResult) {
mEncryptionPasswordLabel->setText(i18n("Incorrect encryption password. Please try again."));
if (etesync_get_error_code() == ETESYNC_ERROR_CODE_ENCRYPTION_MAC) {
mEncryptionPasswordLabel->setText(i18n("Incorrect encryption password. Please try again."));
} else {
mEncryptionPasswordLabel->setText(i18n(CharPtr(etesync_get_error_message()).get()));
}
}
return keypairResult;
}
\ No newline at end of file
......@@ -79,7 +79,6 @@ public:
private:
KPasswordLineEdit *mEncryptionPassword = nullptr;
QLabel *mEncryptionPasswordLabel = nullptr;
bool mInitAccount = false;
};
#endif
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