support custom data for all plugins

This commit is contained in:
Martin Rotter 2021-03-01 09:16:11 +01:00
parent 48909d9ef9
commit c97a1dd2e7
16 changed files with 190 additions and 45 deletions

View File

@ -37,6 +37,27 @@
#include <QUrl>
#include <QVariant>
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;
}
}

View File

@ -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<typename Categ, typename Fee>
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<Message>& 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<ServiceRoot*> 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);
}

View File

@ -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.

View File

@ -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());
}
}

View File

@ -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<Category, FeedlyFeed>(this);

View File

@ -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;
};

View File

@ -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);

View File

@ -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;

View File

@ -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());
}
});
}

View File

@ -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<Category, GreaderFeed>(this);

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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());
}
});
}

View File

@ -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());
}

View File

@ -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;
};