big changes to simplify account dialog flows

This commit is contained in:
Martin Rotter 2021-02-25 12:21:07 +01:00
parent 1d5b69b366
commit 0a588f7b5e
24 changed files with 164 additions and 172 deletions

View file

@ -481,6 +481,7 @@ bool FeedsModel::addServiceAccount(ServiceRoot* root, bool freshly_activated) {
connect(root, &ServiceRoot::reloadMessageListRequested, this, &FeedsModel::reloadMessageListRequested); connect(root, &ServiceRoot::reloadMessageListRequested, this, &FeedsModel::reloadMessageListRequested);
connect(root, &ServiceRoot::itemExpandRequested, this, &FeedsModel::itemExpandRequested); connect(root, &ServiceRoot::itemExpandRequested, this, &FeedsModel::itemExpandRequested);
connect(root, &ServiceRoot::itemExpandStateSaveRequested, this, &FeedsModel::itemExpandStateSaveRequested); connect(root, &ServiceRoot::itemExpandStateSaveRequested, this, &FeedsModel::itemExpandStateSaveRequested);
root->start(freshly_activated); root->start(freshly_activated);
return true; return true;

View file

@ -2798,24 +2798,8 @@ bool DatabaseQueries::overwriteGmailAccount(const QSqlDatabase& db, const QStrin
"redirect_url = :redirect_url, refresh_token = :refresh_token , msg_limit = :msg_limit " "redirect_url = :redirect_url, refresh_token = :refresh_token , msg_limit = :msg_limit "
"WHERE id = :id;"); "WHERE id = :id;");
query.bindValue(QSL(":username"), username); query.bindValue(QSL(":username"), username);
#if defined(GMAIL_OFFICIAL_SUPPORT)
const QString official_app_id = TextFactory::decrypt(GMAIL_CLIENT_ID, OAUTH_DECRYPTION_KEY);
const QString official_app_key = TextFactory::decrypt(GMAIL_CLIENT_SECRET, OAUTH_DECRYPTION_KEY);
if (official_app_id == app_id) {
query.bindValue(QSL(":app_id"), {});
query.bindValue(QSL(":app_key"), {});
}
else {
query.bindValue(QSL(":app_id"), app_id);
query.bindValue(QSL(":app_key"), app_key);
}
#else
query.bindValue(QSL(":app_id"), app_id); query.bindValue(QSL(":app_id"), app_id);
query.bindValue(QSL(":app_key"), app_key); query.bindValue(QSL(":app_key"), app_key);
#endif
query.bindValue(QSL(":redirect_url"), redirect_url); query.bindValue(QSL(":redirect_url"), redirect_url);
query.bindValue(QSL(":refresh_token"), refresh_token); query.bindValue(QSL(":refresh_token"), refresh_token);
query.bindValue(QSL(":id"), account_id); query.bindValue(QSL(":id"), account_id);
@ -2842,24 +2826,8 @@ bool DatabaseQueries::createGmailAccount(const QSqlDatabase& db, int id_to_assig
"VALUES (:id, :username, :app_id, :app_key, :redirect_url, :refresh_token, :msg_limit);"); "VALUES (:id, :username, :app_id, :app_key, :redirect_url, :refresh_token, :msg_limit);");
q.bindValue(QSL(":id"), id_to_assign); q.bindValue(QSL(":id"), id_to_assign);
q.bindValue(QSL(":username"), username); q.bindValue(QSL(":username"), username);
#if defined(GMAIL_OFFICIAL_SUPPORT)
const QString official_app_id = TextFactory::decrypt(GMAIL_CLIENT_ID, OAUTH_DECRYPTION_KEY);
const QString official_app_key = TextFactory::decrypt(GMAIL_CLIENT_SECRET, OAUTH_DECRYPTION_KEY);
if (official_app_id == app_id) {
q.bindValue(QSL(":app_id"), {});
q.bindValue(QSL(":app_key"), {});
}
else {
q.bindValue(QSL(":app_id"), app_id);
q.bindValue(QSL(":app_key"), app_key);
}
#else
q.bindValue(QSL(":app_id"), app_id); q.bindValue(QSL(":app_id"), app_id);
q.bindValue(QSL(":app_key"), app_key); q.bindValue(QSL(":app_key"), app_key);
#endif
q.bindValue(QSL(":redirect_url"), redirect_url); q.bindValue(QSL(":redirect_url"), redirect_url);
q.bindValue(QSL(":refresh_token"), refresh_token); q.bindValue(QSL(":refresh_token"), refresh_token);
q.bindValue(QSL(":msg_limit"), batch_size <= 0 ? GMAIL_DEFAULT_BATCH_SIZE : batch_size); q.bindValue(QSL(":msg_limit"), batch_size <= 0 ? GMAIL_DEFAULT_BATCH_SIZE : batch_size);

View file

@ -54,6 +54,7 @@ OAuth2Service::OAuth2Service(const QString& auth_url, const QString& token_url,
m_clientId = client_id; m_clientId = client_id;
m_clientSecret = client_secret; m_clientSecret = client_secret;
m_clientSecretId = m_clientSecretSecret = QString();
m_scope = scope; m_scope = scope;
connect(&m_networkManager, &QNetworkAccessManager::finished, this, &OAuth2Service::tokenRequestFinished); connect(&m_networkManager, &QNetworkAccessManager::finished, this, &OAuth2Service::tokenRequestFinished);
@ -127,6 +128,22 @@ void OAuth2Service::timerEvent(QTimerEvent* event) {
QObject::timerEvent(event); QObject::timerEvent(event);
} }
QString OAuth2Service::clientSecretSecret() const {
return m_clientSecretSecret;
}
void OAuth2Service::setClientSecretSecret(const QString& client_secret_secret) {
m_clientSecretSecret = client_secret_secret;
}
QString OAuth2Service::clientSecretId() const {
return m_clientSecretId;
}
void OAuth2Service::setClientSecretId(const QString& client_secret_id) {
m_clientSecretId = client_secret_id;
}
QString OAuth2Service::id() const { QString OAuth2Service::id() const {
return m_id; return m_id;
} }
@ -145,8 +162,10 @@ void OAuth2Service::retrieveAccessToken(const QString& auth_code) {
"client_secret=%2&" "client_secret=%2&"
"code=%3&" "code=%3&"
"redirect_uri=%5&" "redirect_uri=%5&"
"grant_type=%4").arg(m_clientId, m_clientSecret, "grant_type=%4").arg(properClientId(),
auth_code, m_tokenGrantType, properClientSecret(),
auth_code,
m_tokenGrantType,
m_redirectionHandler->listenAddressPort()); m_redirectionHandler->listenAddressPort());
qDebugNN << LOGSEC_OAUTH << "Posting data for access token retrieval:" << QUOTE_W_SPACE_DOT(content); qDebugNN << LOGSEC_OAUTH << "Posting data for access token retrieval:" << QUOTE_W_SPACE_DOT(content);
@ -163,7 +182,10 @@ void OAuth2Service::refreshAccessToken(const QString& refresh_token) {
QString content = QString("client_id=%1&" QString content = QString("client_id=%1&"
"client_secret=%2&" "client_secret=%2&"
"refresh_token=%3&" "refresh_token=%3&"
"grant_type=%4").arg(m_clientId, m_clientSecret, real_refresh_token, QSL("refresh_token")); "grant_type=%4").arg(properClientId(),
properClientSecret(),
real_refresh_token,
QSL("refresh_token"));
qApp->showGuiMessage(tr("Logging in via OAuth 2.0..."), qApp->showGuiMessage(tr("Logging in via OAuth 2.0..."),
tr("Refreshing login tokens for '%1'...").arg(m_tokenUrl.toString()), tr("Refreshing login tokens for '%1'...").arg(m_tokenUrl.toString()),
@ -213,6 +235,18 @@ void OAuth2Service::tokenRequestFinished(QNetworkReply* network_reply) {
network_reply->deleteLater(); network_reply->deleteLater();
} }
QString OAuth2Service::properClientId() const {
return m_clientId.simplified().isEmpty()
? m_clientSecretId
: m_clientId;
}
QString OAuth2Service::properClientSecret() const {
return m_clientSecret.simplified().isEmpty()
? m_clientSecretSecret
: m_clientSecret;
}
QString OAuth2Service::accessToken() const { QString OAuth2Service::accessToken() const {
return m_accessToken; return m_accessToken;
} }
@ -326,7 +360,7 @@ void OAuth2Service::retrieveAuthCode() {
"response_type=code&" "response_type=code&"
"state=%4&" "state=%4&"
"prompt=consent&" "prompt=consent&"
"access_type=offline").arg(m_clientId, "access_type=offline").arg(properClientId(),
m_scope, m_scope,
m_redirectionHandler->listenAddressPort(), m_redirectionHandler->listenAddressPort(),
m_id); m_id);

View file

@ -71,6 +71,13 @@ class OAuth2Service : public QObject {
QString id() const; QString id() const;
void setId(const QString& id); void setId(const QString& id);
// Super secret fallback client ID/SECRET.
QString clientSecretId() const;
void setClientSecretId(const QString& client_secret_id);
QString clientSecretSecret() const;
void setClientSecretSecret(const QString& client_secret_secret);
signals: signals:
void tokensRetrieved(QString access_token, QString refresh_token, int expires_in); void tokensRetrieved(QString access_token, QString refresh_token, int expires_in);
void tokensRetrieveError(QString error, QString error_description); void tokensRetrieveError(QString error, QString error_description);
@ -103,6 +110,9 @@ class OAuth2Service : public QObject {
void tokenRequestFinished(QNetworkReply* network_reply); void tokenRequestFinished(QNetworkReply* network_reply);
private: private:
QString properClientId() const;
QString properClientSecret() const;
void timerEvent(QTimerEvent* event); void timerEvent(QTimerEvent* event);
private: private:
@ -114,6 +124,8 @@ class OAuth2Service : public QObject {
QString m_tokenGrantType; QString m_tokenGrantType;
QString m_clientId; QString m_clientId;
QString m_clientSecret; QString m_clientSecret;
QString m_clientSecretId;
QString m_clientSecretSecret;
QUrl m_tokenUrl; QUrl m_tokenUrl;
QString m_authUrl; QString m_authUrl;
QString m_scope; QString m_scope;

View file

@ -8,7 +8,7 @@
#include "services/abstract/serviceroot.h" #include "services/abstract/serviceroot.h"
FormAccountDetails::FormAccountDetails(const QIcon& icon, QWidget* parent) FormAccountDetails::FormAccountDetails(const QIcon& icon, QWidget* parent)
: QDialog(parent), m_proxyDetails(new NetworkProxyDetails(this)), m_account(nullptr) { : QDialog(parent), m_proxyDetails(new NetworkProxyDetails(this)), m_account(nullptr), m_creatingNew(false) {
m_ui.setupUi(this); m_ui.setupUi(this);
insertCustomTab(m_proxyDetails, tr("Network proxy"), 0); insertCustomTab(m_proxyDetails, tr("Network proxy"), 0);
@ -16,8 +16,19 @@ FormAccountDetails::FormAccountDetails(const QIcon& icon, QWidget* parent)
? qApp->icons()->fromTheme(QSL("emblem-system")) ? qApp->icons()->fromTheme(QSL("emblem-system"))
: icon); : icon);
createConnections(); createConnections();
}
m_proxyDetails->setProxy(QNetworkProxy()); void FormAccountDetails::apply() {
QSqlDatabase database = qApp->database()->connection(QSL("FormAccountDetails"));
if (m_creatingNew) {
m_account->setAccountId(DatabaseQueries::createBaseAccount(database, m_account->code()));
}
m_account->setNetworkProxy(m_proxyDetails->proxy());
// NOTE: We edit account common attributes here directly.
DatabaseQueries::editBaseAccount(database, m_account);
} }
void FormAccountDetails::insertCustomTab(QWidget* custom_tab, const QString& title, int index) { void FormAccountDetails::insertCustomTab(QWidget* custom_tab, const QString& title, int index) {
@ -32,13 +43,23 @@ void FormAccountDetails::clearTabs() {
m_ui.m_tabWidget->clear(); m_ui.m_tabWidget->clear();
} }
void FormAccountDetails::setEditableAccount(ServiceRoot* editable_account) { void FormAccountDetails::loadAccountData() {
setWindowTitle(tr("Edit account '%1'").arg(editable_account->title())); if (m_creatingNew) {
m_account = editable_account; setWindowTitle(tr("Add new account"));
if (m_account != nullptr) {
m_proxyDetails->setProxy(m_account->networkProxy());
} }
else {
setWindowTitle(tr("Edit account '%1'").arg(m_account->title()));
// Perform last-time operations before account is changed.
auto* cached_account = dynamic_cast<CacheForServiceRoot*>(m_account);
if (cached_account != nullptr) {
qWarningNN << LOGSEC_CORE << "Last-time account cache saving before account could be edited.";
cached_account->saveAllCachedData(true);
}
}
m_proxyDetails->setProxy(m_account->networkProxy());
} }
void FormAccountDetails::createConnections() { void FormAccountDetails::createConnections() {

View file

@ -31,15 +31,10 @@ class FormAccountDetails : public QDialog {
// Applies changes. // Applies changes.
// NOTE: This must be reimplemented in subclasses. Also, every // NOTE: This must be reimplemented in subclasses. Also, every
// subclass must call applyInternal() method as first statement. // subclass must call applyInternal() method as first statement.
virtual void apply() = 0; virtual void apply();
protected: protected:
// Performs some common operations and returns true if creating
// new account or false if editing existing account.
template<class T>
bool applyInternal();
void activateTab(int index); void activateTab(int index);
void clearTabs(); void clearTabs();
void insertCustomTab(QWidget* custom_tab, const QString& title, int index); void insertCustomTab(QWidget* custom_tab, const QString& title, int index);
@ -47,7 +42,7 @@ class FormAccountDetails : public QDialog {
// Sets the account which will be edited. // Sets the account which will be edited.
// NOTE: This must be reimplemented in subclasses. Also this // NOTE: This must be reimplemented in subclasses. Also this
// base implementation must be called first. // base implementation must be called first.
virtual void setEditableAccount(ServiceRoot* editable_account); virtual void loadAccountData();
private: private:
void createConnections(); void createConnections();
@ -56,44 +51,23 @@ class FormAccountDetails : public QDialog {
Ui::FormAccountDetails m_ui; Ui::FormAccountDetails m_ui;
NetworkProxyDetails* m_proxyDetails; NetworkProxyDetails* m_proxyDetails;
ServiceRoot* m_account; ServiceRoot* m_account;
bool m_creatingNew;
}; };
template<class T>
inline bool FormAccountDetails::applyInternal() {
if (m_account != nullptr) {
// Perform last-time operations before account is changed.
auto* cached_account = dynamic_cast<CacheForServiceRoot*>(m_account);
if (cached_account != nullptr) {
qWarningNN << LOGSEC_CORE << "Last-time account cache saving before account gets changed.";
cached_account->saveAllCachedData(true);
}
}
QSqlDatabase database = qApp->database()->connection(QSL("FormAccountDetails"));
bool creating = m_account == nullptr;
if (creating) {
m_account = new T();
m_account->setAccountId(DatabaseQueries::createBaseAccount(database, m_account->code()));
}
m_account->setNetworkProxy(m_proxyDetails->proxy());
// NOTE: We edit account common attributes here directly.
DatabaseQueries::editBaseAccount(database, m_account);
return creating;
}
template<class T> template<class T>
inline T* FormAccountDetails::addEditAccount(T* account_to_edit) { inline T* FormAccountDetails::addEditAccount(T* account_to_edit) {
if (account_to_edit == nullptr) { m_creatingNew = account_to_edit == nullptr;
setWindowTitle(tr("Add new account"));
if (m_creatingNew) {
m_account = new T();
} }
else { else {
setEditableAccount(static_cast<ServiceRoot*>(account_to_edit)); m_account = account_to_edit;
} }
// Load custom logic for account data loading.
loadAccountData();
if (exec() == QDialog::DialogCode::Accepted) { if (exec() == QDialog::DialogCode::Accepted) {
return account<T>(); return account<T>();
} }

View file

@ -18,7 +18,7 @@
ServiceRoot::ServiceRoot(RootItem* parent) ServiceRoot::ServiceRoot(RootItem* parent)
: RootItem(parent), m_recycleBin(new RecycleBin(this)), m_importantNode(new ImportantNode(this)), : RootItem(parent), m_recycleBin(new RecycleBin(this)), m_importantNode(new ImportantNode(this)),
m_labelsNode(new LabelsNode(this)), m_accountId(NO_PARENT_CATEGORY) { m_labelsNode(new LabelsNode(this)), m_accountId(NO_PARENT_CATEGORY), m_networkProxy(QNetworkProxy()) {
setKind(RootItem::Kind::ServiceRoot); setKind(RootItem::Kind::ServiceRoot);
setCreationDate(QDateTime::currentDateTime()); setCreationDate(QDateTime::currentDateTime());
} }

View file

@ -24,10 +24,10 @@ FormEditFeedlyAccount::FormEditFeedlyAccount(QWidget* parent)
} }
void FormEditFeedlyAccount::apply() { void FormEditFeedlyAccount::apply() {
bool editing_account = !applyInternal<FeedlyServiceRoot>(); FormAccountDetails::apply();
#if defined(FEEDLY_OFFICIAL_SUPPORT) #if defined(FEEDLY_OFFICIAL_SUPPORT)
if (!editing_account) { if (!m_creatingNew) {
// We transfer refresh token to avoid the need to login once more, // We transfer refresh token to avoid the need to login once more,
// then we delete testing OAuth service. // then we delete testing OAuth service.
account<FeedlyServiceRoot>()->network()->oauth()->setAccessToken(m_details->m_oauth->accessToken()); account<FeedlyServiceRoot>()->network()->oauth()->setAccessToken(m_details->m_oauth->accessToken());
@ -48,17 +48,17 @@ void FormEditFeedlyAccount::apply() {
account<FeedlyServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value()); account<FeedlyServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value());
account<FeedlyServiceRoot>()->network()->setDeveloperAccessToken(m_details->m_ui.m_txtDeveloperAccessToken->lineEdit()->text()); account<FeedlyServiceRoot>()->network()->setDeveloperAccessToken(m_details->m_ui.m_txtDeveloperAccessToken->lineEdit()->text());
account<FeedlyServiceRoot>()->saveAccountDataToDatabase(!editing_account); account<FeedlyServiceRoot>()->saveAccountDataToDatabase(m_creatingNew);
accept(); accept();
if (editing_account) { if (!m_creatingNew) {
account<FeedlyServiceRoot>()->completelyRemoveAllData(); account<FeedlyServiceRoot>()->completelyRemoveAllData();
account<FeedlyServiceRoot>()->syncIn(); account<FeedlyServiceRoot>()->syncIn();
} }
} }
void FormEditFeedlyAccount::setEditableAccount(ServiceRoot* editable_account) { void FormEditFeedlyAccount::loadAccountData() {
FormAccountDetails::setEditableAccount(editable_account); FormAccountDetails::loadAccountData();
#if defined(FEEDLY_OFFICIAL_SUPPORT) #if defined(FEEDLY_OFFICIAL_SUPPORT)
if (m_details->m_oauth != nullptr) { if (m_details->m_oauth != nullptr) {

View file

@ -18,7 +18,7 @@ class FormEditFeedlyAccount : public FormAccountDetails {
virtual void apply(); virtual void apply();
protected: protected:
virtual void setEditableAccount(ServiceRoot* editable_account); virtual void loadAccountData();
private slots: private slots:
void performTest(); void performTest();

View file

@ -166,17 +166,16 @@ bool GmailServiceRoot::supportsCategoryAdding() const {
} }
void GmailServiceRoot::start(bool freshly_activated) { void GmailServiceRoot::start(bool freshly_activated) {
Q_UNUSED(freshly_activated) if (!freshly_activated) {
loadFromDatabase();
loadCacheFromFile();
}
loadFromDatabase(); if (getSubTreeFeeds().isEmpty()) {
loadCacheFromFile();
if (childCount() <= 3) {
syncIn(); syncIn();
} }
else {
m_network->oauth()->login(); m_network->oauth()->login();
}
} }
QString GmailServiceRoot::code() const { QString GmailServiceRoot::code() const {
@ -185,7 +184,9 @@ QString GmailServiceRoot::code() const {
QString GmailServiceRoot::additionalTooltip() const { QString GmailServiceRoot::additionalTooltip() const {
return tr("Authentication status: %1\n" return tr("Authentication status: %1\n"
"Login tokens expiration: %2").arg(network()->oauth()->isFullyLoggedIn() ? tr("logged-in") : tr("NOT logged-in"), "Login tokens expiration: %2").arg(network()->oauth()->isFullyLoggedIn()
? tr("logged-in")
: tr("NOT logged-in"),
network()->oauth()->tokensExpireIn().isValid() ? network()->oauth()->tokensExpireIn().isValid() ?
network()->oauth()->tokensExpireIn().toString() : QSL("-")); network()->oauth()->tokensExpireIn().toString() : QSL("-"));
} }

View file

@ -20,57 +20,37 @@ FormEditGmailAccount::FormEditGmailAccount(QWidget* parent)
} }
void FormEditGmailAccount::apply() { void FormEditGmailAccount::apply() {
bool editing_account = !applyInternal<GmailServiceRoot>(); FormAccountDetails::apply();
if (!editing_account) { if (!m_creatingNew) {
// We transfer refresh token to avoid the need to login once more, // Disable "Cancel" button because all changes made to
// then we delete testing OAuth service. // existing account are always saved anyway.
account<GmailServiceRoot>()->network()->oauth()->setRefreshToken(m_details->m_oauth->refreshToken()); m_ui.m_buttonBox->button(QDialogButtonBox::StandardButton::Cancel)->setVisible(false);
account<GmailServiceRoot>()->network()->oauth()->setAccessToken(m_details->m_oauth->accessToken());
account<GmailServiceRoot>()->network()->oauth()->setTokensExpireIn(m_details->m_oauth->tokensExpireIn());
m_details->m_oauth->logout(true);
m_details->m_oauth->deleteLater();
} }
#if defined(GMAIL_OFFICIAL_SUPPORT) // Make sure that the data copied from GUI are used for brand new login.
if (m_details->m_ui.m_txtAppId->lineEdit()->text().isEmpty() || account<GmailServiceRoot>()->network()->oauth()->logout(false);
m_details->m_ui.m_txtAppKey->lineEdit()->text().isEmpty()) {
account<GmailServiceRoot>()->network()->oauth()->setClientId(TextFactory::decrypt(GMAIL_CLIENT_ID,
OAUTH_DECRYPTION_KEY));
account<GmailServiceRoot>()->network()->oauth()->setClientSecret(TextFactory::decrypt(GMAIL_CLIENT_SECRET,
OAUTH_DECRYPTION_KEY));
}
else {
#endif
account<GmailServiceRoot>()->network()->oauth()->setClientId(m_details->m_ui.m_txtAppId->lineEdit()->text()); account<GmailServiceRoot>()->network()->oauth()->setClientId(m_details->m_ui.m_txtAppId->lineEdit()->text());
account<GmailServiceRoot>()->network()->oauth()->setClientSecret(m_details->m_ui.m_txtAppKey->lineEdit()->text()); account<GmailServiceRoot>()->network()->oauth()->setClientSecret(m_details->m_ui.m_txtAppKey->lineEdit()->text());
#if defined(GMAIL_OFFICIAL_SUPPORT)
}
#endif
account<GmailServiceRoot>()->network()->oauth()->setRedirectUrl(m_details->m_ui.m_txtRedirectUrl->lineEdit()->text()); account<GmailServiceRoot>()->network()->oauth()->setRedirectUrl(m_details->m_ui.m_txtRedirectUrl->lineEdit()->text());
account<GmailServiceRoot>()->network()->setUsername(m_details->m_ui.m_txtUsername->lineEdit()->text()); account<GmailServiceRoot>()->network()->setUsername(m_details->m_ui.m_txtUsername->lineEdit()->text());
account<GmailServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value()); account<GmailServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value());
account<GmailServiceRoot>()->saveAccountDataToDatabase(!editing_account); account<GmailServiceRoot>()->saveAccountDataToDatabase(m_creatingNew);
accept(); accept();
if (editing_account) { if (!m_creatingNew) {
account<GmailServiceRoot>()->completelyRemoveAllData(); account<GmailServiceRoot>()->completelyRemoveAllData();
account<GmailServiceRoot>()->syncIn();
// Account data are erased, it is similar to situation
// where we start the account after it was freshly added.
account<GmailServiceRoot>()->start(true);
} }
} }
void FormEditGmailAccount::setEditableAccount(ServiceRoot* editable_account) { void FormEditGmailAccount::loadAccountData() {
FormAccountDetails::setEditableAccount(editable_account); FormAccountDetails::loadAccountData();
if (m_details->m_oauth != nullptr) {
// We will use live OAuth service for testing.
m_details->m_oauth->logout(true);
m_details->m_oauth->deleteLater();
}
m_details->m_oauth = account<GmailServiceRoot>()->network()->oauth(); m_details->m_oauth = account<GmailServiceRoot>()->network()->oauth();
m_details->hookNetwork(); m_details->hookNetwork();

View file

@ -20,7 +20,7 @@ class FormEditGmailAccount : public FormAccountDetails {
virtual void apply(); virtual void apply();
protected: protected:
virtual void setEditableAccount(ServiceRoot* editable_account); virtual void loadAccountData();
private: private:
GmailAccountDetails* m_details; GmailAccountDetails* m_details;

View file

@ -10,8 +10,7 @@
#include "services/gmail/network/gmailnetworkfactory.h" #include "services/gmail/network/gmailnetworkfactory.h"
GmailAccountDetails::GmailAccountDetails(QWidget* parent) GmailAccountDetails::GmailAccountDetails(QWidget* parent)
: QWidget(parent), m_oauth(new OAuth2Service(GMAIL_OAUTH_AUTH_URL, GMAIL_OAUTH_TOKEN_URL, : QWidget(parent), m_oauth(nullptr) {
{}, {}, GMAIL_OAUTH_SCOPE, this)) {
m_ui.setupUi(this); m_ui.setupUi(this);
GuiUtilities::setLabelAsNotice(*m_ui.m_lblInfo, true); GuiUtilities::setLabelAsNotice(*m_ui.m_lblInfo, true);
@ -52,10 +51,7 @@ GmailAccountDetails::GmailAccountDetails(QWidget* parent)
emit m_ui.m_txtUsername->lineEdit()->textChanged(m_ui.m_txtUsername->lineEdit()->text()); emit m_ui.m_txtUsername->lineEdit()->textChanged(m_ui.m_txtUsername->lineEdit()->text());
emit m_ui.m_txtAppId->lineEdit()->textChanged(m_ui.m_txtAppId->lineEdit()->text()); emit m_ui.m_txtAppId->lineEdit()->textChanged(m_ui.m_txtAppId->lineEdit()->text());
emit m_ui.m_txtAppKey->lineEdit()->textChanged(m_ui.m_txtAppKey->lineEdit()->text()); emit m_ui.m_txtAppKey->lineEdit()->textChanged(m_ui.m_txtAppKey->lineEdit()->text());
emit m_ui.m_txtRedirectUrl->lineEdit()->textChanged(m_ui.m_txtAppKey->lineEdit()->text());
m_ui.m_txtRedirectUrl->lineEdit()->setText(QString(OAUTH_REDIRECT_URI) +
QL1C(':') +
QString::number(OAUTH_REDIRECT_URI_PORT));
hookNetwork(); hookNetwork();
} }

View file

@ -32,11 +32,7 @@ class GmailAccountDetails : public QWidget {
private: private:
Ui::GmailAccountDetails m_ui; Ui::GmailAccountDetails m_ui;
// Testing OAuth service. This object is not ever copied // Pointer to live OAuth.
// to new living account instance, instead only its properties
// like tokens are copied.
// If editing existing account, then the pointer points
// directly to existing OAuth from the account.
OAuth2Service* m_oauth; OAuth2Service* m_oauth;
}; };

View file

@ -118,6 +118,15 @@ QString GmailNetworkFactory::sendEmail(Mimesis::Message msg, const QNetworkProxy
} }
void GmailNetworkFactory::initializeOauth() { void GmailNetworkFactory::initializeOauth() {
#if defined(GMAIL_OFFICIAL_SUPPORT)
m_oauth2->setClientSecretId(TextFactory::decrypt(GMAIL_CLIENT_ID, OAUTH_DECRYPTION_KEY));
m_oauth2->setClientSecretSecret(TextFactory::decrypt(GMAIL_CLIENT_SECRET, OAUTH_DECRYPTION_KEY));
#endif
m_oauth2->setRedirectUrl(QString(OAUTH_REDIRECT_URI) +
QL1C(':') +
QString::number(OAUTH_REDIRECT_URI_PORT));
connect(m_oauth2, &OAuth2Service::tokensRetrieveError, this, &GmailNetworkFactory::onTokensError); connect(m_oauth2, &OAuth2Service::tokensRetrieveError, this, &GmailNetworkFactory::onTokensError);
connect(m_oauth2, &OAuth2Service::authFailed, this, &GmailNetworkFactory::onAuthFailed); connect(m_oauth2, &OAuth2Service::authFailed, this, &GmailNetworkFactory::onAuthFailed);
connect(m_oauth2, &OAuth2Service::tokensRetrieved, this, [this](QString access_token, QString refresh_token, int expires_in) { connect(m_oauth2, &OAuth2Service::tokensRetrieved, this, [this](QString access_token, QString refresh_token, int expires_in) {

View file

@ -21,7 +21,7 @@ FormEditGreaderAccount::FormEditGreaderAccount(QWidget* parent)
} }
void FormEditGreaderAccount::apply() { void FormEditGreaderAccount::apply() {
bool editing_account = !applyInternal<GreaderServiceRoot>(); FormAccountDetails::apply();
account<GreaderServiceRoot>()->network()->setBaseUrl(m_details->m_ui.m_txtUrl->lineEdit()->text()); account<GreaderServiceRoot>()->network()->setBaseUrl(m_details->m_ui.m_txtUrl->lineEdit()->text());
account<GreaderServiceRoot>()->network()->setUsername(m_details->m_ui.m_txtUsername->lineEdit()->text()); account<GreaderServiceRoot>()->network()->setUsername(m_details->m_ui.m_txtUsername->lineEdit()->text());
@ -29,17 +29,17 @@ void FormEditGreaderAccount::apply() {
account<GreaderServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value()); account<GreaderServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value());
account<GreaderServiceRoot>()->network()->setService(m_details->service()); account<GreaderServiceRoot>()->network()->setService(m_details->service());
account<GreaderServiceRoot>()->saveAccountDataToDatabase(!editing_account); account<GreaderServiceRoot>()->saveAccountDataToDatabase(m_creatingNew);
accept(); accept();
if (editing_account) { if (!m_creatingNew) {
account<GreaderServiceRoot>()->completelyRemoveAllData(); account<GreaderServiceRoot>()->completelyRemoveAllData();
account<GreaderServiceRoot>()->syncIn(); account<GreaderServiceRoot>()->syncIn();
} }
} }
void FormEditGreaderAccount::setEditableAccount(ServiceRoot* editable_account) { void FormEditGreaderAccount::loadAccountData() {
FormAccountDetails::setEditableAccount(editable_account); FormAccountDetails::loadAccountData();
GreaderServiceRoot* existing_root = account<GreaderServiceRoot>(); GreaderServiceRoot* existing_root = account<GreaderServiceRoot>();

View file

@ -18,7 +18,7 @@ class FormEditGreaderAccount : public FormAccountDetails {
virtual void apply(); virtual void apply();
protected: protected:
virtual void setEditableAccount(ServiceRoot* editable_account); virtual void loadAccountData();
private slots: private slots:
void performTest(); void performTest();

View file

@ -23,9 +23,9 @@ FormEditInoreaderAccount::FormEditInoreaderAccount(QWidget* parent)
} }
void FormEditInoreaderAccount::apply() { void FormEditInoreaderAccount::apply() {
bool editing_account = !applyInternal<InoreaderServiceRoot>(); FormAccountDetails::apply();
if (!editing_account) { if (m_creatingNew) {
// We transfer refresh token to avoid the need to login once more, // We transfer refresh token to avoid the need to login once more,
// then we delete testing OAuth service. // then we delete testing OAuth service.
account<InoreaderServiceRoot>()->network()->oauth()->setRefreshToken(m_details->m_oauth->refreshToken()); account<InoreaderServiceRoot>()->network()->oauth()->setRefreshToken(m_details->m_oauth->refreshToken());
@ -42,17 +42,17 @@ void FormEditInoreaderAccount::apply() {
account<InoreaderServiceRoot>()->network()->setUsername(m_details->m_ui.m_txtUsername->lineEdit()->text()); account<InoreaderServiceRoot>()->network()->setUsername(m_details->m_ui.m_txtUsername->lineEdit()->text());
account<InoreaderServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value()); account<InoreaderServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value());
account<InoreaderServiceRoot>()->saveAccountDataToDatabase(!editing_account); account<InoreaderServiceRoot>()->saveAccountDataToDatabase(m_creatingNew);
accept(); accept();
if (editing_account) { if (!m_creatingNew) {
account<InoreaderServiceRoot>()->completelyRemoveAllData(); account<InoreaderServiceRoot>()->completelyRemoveAllData();
account<InoreaderServiceRoot>()->syncIn(); account<InoreaderServiceRoot>()->syncIn();
} }
} }
void FormEditInoreaderAccount::setEditableAccount(ServiceRoot* editable_account) { void FormEditInoreaderAccount::loadAccountData() {
FormAccountDetails::setEditableAccount(editable_account); FormAccountDetails::loadAccountData();
if (m_details->m_oauth != nullptr) { if (m_details->m_oauth != nullptr) {
// We will use live OAuth service for testing. // We will use live OAuth service for testing.

View file

@ -18,7 +18,7 @@ class FormEditInoreaderAccount : public FormAccountDetails {
virtual void apply(); virtual void apply();
protected: protected:
virtual void setEditableAccount(ServiceRoot* editable_account); virtual void loadAccountData();
private: private:
InoreaderAccountDetails* m_details; InoreaderAccountDetails* m_details;

View file

@ -21,7 +21,7 @@ FormEditOwnCloudAccount::FormEditOwnCloudAccount(QWidget* parent)
} }
void FormEditOwnCloudAccount::apply() { void FormEditOwnCloudAccount::apply() {
bool editing_account = !applyInternal<OwnCloudServiceRoot>(); FormAccountDetails::apply();
account<OwnCloudServiceRoot>()->network()->setUrl(m_details->m_ui.m_txtUrl->lineEdit()->text()); account<OwnCloudServiceRoot>()->network()->setUrl(m_details->m_ui.m_txtUrl->lineEdit()->text());
account<OwnCloudServiceRoot>()->network()->setAuthUsername(m_details->m_ui.m_txtUsername->lineEdit()->text()); account<OwnCloudServiceRoot>()->network()->setAuthUsername(m_details->m_ui.m_txtUsername->lineEdit()->text());
@ -30,17 +30,17 @@ void FormEditOwnCloudAccount::apply() {
account<OwnCloudServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value()); account<OwnCloudServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value());
account<OwnCloudServiceRoot>()->network()->setDownloadOnlyUnreadMessages(m_details->m_ui.m_checkDownloadOnlyUnreadMessages->isChecked()); account<OwnCloudServiceRoot>()->network()->setDownloadOnlyUnreadMessages(m_details->m_ui.m_checkDownloadOnlyUnreadMessages->isChecked());
account<OwnCloudServiceRoot>()->saveAccountDataToDatabase(!editing_account); account<OwnCloudServiceRoot>()->saveAccountDataToDatabase(m_creatingNew);
accept(); accept();
if (editing_account) { if (!m_creatingNew) {
account<OwnCloudServiceRoot>()->completelyRemoveAllData(); account<OwnCloudServiceRoot>()->completelyRemoveAllData();
account<OwnCloudServiceRoot>()->syncIn(); account<OwnCloudServiceRoot>()->syncIn();
} }
} }
void FormEditOwnCloudAccount::setEditableAccount(ServiceRoot* editable_account) { void FormEditOwnCloudAccount::loadAccountData() {
FormAccountDetails::setEditableAccount(editable_account); FormAccountDetails::loadAccountData();
OwnCloudServiceRoot* existing_root = account<OwnCloudServiceRoot>(); OwnCloudServiceRoot* existing_root = account<OwnCloudServiceRoot>();

View file

@ -18,7 +18,7 @@ class FormEditOwnCloudAccount : public FormAccountDetails {
virtual void apply(); virtual void apply();
protected: protected:
virtual void setEditableAccount(ServiceRoot* editable_account); virtual void loadAccountData();
private slots: private slots:
void performTest(); void performTest();

View file

@ -12,6 +12,6 @@ FormEditStandardAccount::FormEditStandardAccount(QWidget* parent)
: FormAccountDetails(qApp->icons()->fromTheme(QSL("rssguard")), parent) {} : FormAccountDetails(qApp->icons()->fromTheme(QSL("rssguard")), parent) {}
void FormEditStandardAccount::apply() { void FormEditStandardAccount::apply() {
applyInternal<StandardServiceRoot>(); FormAccountDetails::apply();
accept(); accept();
} }

View file

@ -18,7 +18,7 @@ FormEditTtRssAccount::FormEditTtRssAccount(QWidget* parent)
} }
void FormEditTtRssAccount::apply() { void FormEditTtRssAccount::apply() {
bool editing_account = !applyInternal<TtRssServiceRoot>(); FormAccountDetails::apply();
account<TtRssServiceRoot>()->network()->setUrl(m_details->m_ui.m_txtUrl->lineEdit()->text()); account<TtRssServiceRoot>()->network()->setUrl(m_details->m_ui.m_txtUrl->lineEdit()->text());
account<TtRssServiceRoot>()->network()->setUsername(m_details->m_ui.m_txtUsername->lineEdit()->text()); account<TtRssServiceRoot>()->network()->setUsername(m_details->m_ui.m_txtUsername->lineEdit()->text());
@ -29,20 +29,20 @@ void FormEditTtRssAccount::apply() {
account<TtRssServiceRoot>()->network()->setForceServerSideUpdate(m_details->m_ui.m_checkServerSideUpdate->isChecked()); account<TtRssServiceRoot>()->network()->setForceServerSideUpdate(m_details->m_ui.m_checkServerSideUpdate->isChecked());
account<TtRssServiceRoot>()->network()->setDownloadOnlyUnreadMessages(m_details->m_ui.m_checkDownloadOnlyUnreadMessages->isChecked()); account<TtRssServiceRoot>()->network()->setDownloadOnlyUnreadMessages(m_details->m_ui.m_checkDownloadOnlyUnreadMessages->isChecked());
account<TtRssServiceRoot>()->saveAccountDataToDatabase(!editing_account); account<TtRssServiceRoot>()->saveAccountDataToDatabase(m_creatingNew);
accept(); accept();
if (editing_account) { if (!m_creatingNew) {
account<TtRssServiceRoot>()->network()->logout(m_account->networkProxy()); account<TtRssServiceRoot>()->network()->logout(m_account->networkProxy());
account<TtRssServiceRoot>()->completelyRemoveAllData(); account<TtRssServiceRoot>()->completelyRemoveAllData();
account<TtRssServiceRoot>()->syncIn(); account<TtRssServiceRoot>()->syncIn();
} }
} }
void FormEditTtRssAccount::setEditableAccount(ServiceRoot* editable_account) { void FormEditTtRssAccount::loadAccountData() {
FormAccountDetails::setEditableAccount(editable_account); FormAccountDetails::loadAccountData();
TtRssServiceRoot* existing_root = qobject_cast<TtRssServiceRoot*>(editable_account); TtRssServiceRoot* existing_root = account<TtRssServiceRoot>();
m_details->m_ui.m_gbHttpAuthentication->setChecked(existing_root->network()->authIsUsed()); m_details->m_ui.m_gbHttpAuthentication->setChecked(existing_root->network()->authIsUsed());
m_details->m_ui.m_txtHttpPassword->lineEdit()->setText(existing_root->network()->authPassword()); m_details->m_ui.m_txtHttpPassword->lineEdit()->setText(existing_root->network()->authPassword());

View file

@ -19,7 +19,7 @@ class FormEditTtRssAccount : public FormAccountDetails {
virtual void apply(); virtual void apply();
protected: protected:
virtual void setEditableAccount(ServiceRoot* editable_account); virtual void loadAccountData();
private slots: private slots:
void performTest(); void performTest();