massive work, enhanced oauth2 post-login lambdas, simplified interfaces for acc editing
This commit is contained in:
parent
0a588f7b5e
commit
ee5de37805
@ -47,7 +47,8 @@ OAuth2Service::OAuth2Service(const QString& auth_url, const QString& token_url,
|
||||
const QString& client_secret, const QString& scope, QObject* parent)
|
||||
: QObject(parent),
|
||||
m_id(QString::number(QRandomGenerator::global()->generate())), m_timerId(-1),
|
||||
m_redirectionHandler(new OAuthHttpHandler(tr("You can close this window now. Go back to %1.").arg(APP_NAME), this)) {
|
||||
m_redirectionHandler(new OAuthHttpHandler(tr("You can close this window now. Go back to %1.").arg(APP_NAME), this)),
|
||||
m_functorOnLogin({}) {
|
||||
m_tokenGrantType = QSL("authorization_code");
|
||||
m_tokenUrl = QUrl(token_url);
|
||||
m_authUrl = auth_url;
|
||||
@ -229,6 +230,7 @@ void OAuth2Service::tokenRequestFinished(QNetworkReply* network_reply) {
|
||||
<< "Obtained refresh token" << QUOTE_W_SPACE(refreshToken())
|
||||
<< "- expires on date/time" << QUOTE_W_SPACE_DOT(tokensExpireIn());
|
||||
|
||||
m_functorOnLogin();
|
||||
emit tokensRetrieved(accessToken(), refreshToken(), expires);
|
||||
}
|
||||
|
||||
@ -297,7 +299,9 @@ void OAuth2Service::setRefreshToken(const QString& refresh_token) {
|
||||
startRefreshTimer();
|
||||
}
|
||||
|
||||
bool OAuth2Service::login() {
|
||||
bool OAuth2Service::login(const std::function<void()>& functor_when_logged_in) {
|
||||
m_functorOnLogin = {};
|
||||
|
||||
if (!m_redirectionHandler->isListening()) {
|
||||
qCriticalNN << LOGSEC_OAUTH
|
||||
<< "Cannot log-in because OAuth redirection handler is not listening.";
|
||||
@ -312,6 +316,8 @@ bool OAuth2Service::login() {
|
||||
bool did_token_expire = tokensExpireIn().isNull() || tokensExpireIn() < QDateTime::currentDateTime().addSecs(-120);
|
||||
bool does_token_exist = !refreshToken().isEmpty();
|
||||
|
||||
m_functorOnLogin = functor_when_logged_in;
|
||||
|
||||
// We refresh current tokens only if:
|
||||
// 1. We have some existing refresh token.
|
||||
// AND
|
||||
@ -325,6 +331,7 @@ bool OAuth2Service::login() {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
functor_when_logged_in();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -26,11 +26,14 @@
|
||||
#define OAUTH2SERVICE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
|
||||
#include "network-web/oauthhttphandler.h"
|
||||
#include "network-web/silentnetworkaccessmanager.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
class OAuth2Service : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
@ -96,10 +99,7 @@ class OAuth2Service : public QObject {
|
||||
//
|
||||
// Returns true, if user is already logged in (final state).
|
||||
// Returns false, if user is NOT logged in (asynchronous flow).
|
||||
//
|
||||
// NOTE: This can be called ONLY on main GUI thread,
|
||||
// because widgets may be displayed.
|
||||
bool login();
|
||||
bool login(const std::function<void()>& functor_when_logged_in = {});
|
||||
|
||||
// Removes all state data and stops redirection handler.
|
||||
void logout(bool stop_redirection_handler = true);
|
||||
@ -131,6 +131,7 @@ class OAuth2Service : public QObject {
|
||||
QString m_scope;
|
||||
SilentNetworkAccessManager m_networkManager;
|
||||
OAuthHttpHandler* m_redirectionHandler;
|
||||
std::function<void()> m_functorOnLogin;
|
||||
};
|
||||
|
||||
#endif // OAUTH2SERVICE_H
|
||||
|
@ -390,6 +390,7 @@ void ServiceRoot::syncIn() {
|
||||
|
||||
setIcon(original_icon);
|
||||
itemChanged(getSubTree());
|
||||
requestItemExpand({ this }, true);
|
||||
}
|
||||
|
||||
void ServiceRoot::performInitialAssembly(const Assignment& categories, const Assignment& feeds, const QList<Label*>& labels) {
|
||||
|
@ -22,12 +22,6 @@ FormEditGmailAccount::FormEditGmailAccount(QWidget* parent)
|
||||
void FormEditGmailAccount::apply() {
|
||||
FormAccountDetails::apply();
|
||||
|
||||
if (!m_creatingNew) {
|
||||
// Disable "Cancel" button because all changes made to
|
||||
// existing account are always saved anyway.
|
||||
m_ui.m_buttonBox->button(QDialogButtonBox::StandardButton::Cancel)->setVisible(false);
|
||||
}
|
||||
|
||||
// Make sure that the data copied from GUI are used for brand new login.
|
||||
account<GmailServiceRoot>()->network()->oauth()->logout(false);
|
||||
account<GmailServiceRoot>()->network()->oauth()->setClientId(m_details->m_ui.m_txtAppId->lineEdit()->text());
|
||||
@ -42,9 +36,6 @@ void FormEditGmailAccount::apply() {
|
||||
|
||||
if (!m_creatingNew) {
|
||||
account<GmailServiceRoot>()->completelyRemoveAllData();
|
||||
|
||||
// Account data are erased, it is similar to situation
|
||||
// where we start the account after it was freshly added.
|
||||
account<GmailServiceRoot>()->start(true);
|
||||
}
|
||||
}
|
||||
@ -52,6 +43,12 @@ void FormEditGmailAccount::apply() {
|
||||
void FormEditGmailAccount::loadAccountData() {
|
||||
FormAccountDetails::loadAccountData();
|
||||
|
||||
if (!m_creatingNew) {
|
||||
// Disable "Cancel" button because all changes made to
|
||||
// existing account are always saved anyway.
|
||||
m_ui.m_buttonBox->button(QDialogButtonBox::StandardButton::Cancel)->setVisible(false);
|
||||
}
|
||||
|
||||
m_details->m_oauth = account<GmailServiceRoot>()->network()->oauth();
|
||||
m_details->hookNetwork();
|
||||
|
||||
|
@ -58,21 +58,8 @@ GmailAccountDetails::GmailAccountDetails(QWidget* parent)
|
||||
|
||||
void GmailAccountDetails::testSetup() {
|
||||
m_oauth->logout();
|
||||
|
||||
#if defined(GMAIL_OFFICIAL_SUPPORT)
|
||||
if (m_ui.m_txtAppId->lineEdit()->text().isEmpty() || m_ui.m_txtAppKey->lineEdit()->text().isEmpty()) {
|
||||
m_oauth->setClientId(TextFactory::decrypt(GMAIL_CLIENT_ID, OAUTH_DECRYPTION_KEY));
|
||||
m_oauth->setClientSecret(TextFactory::decrypt(GMAIL_CLIENT_SECRET, OAUTH_DECRYPTION_KEY));
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
m_oauth->setClientId(m_ui.m_txtAppId->lineEdit()->text());
|
||||
m_oauth->setClientSecret(m_ui.m_txtAppKey->lineEdit()->text());
|
||||
|
||||
#if defined(GMAIL_OFFICIAL_SUPPORT)
|
||||
}
|
||||
#endif
|
||||
|
||||
m_oauth->setRedirectUrl(m_ui.m_txtRedirectUrl->lineEdit()->text());
|
||||
|
||||
if (m_oauth->login()) {
|
||||
|
@ -51,11 +51,13 @@ bool GreaderServiceRoot::deleteViaGui() {
|
||||
}
|
||||
|
||||
void GreaderServiceRoot::start(bool freshly_activated) {
|
||||
Q_UNUSED(freshly_activated)
|
||||
loadFromDatabase();
|
||||
loadCacheFromFile();
|
||||
if (!freshly_activated) {
|
||||
loadFromDatabase();
|
||||
loadCacheFromFile();
|
||||
|
||||
if (childCount() <= 3) {
|
||||
}
|
||||
|
||||
if (getSubTreeFeeds().isEmpty()) {
|
||||
syncIn();
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ void FormEditGreaderAccount::apply() {
|
||||
|
||||
if (!m_creatingNew) {
|
||||
account<GreaderServiceRoot>()->completelyRemoveAllData();
|
||||
account<GreaderServiceRoot>()->syncIn();
|
||||
account<GreaderServiceRoot>()->start(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,6 @@
|
||||
#define INOREADER_OAUTH_AUTH_URL "https://www.inoreader.com/oauth2/auth"
|
||||
#define INOREADER_REG_API_URL "https://www.inoreader.com/developers/register-app"
|
||||
|
||||
#define INOREADER_OAUTH_CLI_ID "999999019"
|
||||
#define INOREADER_OAUTH_CLI_KEY "k4bkOJ5Jj1erc52tmniluKtU6lZdNoZc"
|
||||
|
||||
#define INOREADER_REFRESH_TOKEN_KEY "refresh_token"
|
||||
#define INOREADER_ACCESS_TOKEN_KEY "access_token"
|
||||
|
||||
|
@ -25,16 +25,13 @@ FormEditInoreaderAccount::FormEditInoreaderAccount(QWidget* parent)
|
||||
void FormEditInoreaderAccount::apply() {
|
||||
FormAccountDetails::apply();
|
||||
|
||||
if (m_creatingNew) {
|
||||
// We transfer refresh token to avoid the need to login once more,
|
||||
// then we delete testing OAuth service.
|
||||
account<InoreaderServiceRoot>()->network()->oauth()->setRefreshToken(m_details->m_oauth->refreshToken());
|
||||
account<InoreaderServiceRoot>()->network()->oauth()->setAccessToken(m_details->m_oauth->accessToken());
|
||||
account<InoreaderServiceRoot>()->network()->oauth()->setTokensExpireIn(m_details->m_oauth->tokensExpireIn());
|
||||
m_details->m_oauth->logout(true);
|
||||
m_details->m_oauth->deleteLater();
|
||||
if (!m_creatingNew) {
|
||||
// Disable "Cancel" button because all changes made to
|
||||
// existing account are always saved anyway.
|
||||
m_ui.m_buttonBox->button(QDialogButtonBox::StandardButton::Cancel)->setVisible(false);
|
||||
}
|
||||
|
||||
account<InoreaderServiceRoot>()->network()->oauth()->logout(false);
|
||||
account<InoreaderServiceRoot>()->network()->oauth()->setClientId(m_details->m_ui.m_txtAppId->lineEdit()->text());
|
||||
account<InoreaderServiceRoot>()->network()->oauth()->setClientSecret(m_details->m_ui.m_txtAppKey->lineEdit()->text());
|
||||
account<InoreaderServiceRoot>()->network()->oauth()->setRedirectUrl(m_details->m_ui.m_txtRedirectUrl->lineEdit()->text());
|
||||
@ -47,18 +44,17 @@ void FormEditInoreaderAccount::apply() {
|
||||
|
||||
if (!m_creatingNew) {
|
||||
account<InoreaderServiceRoot>()->completelyRemoveAllData();
|
||||
account<InoreaderServiceRoot>()->syncIn();
|
||||
account<InoreaderServiceRoot>()->start(true);
|
||||
}
|
||||
}
|
||||
|
||||
void FormEditInoreaderAccount::loadAccountData() {
|
||||
FormAccountDetails::loadAccountData();
|
||||
|
||||
if (m_details->m_oauth != nullptr) {
|
||||
// We will use live OAuth service for testing.
|
||||
m_details->m_oauth->logout(true);
|
||||
delete m_details->m_oauth;
|
||||
m_details->m_oauth = nullptr;
|
||||
if (!m_creatingNew) {
|
||||
// Disable "Cancel" button because all changes made to
|
||||
// existing account are always saved anyway.
|
||||
m_ui.m_buttonBox->button(QDialogButtonBox::StandardButton::Cancel)->setVisible(false);
|
||||
}
|
||||
|
||||
m_details->m_oauth = account<InoreaderServiceRoot>()->network()->oauth();
|
||||
|
@ -10,17 +10,20 @@
|
||||
#include "services/inoreader/network/inoreadernetworkfactory.h"
|
||||
|
||||
InoreaderAccountDetails::InoreaderAccountDetails(QWidget* parent)
|
||||
: QWidget(parent), m_oauth(new OAuth2Service(INOREADER_OAUTH_AUTH_URL, INOREADER_OAUTH_TOKEN_URL,
|
||||
{}, {}, INOREADER_OAUTH_SCOPE, this)) {
|
||||
: QWidget(parent), m_oauth(nullptr) {
|
||||
m_ui.setupUi(this);
|
||||
|
||||
GuiUtilities::setLabelAsNotice(*m_ui.m_lblInfo, true);
|
||||
|
||||
m_ui.m_lblInfo->setText(tr("Specified redirect URL must start with \"http://localhost\" and "
|
||||
"must be configured in your OAuth \"application\".\n\n"
|
||||
"It is highly recommended to create your own \"App ID\". "
|
||||
"Because predefined one may be limited due to usage quotas if used by "
|
||||
"too many users simultaneously."));
|
||||
#if defined(INOREADER_OFFICIAL_SUPPORT)
|
||||
m_ui.m_lblInfo->setText(tr("There are some preconfigured OAuth tokens so you do not have to fill in your "
|
||||
"client ID/secret, but it is strongly recommended to obtain your "
|
||||
"own as it preconfigured tokens have limited global usage quota. If you wash "
|
||||
"to use preconfigured tokens, simply leave those fields empty and make sure "
|
||||
"to leave default value of redirect URL."));
|
||||
#else
|
||||
m_ui.m_lblInfo->setText(tr("You have to fill in your client ID/secret and also fill in correct redirect URL."));
|
||||
#endif
|
||||
|
||||
m_ui.m_lblTestResult->setStatus(WidgetWithStatus::StatusType::Information,
|
||||
tr("Not tested yet."),
|
||||
@ -46,12 +49,9 @@ InoreaderAccountDetails::InoreaderAccountDetails(QWidget* parent)
|
||||
m_ui.m_spinLimitMessages->setMaximum(INOREADER_MAX_BATCH_SIZE);
|
||||
|
||||
emit m_ui.m_txtUsername->lineEdit()->textChanged(m_ui.m_txtUsername->lineEdit()->text());
|
||||
|
||||
m_ui.m_txtAppId->lineEdit()->setText(INOREADER_OAUTH_CLI_ID);
|
||||
m_ui.m_txtAppKey->lineEdit()->setText(INOREADER_OAUTH_CLI_KEY);
|
||||
m_ui.m_txtRedirectUrl->lineEdit()->setText(QString(OAUTH_REDIRECT_URI) +
|
||||
QL1C(':') +
|
||||
QString::number(OAUTH_REDIRECT_URI_PORT));
|
||||
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_txtRedirectUrl->lineEdit()->textChanged(m_ui.m_txtAppKey->lineEdit()->text());
|
||||
|
||||
hookNetwork();
|
||||
}
|
||||
@ -113,7 +113,11 @@ void InoreaderAccountDetails::checkOAuthValue(const QString& value) {
|
||||
|
||||
if (line_edit != nullptr) {
|
||||
if (value.isEmpty()) {
|
||||
#if defined(INOREADER_OFFICIAL_SUPPORT)
|
||||
line_edit->setStatus(WidgetWithStatus::StatusType::Ok, tr("Preconfigured client ID/secret will be used."));
|
||||
#else
|
||||
line_edit->setStatus(WidgetWithStatus::StatusType::Error, tr("Empty value is entered."));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
line_edit->setStatus(WidgetWithStatus::StatusType::Ok, tr("Some value is entered."));
|
||||
|
@ -94,16 +94,15 @@ bool InoreaderServiceRoot::supportsCategoryAdding() const {
|
||||
}
|
||||
|
||||
void InoreaderServiceRoot::start(bool freshly_activated) {
|
||||
Q_UNUSED(freshly_activated)
|
||||
|
||||
loadFromDatabase();
|
||||
loadCacheFromFile();
|
||||
|
||||
if (childCount() <= 3) {
|
||||
syncIn();
|
||||
if (!freshly_activated) {
|
||||
loadFromDatabase();
|
||||
loadCacheFromFile();
|
||||
}
|
||||
else {
|
||||
m_network->oauth()->login();
|
||||
|
||||
if (getSubTreeFeeds().isEmpty()) {
|
||||
m_network->oauth()->login([this]() {
|
||||
syncIn();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,15 @@ void InoreaderNetworkFactory::setBatchSize(int batch_size) {
|
||||
}
|
||||
|
||||
void InoreaderNetworkFactory::initializeOauth() {
|
||||
#if defined(INOREADER_OFFICIAL_SUPPORT)
|
||||
m_oauth2->setClientSecretId(TextFactory::decrypt(INOREADER_CLIENT_ID, OAUTH_DECRYPTION_KEY));
|
||||
m_oauth2->setClientSecretSecret(TextFactory::decrypt(INOREADER_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, &InoreaderNetworkFactory::onTokensError);
|
||||
connect(m_oauth2, &OAuth2Service::authFailed, this, &InoreaderNetworkFactory::onAuthFailed);
|
||||
connect(m_oauth2, &OAuth2Service::tokensRetrieved, this, [this](QString access_token, QString refresh_token, int expires_in) {
|
||||
|
@ -35,7 +35,7 @@ void FormEditOwnCloudAccount::apply() {
|
||||
|
||||
if (!m_creatingNew) {
|
||||
account<OwnCloudServiceRoot>()->completelyRemoveAllData();
|
||||
account<OwnCloudServiceRoot>()->syncIn();
|
||||
account<OwnCloudServiceRoot>()->start(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,11 +63,12 @@ bool OwnCloudServiceRoot::supportsCategoryAdding() const {
|
||||
}
|
||||
|
||||
void OwnCloudServiceRoot::start(bool freshly_activated) {
|
||||
Q_UNUSED(freshly_activated)
|
||||
loadFromDatabase();
|
||||
loadCacheFromFile();
|
||||
if (!freshly_activated) {
|
||||
loadFromDatabase();
|
||||
loadCacheFromFile();
|
||||
}
|
||||
|
||||
if (childCount() <= 3) {
|
||||
if (getSubTreeFeeds().isEmpty()) {
|
||||
syncIn();
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ FormEditTtRssAccount::FormEditTtRssAccount(QWidget* parent)
|
||||
void FormEditTtRssAccount::apply() {
|
||||
FormAccountDetails::apply();
|
||||
|
||||
account<TtRssServiceRoot>()->network()->logout(m_account->networkProxy());
|
||||
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()->setPassword(m_details->m_ui.m_txtPassword->lineEdit()->text());
|
||||
@ -33,9 +34,8 @@ void FormEditTtRssAccount::apply() {
|
||||
accept();
|
||||
|
||||
if (!m_creatingNew) {
|
||||
account<TtRssServiceRoot>()->network()->logout(m_account->networkProxy());
|
||||
account<TtRssServiceRoot>()->completelyRemoveAllData();
|
||||
account<TtRssServiceRoot>()->syncIn();
|
||||
account<TtRssServiceRoot>()->start(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,11 +37,12 @@ ServiceRoot::LabelOperation TtRssServiceRoot::supportedLabelOperations() const {
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::start(bool freshly_activated) {
|
||||
Q_UNUSED(freshly_activated)
|
||||
loadFromDatabase();
|
||||
loadCacheFromFile();
|
||||
if (!freshly_activated) {
|
||||
loadFromDatabase();
|
||||
loadCacheFromFile();
|
||||
}
|
||||
|
||||
if (childCount() <= 3) {
|
||||
if (getSubTreeFeeds().isEmpty()) {
|
||||
syncIn();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user