From 3469e457cad3cb07ee907c1947c165107fabd6a3 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Sun, 28 Feb 2021 19:44:02 +0100 Subject: [PATCH] simple custom data SQL layer for accounts, something similar will come for feeds too maybe --- resources/scripts/7za | 2 +- resources/sql/db_init_sqlite.sql | 23 +---- .../miscellaneous/databasequeries.cpp | 33 ++----- .../miscellaneous/databasequeries.h | 17 +--- .../services/abstract/serviceroot.cpp | 12 ++- .../services/abstract/serviceroot.h | 4 +- .../services/tt-rss/ttrssserviceroot.cpp | 93 +++++-------------- .../services/tt-rss/ttrssserviceroot.h | 41 +------- 8 files changed, 54 insertions(+), 171 deletions(-) diff --git a/resources/scripts/7za b/resources/scripts/7za index 47f412575..9c10723bf 160000 --- a/resources/scripts/7za +++ b/resources/scripts/7za @@ -1 +1 @@ -Subproject commit 47f4125753452eff8800dbd6600c5a05540b15d9 +Subproject commit 9c10723bfbaf6cb85107d6ee16e0324e9e487749 diff --git a/resources/sql/db_init_sqlite.sql b/resources/sql/db_init_sqlite.sql index 8465e6eb9..ef2c375a1 100644 --- a/resources/sql/db_init_sqlite.sql +++ b/resources/sql/db_init_sqlite.sql @@ -13,27 +13,8 @@ CREATE TABLE Accounts ( proxy_port INTEGER, proxy_username TEXT, proxy_password TEXT, - /* Custom attributes dynamically mapped to actual account data fields. */ - custom_data_1 TEXT, - custom_data_2 TEXT, - custom_data_3 TEXT, - custom_data_4 TEXT, - custom_data_5 TEXT, - custom_data_6 TEXT, - custom_data_7 TEXT, - custom_data_8 TEXT, - custom_data_9 TEXT, - custom_data_10 TEXT, - custom_data_11 TEXT, - custom_data_12 TEXT, - custom_data_13 TEXT, - custom_data_14 TEXT, - custom_data_15 TEXT, - custom_data_16 TEXT, - custom_data_17 TEXT, - custom_data_18 TEXT, - custom_data_19 TEXT, - custom_data_20 TEXT + /* Custom column for (serialized) custom account-specific data. */ + custom_data TEXT ); -- ! CREATE TABLE Categories ( diff --git a/src/librssguard/miscellaneous/databasequeries.cpp b/src/librssguard/miscellaneous/databasequeries.cpp index 427884b97..9425098f4 100755 --- a/src/librssguard/miscellaneous/databasequeries.cpp +++ b/src/librssguard/miscellaneous/databasequeries.cpp @@ -1677,32 +1677,12 @@ void DatabaseQueries::createOverwriteAccount(const QSqlDatabase& db, ServiceRoot // Now we construct the SQL update query. auto proxy = account->networkProxy(); - QString sql_statement = QSL("UPDATE Accounts " - "SET proxy_type = :proxy_type, proxy_host = :proxy_host, proxy_port = :proxy_port, " - " proxy_username = :proxy_username, proxy_password = :proxy_password%1 " - "WHERE id = :id"); - auto custom_attributes = account->customDatabaseAttributes(); - QStringList custom_sql_clauses; - for (int i = 0; i < custom_attributes.size(); i++) { - QString target_data = account->property(custom_attributes.at(i).m_name.toLocal8Bit()).toString(); - - if (custom_attributes.at(i).m_encrypted) { - target_data = TextFactory::encrypt(target_data); - } - - custom_sql_clauses.append(QSL("custom_data_%1 = '%2'").arg(QString::number(i + 1), - target_data)); - } - - if (!custom_sql_clauses.isEmpty()) { - sql_statement = sql_statement.arg(QSL(", ") + custom_sql_clauses.join(QSL(", "))); - } - else { - sql_statement = sql_statement.arg(QString()); - } - - q.prepare(sql_statement); + q.prepare(QSL("UPDATE Accounts " + "SET proxy_type = :proxy_type, proxy_host = :proxy_host, proxy_port = :proxy_port, " + " proxy_username = :proxy_username, proxy_password = :proxy_password, " + " custom_data = :custom_data " + "WHERE id = :id")); q.bindValue(QSL(":proxy_type"), proxy.type()); q.bindValue(QSL(":proxy_host"), proxy.hostName()); q.bindValue(QSL(":proxy_port"), proxy.port()); @@ -1710,6 +1690,9 @@ void DatabaseQueries::createOverwriteAccount(const QSqlDatabase& db, ServiceRoot q.bindValue(QSL(":proxy_password"), TextFactory::encrypt(proxy.password())); q.bindValue(QSL(":id"), account->accountId()); + q.bindValue(QSL(":custom_data"), + QString::fromUtf8(QJsonDocument::fromVariant(account->customDatabaseData()).toJson(QJsonDocument::JsonFormat::Indented))); + if (!q.exec()) { throw ApplicationException(q.lastError().text()); } diff --git a/src/librssguard/miscellaneous/databasequeries.h b/src/librssguard/miscellaneous/databasequeries.h index dfc4f0072..4974201e1 100644 --- a/src/librssguard/miscellaneous/databasequeries.h +++ b/src/librssguard/miscellaneous/databasequeries.h @@ -14,6 +14,8 @@ #include "services/abstract/serviceroot.h" #include "services/standard/standardfeed.h" +#include +#include #include #include #include @@ -197,20 +199,7 @@ QList DatabaseQueries::getAccounts(const QSqlDatabase& db, const Q TextFactory::decrypt(query.value(QSL("proxy_password")).toString())); root->setNetworkProxy(proxy); - - // Load account-specific custom data. - auto custom_attributes = root->customDatabaseAttributes(); - - for (int i = 0; i < custom_attributes.size(); i++) { - const QString target_db_attribute = QSL("custom_data_%1").arg(QString::number(i + 1)); - QString target_data = query.value(target_db_attribute).toString(); - - if (custom_attributes.at(i).m_encrypted) { - target_data = TextFactory::decrypt(target_data); - } - - root->setProperty(custom_attributes.at(i).m_name.toLocal8Bit(), target_data); - } + root->setCustomDatabaseData(QJsonDocument::fromJson(query.value(QSL("custom_data")).toString().toUtf8()).object().toVariantHash()); roots.append(root); } diff --git a/src/librssguard/services/abstract/serviceroot.cpp b/src/librssguard/services/abstract/serviceroot.cpp index 4c1e97553..506c67c52 100644 --- a/src/librssguard/services/abstract/serviceroot.cpp +++ b/src/librssguard/services/abstract/serviceroot.cpp @@ -260,16 +260,20 @@ ServiceRoot::LabelOperation ServiceRoot::supportedLabelOperations() const { return LabelOperation::Adding | LabelOperation::Editing | LabelOperation::Deleting; } -QList ServiceRoot::customDatabaseAttributes() const { - return {}; -} - void ServiceRoot::saveAccountDataToDatabase() { QSqlDatabase database = qApp->database()->connection(metaObject()->className()); DatabaseQueries::createOverwriteAccount(database, this); } +QVariantHash ServiceRoot::customDatabaseData() const { + return {}; +} + +void ServiceRoot::setCustomDatabaseData(const QVariantHash& data) const { + Q_UNUSED(data) +} + void ServiceRoot::itemChanged(const QList& items) { emit dataChanged(items); } diff --git a/src/librssguard/services/abstract/serviceroot.h b/src/librssguard/services/abstract/serviceroot.h index d4da81338..1eef4efa7 100644 --- a/src/librssguard/services/abstract/serviceroot.h +++ b/src/librssguard/services/abstract/serviceroot.h @@ -9,6 +9,7 @@ #include "core/messagefilter.h" #include "definitions/typedefs.h" +#include #include #include @@ -59,8 +60,9 @@ class ServiceRoot : public RootItem { virtual bool supportsFeedAdding() const; virtual bool supportsCategoryAdding() const; virtual LabelOperation supportedLabelOperations() const; - virtual QList customDatabaseAttributes() const; virtual void saveAccountDataToDatabase(); + virtual QVariantHash customDatabaseData() const; + virtual void setCustomDatabaseData(const QVariantHash& json) const; // Returns list of specific actions for "Add new item" main window menu. // So typical list of returned actions could look like: diff --git a/src/librssguard/services/tt-rss/ttrssserviceroot.cpp b/src/librssguard/services/tt-rss/ttrssserviceroot.cpp index f741503c3..ded8558b9 100644 --- a/src/librssguard/services/tt-rss/ttrssserviceroot.cpp +++ b/src/librssguard/services/tt-rss/ttrssserviceroot.cpp @@ -185,11 +185,30 @@ void TtRssServiceRoot::saveAllCachedData(bool ignore_errors) { } } -QList TtRssServiceRoot::customDatabaseAttributes() const { - return { - { QSL("username") }, { QSL("password"), true }, { QSL("auth_protected") }, { QSL("auth_username") }, - { QSL("auth_password"), true }, { QSL("url") }, { QSL("force_update") }, { QSL("download_only_unread") } - }; +QVariantHash TtRssServiceRoot::customDatabaseData() const { + QVariantHash data; + + data["username"] = m_network->username(); + data["password"] = TextFactory::encrypt(m_network->password()); + data["auth_protected"] = m_network->authIsUsed(); + 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["download_only_unread"] = m_network->downloadOnlyUnreadMessages(); + + return data; +} + +void TtRssServiceRoot::setCustomDatabaseData(const QVariantHash& data) const { + m_network->setUsername( data["username"].toString()); + m_network->setPassword(TextFactory::decrypt(data["password"].toString())); + m_network->setAuthIsUsed(data["auth_protected"].toBool()); + 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->setDownloadOnlyUnreadMessages(data["download_only_unread"].toBool()); } QString TtRssServiceRoot::additionalTooltip() const { @@ -216,70 +235,6 @@ void TtRssServiceRoot::updateTitle() { setTitle(TextFactory::extractUsernameFromEmail(m_network->username()) + QSL(" (Tiny Tiny RSS)")); } -QString TtRssServiceRoot::username() const { - return m_network->username(); -} - -void TtRssServiceRoot::setUsername(const QString& username) { - m_network->setUsername(username); -} - -QString TtRssServiceRoot::password() const { - return m_network->password(); -} - -void TtRssServiceRoot::setPassword(const QString& password) { - m_network->setPassword(password); -} - -bool TtRssServiceRoot::authProtected() const { - return m_network->authIsUsed(); -} - -void TtRssServiceRoot::setAuthProtected(bool auth_protected) { - m_network->setAuthIsUsed(auth_protected); -} - -QString TtRssServiceRoot::authUsername() const { - return m_network->authUsername(); -} - -void TtRssServiceRoot::setAuthUsername(const QString& auth_username) { - m_network->setAuthUsername(auth_username); -} - -QString TtRssServiceRoot::authPassword() const { - return m_network->authPassword(); -} - -void TtRssServiceRoot::setAuthPassword(const QString& auth_password) { - m_network->setAuthPassword(auth_password); -} - -QString TtRssServiceRoot::url() const { - return m_network->url(); -} - -void TtRssServiceRoot::setUrl(const QString& url) { - m_network->setUrl(url); -} - -bool TtRssServiceRoot::forceUpdate() const { - return m_network->forceServerSideUpdate(); -} - -void TtRssServiceRoot::setForceUpdate(bool force_update) { - m_network->setForceServerSideUpdate(force_update); -} - -bool TtRssServiceRoot::downloadOnlyUnread() const { - return m_network->downloadOnlyUnreadMessages(); -} - -void TtRssServiceRoot::setDownloadOnlyUnread(bool download_only_unread) { - m_network->setDownloadOnlyUnreadMessages(download_only_unread); -} - RootItem* TtRssServiceRoot::obtainNewTreeForSyncIn() const { TtRssGetFeedsCategoriesResponse feed_cats = m_network->getFeedsCategories(networkProxy()); TtRssGetLabelsResponse labels = m_network->getLabels(networkProxy()); diff --git a/src/librssguard/services/tt-rss/ttrssserviceroot.h b/src/librssguard/services/tt-rss/ttrssserviceroot.h index fd9648058..418c366d1 100644 --- a/src/librssguard/services/tt-rss/ttrssserviceroot.h +++ b/src/librssguard/services/tt-rss/ttrssserviceroot.h @@ -14,14 +14,6 @@ class TtRssNetworkFactory; class TtRssServiceRoot : public ServiceRoot, public CacheForServiceRoot { Q_OBJECT - Q_PROPERTY(QString username READ username WRITE setUsername) - Q_PROPERTY(QString password READ password WRITE setPassword) - Q_PROPERTY(bool auth_protected READ authProtected WRITE setAuthProtected) - Q_PROPERTY(QString auth_username READ authUsername WRITE setAuthUsername) - Q_PROPERTY(QString auth_password READ authPassword WRITE setAuthPassword) - Q_PROPERTY(QString url READ url WRITE setUrl) - Q_PROPERTY(bool force_update READ forceUpdate WRITE setForceUpdate) - Q_PROPERTY(bool download_only_unread READ downloadOnlyUnread WRITE setDownloadOnlyUnread) public: explicit TtRssServiceRoot(RootItem* parent = nullptr); @@ -39,41 +31,18 @@ class TtRssServiceRoot : public ServiceRoot, public CacheForServiceRoot { virtual void addNewFeed(RootItem* selected_item, const QString& url = QString()); virtual QString additionalTooltip() const; virtual void saveAllCachedData(bool ignore_errors); - virtual QList customDatabaseAttributes() const; + virtual QVariantHash customDatabaseData() const; + virtual void setCustomDatabaseData(const QVariantHash& data) const; // Access to network. TtRssNetworkFactory* network() const; - void updateTitle(); - - // Support for dynamic DB attributes. - QString username() const; - void setUsername(const QString& username); - - QString password() const; - void setPassword(const QString& password); - - bool authProtected() const; - void setAuthProtected(bool auth_protected); - - QString authUsername() const; - void setAuthUsername(const QString& auth_username); - - QString authPassword() const; - void setAuthPassword(const QString& auth_password); - - QString url() const; - void setUrl(const QString& url); - - bool forceUpdate() const; - void setForceUpdate(bool force_update); - - bool downloadOnlyUnread() const; - void setDownloadOnlyUnread(bool download_only_unread); - protected: virtual RootItem* obtainNewTreeForSyncIn() const; + private: + void updateTitle(); + private: TtRssNetworkFactory* m_network; };