diff --git a/src/librssguard/miscellaneous/databasequeries.cpp b/src/librssguard/miscellaneous/databasequeries.cpp index cdd31b45e..85ed334f9 100755 --- a/src/librssguard/miscellaneous/databasequeries.cpp +++ b/src/librssguard/miscellaneous/databasequeries.cpp @@ -37,6 +37,27 @@ #include #include +QString DatabaseQueries::serializeCustomData(const QVariantHash& data) { + if (!data.isEmpty()) { + return QString::fromUtf8(QJsonDocument::fromVariant(data).toJson(QJsonDocument::JsonFormat::Indented)); + } + else { + return QString(); + } +} + +QVariantHash DatabaseQueries::deserializeCustomData(const QString& data) { + if (data.isEmpty()) { + return QVariantHash(); + } + else { + auto json = QJsonDocument::fromJson(data.toUtf8()); + auto json_obj = json.object(); + + return json.object().toVariantHash(); + } +} + bool DatabaseQueries::isLabelAssignedToMessage(const QSqlDatabase& db, Label* label, const Message& msg) { QSqlQuery q(db); @@ -1691,11 +1712,7 @@ void DatabaseQueries::createOverwriteAccount(const QSqlDatabase& db, ServiceRoot q.bindValue(QSL(":id"), account->accountId()); auto custom_data = account->customDatabaseData(); - QString serialized_custom_data; - - if (!custom_data.isEmpty()) { - serialized_custom_data = QString::fromUtf8(QJsonDocument::fromVariant(custom_data).toJson(QJsonDocument::JsonFormat::Indented)); - } + QString serialized_custom_data = serializeCustomData(custom_data); q.bindValue(QSL(":custom_data"), serialized_custom_data); @@ -2162,25 +2179,31 @@ QStringList DatabaseQueries::getAllRecipients(const QSqlDatabase& db, int accoun return rec; } -bool DatabaseQueries::storeNewOauthTokens(const QSqlDatabase& db, const QString& table_name, +bool DatabaseQueries::storeNewOauthTokens(const QSqlDatabase& db, const QString& refresh_token, int account_id) { QSqlQuery query(db); - // TODO:, není funkční - - query.prepare(QSL("UPDATE %1 " - "SET refresh_token = :refresh_token " - "WHERE id = :id;").arg(table_name)); - query.bindValue(QSL(":refresh_token"), refresh_token); + query.prepare(QSL("SELECT custom_data FROM Accounts WHERE id = :id;")); query.bindValue(QSL(":id"), account_id); - if (query.exec()) { - qDebugNN << LOGSEC_DB << "Stored new refresh token into table" << QUOTE_W_SPACE_DOT(table_name); - return true; + if (!query.exec() || !query.next()) { + return false; + } + + QVariantHash custom_data = deserializeCustomData(query.value(0).toString()); + + custom_data["refresh_token"] = refresh_token; + + query.clear(); + query.prepare(QSL("UPDATE Accounts SET custom_data = :custom_data WHERE id = :id;")); + query.bindValue(QSL(":custom_data"), serializeCustomData(custom_data)); + query.bindValue(QSL(":id"), account_id); + + if (!query.exec()) { + return false; } else { - qWarningNN << LOGSEC_DB << "Updating tokens in DB failed:" << QUOTE_W_SPACE_DOT(query.lastError().text()); - return false; + return true; } } diff --git a/src/librssguard/miscellaneous/databasequeries.h b/src/librssguard/miscellaneous/databasequeries.h index 98ab823e6..9e93eb256 100644 --- a/src/librssguard/miscellaneous/databasequeries.h +++ b/src/librssguard/miscellaneous/databasequeries.h @@ -23,6 +23,10 @@ class DatabaseQueries { public: + // Custom data serializers. + static QString serializeCustomData(const QVariantHash& data); + static QVariantHash deserializeCustomData(const QString& data); + // Label operators. static bool isLabelAssignedToMessage(const QSqlDatabase& db, Label* label, const Message& msg); static bool deassignLabelFromMessage(const QSqlDatabase& db, Label* label, const Message& msg); @@ -98,8 +102,7 @@ class DatabaseQueries { template static void loadFromDatabase(ServiceRoot* root); - static bool storeNewOauthTokens(const QSqlDatabase& db, const QString& table_name, - const QString& refresh_token, int account_id); + static bool storeNewOauthTokens(const QSqlDatabase& db, const QString& refresh_token, int account_id); static void createOverwriteAccount(const QSqlDatabase& db, ServiceRoot* account); static int updateMessages(QSqlDatabase db, const QList& messages, const QString& feed_custom_id, int account_id, const QString& url, bool force_update, bool* any_message_changed, bool* ok = nullptr); @@ -199,7 +202,7 @@ QList DatabaseQueries::getAccounts(const QSqlDatabase& db, const Q TextFactory::decrypt(query.value(QSL("proxy_password")).toString())); root->setNetworkProxy(proxy); - root->setCustomDatabaseData(QJsonDocument::fromJson(query.value(QSL("custom_data")).toString().toUtf8()).object().toVariantHash()); + root->setCustomDatabaseData(deserializeCustomData(query.value(QSL("custom_data")).toString())); roots.append(root); } diff --git a/src/librssguard/services/abstract/serviceroot.h b/src/librssguard/services/abstract/serviceroot.h index 1eef4efa7..711c82fad 100644 --- a/src/librssguard/services/abstract/serviceroot.h +++ b/src/librssguard/services/abstract/serviceroot.h @@ -22,14 +22,6 @@ class QAction; class MessagesModel; class CacheForServiceRoot; -struct CustomDatabaseEntry { - public: - CustomDatabaseEntry(const QString& name, bool encrypted = false) : m_name(name), m_encrypted(encrypted) {} - - QString m_name; - bool m_encrypted; -}; - // THIS IS the root node of the service. // NOTE: The root usually contains some core functionality of the // service like service account username/password etc. diff --git a/src/librssguard/services/feedly/feedlynetwork.cpp b/src/librssguard/services/feedly/feedlynetwork.cpp index 73f384ab2..f5a694ab6 100755 --- a/src/librssguard/services/feedly/feedlynetwork.cpp +++ b/src/librssguard/services/feedly/feedlynetwork.cpp @@ -523,7 +523,7 @@ void FeedlyNetwork::onTokensRetrieved(const QString& access_token, const QString if (m_service != nullptr && !refresh_token.isEmpty()) { QSqlDatabase database = qApp->database()->connection(metaObject()->className()); - DatabaseQueries::storeNewOauthTokens(database, QSL("FeedlyAccounts"), refresh_token, m_service->accountId()); + DatabaseQueries::storeNewOauthTokens(database, refresh_token, m_service->accountId()); } } diff --git a/src/librssguard/services/feedly/feedlyserviceroot.cpp b/src/librssguard/services/feedly/feedlyserviceroot.cpp index 8b0fc775b..0a4820314 100755 --- a/src/librssguard/services/feedly/feedlyserviceroot.cpp +++ b/src/librssguard/services/feedly/feedlyserviceroot.cpp @@ -44,6 +44,34 @@ bool FeedlyServiceRoot::editViaGui() { return true; } +QVariantHash FeedlyServiceRoot::customDatabaseData() const { + QVariantHash data; + + data["username"] = m_network->username(); + data["dat"] = m_network->developerAccessToken(); + +#if defined(FEEDLY_OFFICIAL_SUPPORT) + data["refresh_token"] = m_network->oauth()->refreshToken(); +#endif + + data["batch_size"] = m_network->batchSize(); + data["download_only_unread"] = m_network->downloadOnlyUnreadMessages(); + + return data; +} + +void FeedlyServiceRoot::setCustomDatabaseData(const QVariantHash& data) const { + m_network->setUsername(data["username"].toString()); + m_network->setDeveloperAccessToken(data["dat"].toString()); + +#if defined(FEEDLY_OFFICIAL_SUPPORT) + m_network->oauth()->setRefreshToken(data["refresh_token"].toString()); +#endif + + m_network->setBatchSize(data["batch_size"].toInt()); + m_network->setDownloadOnlyUnreadMessages(data["download_only_unread"].toBool()); +} + void FeedlyServiceRoot::start(bool freshly_activated) { if (!freshly_activated) { DatabaseQueries::loadFromDatabase(this); diff --git a/src/librssguard/services/feedly/feedlyserviceroot.h b/src/librssguard/services/feedly/feedlyserviceroot.h index cf5a2fd31..a052e0092 100755 --- a/src/librssguard/services/feedly/feedlyserviceroot.h +++ b/src/librssguard/services/feedly/feedlyserviceroot.h @@ -21,14 +21,17 @@ class FeedlyServiceRoot : public ServiceRoot, public CacheForServiceRoot { virtual QString code() const; virtual void saveAllCachedData(bool ignore_errors); virtual LabelOperation supportedLabelOperations() const; + virtual QVariantHash customDatabaseData() const; + virtual void setCustomDatabaseData(const QVariantHash& data) const; FeedlyNetwork* network() const; - void updateTitle(); - protected: virtual RootItem* obtainNewTreeForSyncIn() const; + private: + void updateTitle(); + private: FeedlyNetwork* m_network; }; diff --git a/src/librssguard/services/gmail/gmailserviceroot.cpp b/src/librssguard/services/gmail/gmailserviceroot.cpp index c4ba20553..431116ba0 100644 --- a/src/librssguard/services/gmail/gmailserviceroot.cpp +++ b/src/librssguard/services/gmail/gmailserviceroot.cpp @@ -50,6 +50,28 @@ void GmailServiceRoot::writeNewEmail() { FormAddEditEmail(this, qApp->mainFormWidget()).execForAdd(); } +QVariantHash GmailServiceRoot::customDatabaseData() const { + QVariantHash data; + + data["username"] = m_network->username(); + data["batch_size"] = m_network->batchSize(); + data["client_id"] = m_network->oauth()->clientId(); + data["client_secret"] = m_network->oauth()->clientSecret(); + data["refresh_token"] = m_network->oauth()->refreshToken(); + data["redirect_uri"] = m_network->oauth()->redirectUrl(); + + return data; +} + +void GmailServiceRoot::setCustomDatabaseData(const QVariantHash& data) const { + m_network->setUsername(data["username"].toString()); + m_network->setBatchSize(data["batch_size"].toInt()); + m_network->oauth()->setClientId(data["client_id"].toString()); + m_network->oauth()->setClientSecret(data["client_secret"].toString()); + m_network->oauth()->setRefreshToken(data["refresh_token"].toString()); + m_network->oauth()->setRedirectUrl(data["redirect_uri"].toString()); +} + bool GmailServiceRoot::downloadAttachmentOnMyOwn(const QUrl& url) const { QString str_url = url.toString(); QString attachment_id = str_url.mid(str_url.indexOf(QL1C('?')) + 1); diff --git a/src/librssguard/services/gmail/gmailserviceroot.h b/src/librssguard/services/gmail/gmailserviceroot.h index 2e327fab5..f2c8535a2 100644 --- a/src/librssguard/services/gmail/gmailserviceroot.h +++ b/src/librssguard/services/gmail/gmailserviceroot.h @@ -29,18 +29,19 @@ class GmailServiceRoot : public ServiceRoot, public CacheForServiceRoot { virtual QString code() const; virtual QString additionalTooltip() const; virtual void saveAllCachedData(bool ignore_errors); - - void updateTitle(); - - private slots: - void replyToEmail(); + virtual QVariantHash customDatabaseData() const; + virtual void setCustomDatabaseData(const QVariantHash& data) const; protected: virtual RootItem* obtainNewTreeForSyncIn() const; - private: + private slots: + void replyToEmail(); void writeNewEmail(); + private: + void updateTitle(); + private: GmailNetworkFactory* m_network; QAction* m_actionReply; diff --git a/src/librssguard/services/gmail/network/gmailnetworkfactory.cpp b/src/librssguard/services/gmail/network/gmailnetworkfactory.cpp index 08c7ac42c..ca949539a 100644 --- a/src/librssguard/services/gmail/network/gmailnetworkfactory.cpp +++ b/src/librssguard/services/gmail/network/gmailnetworkfactory.cpp @@ -136,7 +136,7 @@ void GmailNetworkFactory::initializeOauth() { if (m_service != nullptr && !refresh_token.isEmpty()) { QSqlDatabase database = qApp->database()->connection(metaObject()->className()); - DatabaseQueries::storeNewOauthTokens(database, QSL("GmailAccounts"), refresh_token, m_service->accountId()); + DatabaseQueries::storeNewOauthTokens(database, refresh_token, m_service->accountId()); } }); } diff --git a/src/librssguard/services/greader/greaderserviceroot.cpp b/src/librssguard/services/greader/greaderserviceroot.cpp index 913b6c969..f8a91a7c3 100755 --- a/src/librssguard/services/greader/greaderserviceroot.cpp +++ b/src/librssguard/services/greader/greaderserviceroot.cpp @@ -35,6 +35,26 @@ bool GreaderServiceRoot::editViaGui() { return true; } +QVariantHash GreaderServiceRoot::customDatabaseData() const { + QVariantHash data; + + data["service"] = int(m_network->service()); + data["username"] = m_network->username(); + data["password"] = TextFactory::encrypt(m_network->password()); + data["url"] = m_network->baseUrl(); + data["batch_size"] = m_network->batchSize(); + + return data; +} + +void GreaderServiceRoot::setCustomDatabaseData(const QVariantHash& data) const { + m_network->setService(GreaderServiceRoot::Service(data["service"].toInt())); + m_network->setUsername(data["username"].toString()); + TextFactory::decrypt(data["password"].toString()); + m_network->setBaseUrl(data["url"].toString()); + m_network->setBatchSize(data["batch_size"].toInt()); +} + void GreaderServiceRoot::start(bool freshly_activated) { if (!freshly_activated) { DatabaseQueries::loadFromDatabase(this); diff --git a/src/librssguard/services/greader/greaderserviceroot.h b/src/librssguard/services/greader/greaderserviceroot.h index ad78ccb55..3362aff02 100755 --- a/src/librssguard/services/greader/greaderserviceroot.h +++ b/src/librssguard/services/greader/greaderserviceroot.h @@ -29,14 +29,17 @@ class GreaderServiceRoot : public ServiceRoot, public CacheForServiceRoot { virtual QString code() const; virtual void saveAllCachedData(bool ignore_errors); virtual LabelOperation supportedLabelOperations() const; + virtual QVariantHash customDatabaseData() const; + virtual void setCustomDatabaseData(const QVariantHash& data) const; GreaderNetwork* network() const; - void updateTitleIcon(); - protected: virtual RootItem* obtainNewTreeForSyncIn() const; + private: + void updateTitleIcon(); + private: GreaderNetwork* m_network; }; diff --git a/src/librssguard/services/inoreader/inoreaderserviceroot.cpp b/src/librssguard/services/inoreader/inoreaderserviceroot.cpp index 1ada47b72..8c288580b 100644 --- a/src/librssguard/services/inoreader/inoreaderserviceroot.cpp +++ b/src/librssguard/services/inoreader/inoreaderserviceroot.cpp @@ -32,6 +32,28 @@ ServiceRoot::LabelOperation InoreaderServiceRoot::supportedLabelOperations() con return ServiceRoot::LabelOperation(0); } +QVariantHash InoreaderServiceRoot::customDatabaseData() const { + QVariantHash data; + + data["username"] = m_network->username(); + data["batch_size"] = m_network->batchSize(); + data["client_id"] = m_network->oauth()->clientId(); + data["client_secret"] = m_network->oauth()->clientSecret(); + data["refresh_token"] = m_network->oauth()->refreshToken(); + data["redirect_uri"] = m_network->oauth()->redirectUrl(); + + return data; +} + +void InoreaderServiceRoot::setCustomDatabaseData(const QVariantHash& data) const { + m_network->setUsername(data["username"].toString()); + m_network->setBatchSize(data["batch_size"].toInt()); + m_network->oauth()->setClientId(data["client_id"].toString()); + m_network->oauth()->setClientSecret(data["client_secret"].toString()); + m_network->oauth()->setRefreshToken(data["refresh_token"].toString()); + m_network->oauth()->setRedirectUrl(data["redirect_uri"].toString()); +} + bool InoreaderServiceRoot::isSyncable() const { return true; } diff --git a/src/librssguard/services/inoreader/inoreaderserviceroot.h b/src/librssguard/services/inoreader/inoreaderserviceroot.h index 8643027ca..e6a5b6b1e 100644 --- a/src/librssguard/services/inoreader/inoreaderserviceroot.h +++ b/src/librssguard/services/inoreader/inoreaderserviceroot.h @@ -27,12 +27,15 @@ class InoreaderServiceRoot : public ServiceRoot, public CacheForServiceRoot { virtual QString code() const; virtual QString additionalTooltip() const; virtual void saveAllCachedData(bool ignore_errors); - - void updateTitle(); + virtual QVariantHash customDatabaseData() const; + virtual void setCustomDatabaseData(const QVariantHash& data) const; protected: virtual RootItem* obtainNewTreeForSyncIn() const; + private: + void updateTitle(); + private: InoreaderNetworkFactory* m_network; }; diff --git a/src/librssguard/services/inoreader/network/inoreadernetworkfactory.cpp b/src/librssguard/services/inoreader/network/inoreadernetworkfactory.cpp index bc3c3c781..810002238 100644 --- a/src/librssguard/services/inoreader/network/inoreadernetworkfactory.cpp +++ b/src/librssguard/services/inoreader/network/inoreadernetworkfactory.cpp @@ -71,7 +71,7 @@ void InoreaderNetworkFactory::initializeOauth() { if (m_service != nullptr && !refresh_token.isEmpty()) { QSqlDatabase database = qApp->database()->connection(metaObject()->className()); - DatabaseQueries::storeNewOauthTokens(database, QSL("InoreaderAccounts"), refresh_token, m_service->accountId()); + DatabaseQueries::storeNewOauthTokens(database, refresh_token, m_service->accountId()); } }); } diff --git a/src/librssguard/services/owncloud/owncloudserviceroot.cpp b/src/librssguard/services/owncloud/owncloudserviceroot.cpp index c558bd408..6ea1b0fd9 100644 --- a/src/librssguard/services/owncloud/owncloudserviceroot.cpp +++ b/src/librssguard/services/owncloud/owncloudserviceroot.cpp @@ -126,3 +126,25 @@ RootItem* OwnCloudServiceRoot::obtainNewTreeForSyncIn() const { return nullptr; } } + +QVariantHash OwnCloudServiceRoot::customDatabaseData() const { + QVariantHash data; + + data["auth_username"] = m_network->authUsername(); + data["auth_password"] = TextFactory::encrypt(m_network->authPassword()); + data["url"] = m_network->url(); + data["force_update"] = m_network->forceServerSideUpdate(); + data["batch_size"] = m_network->batchSize(); + data["download_only_unread"] = m_network->downloadOnlyUnreadMessages(); + + return data; +} + +void OwnCloudServiceRoot::setCustomDatabaseData(const QVariantHash& data) const { + m_network->setAuthUsername(data["auth_username"].toString()); + m_network->setAuthPassword(TextFactory::decrypt(data["auth_password"].toString())); + m_network->setUrl(data["url"].toString()); + m_network->setForceServerSideUpdate(data["force_update"].toBool()); + m_network->setBatchSize(data["batch_size"].toInt()); + m_network->setDownloadOnlyUnreadMessages(data["download_only_unread"].toBool()); +} diff --git a/src/librssguard/services/owncloud/owncloudserviceroot.h b/src/librssguard/services/owncloud/owncloudserviceroot.h index ac11acf78..fc2ca972d 100644 --- a/src/librssguard/services/owncloud/owncloudserviceroot.h +++ b/src/librssguard/services/owncloud/owncloudserviceroot.h @@ -26,14 +26,17 @@ class OwnCloudServiceRoot : public ServiceRoot, public CacheForServiceRoot { virtual void start(bool freshly_activated); virtual QString code() const; virtual void saveAllCachedData(bool ignore_errors); + virtual QVariantHash customDatabaseData() const; + virtual void setCustomDatabaseData(const QVariantHash& data) const; OwnCloudNetworkFactory* network() const; - void updateTitle(); - protected: virtual RootItem* obtainNewTreeForSyncIn() const; + private: + void updateTitle(); + private: OwnCloudNetworkFactory* m_network; };