dbhub: Refactor networking code

This splits up the RemoteDatabase class into two classes, RemoteDatabase
and RemoteNetwork. The first is for managing the directory of cloned
databases while the second is for network handling only. Moving the
network code into a separate class requires some rewriting but should
make the code easier to maintain and extend.
This commit is contained in:
Martin Kleusberg
2020-07-23 19:14:45 +02:00
parent ab5b633709
commit ddf5117331
17 changed files with 952 additions and 882 deletions

View File

@@ -2,65 +2,12 @@
#define REMOTEDATABASE_H
#include <QObject>
#include <QtNetwork/QSslConfiguration>
#include <QVariant>
#include <map>
#include <string>
class QNetworkAccessManager;
class QNetworkConfigurationManager;
class QNetworkReply;
class QProgressDialog;
class QNetworkRequest;
class QHttpMultiPart;
class QFile;
struct sqlite3;
class RemoteMetadataBranchInfo
{
public:
RemoteMetadataBranchInfo(const std::string& _name, const std::string& _commit_id, const std::string& _description, unsigned int _commit_count) :
name(_name),
commit_id(_commit_id),
description(_description),
commit_count(_commit_count)
{}
RemoteMetadataBranchInfo() :
commit_count(0)
{}
std::string name;
std::string commit_id;
std::string description;
unsigned int commit_count;
};
class RemoteMetadataReleaseInfo
{
public:
RemoteMetadataReleaseInfo(const std::string& _name, const std::string& _commit_id, const std::string& _date,
const std::string& _description, const std::string& _email,
const std::string& _user_name, unsigned int _size) :
name(_name),
commit_id(_commit_id),
date(_date),
description(_description),
email(_email),
user_name(_user_name),
size(_size)
{}
RemoteMetadataReleaseInfo() :
size(0)
{}
std::string name;
std::string commit_id;
std::string date;
std::string description;
std::string email;
std::string user_name;
unsigned long size;
};
class RemoteDatabase : public QObject
{
Q_OBJECT
@@ -69,35 +16,6 @@ public:
RemoteDatabase();
~RemoteDatabase() override;
void reloadSettings();
enum CertInfo
{
CertInfoUser,
CertInfoServer,
};
const QList<QSslCertificate>& caCertificates() const;
const std::map<QString, QSslCertificate>& clientCertificates() const { return m_clientCertFiles; }
QString getInfoFromClientCert(const QString& cert, CertInfo info) const;
enum RequestType
{
RequestTypeDatabase,
RequestTypeDirectory,
RequestTypeNewVersionCheck,
RequestTypePush,
RequestTypeLicenceList,
RequestTypeBranchList,
RequestTypeMetadata,
RequestTypeDownload,
};
void fetch(const QUrl& url, RequestType type, const QString& clientCert = QString(), QVariant userdata = QVariant());
void push(const QString& filename, const QUrl& url, const QString& clientCert, const QString& remotename,
const QString& commitMessage = QString(), const QString& licence = QString(), bool isPublic = false,
const QString& branch = QString("master"), bool forcePush = false);
// This class compiles all the information on a lcao database file
class LocalFileInfo
{
@@ -145,55 +63,23 @@ public:
// If the URL contains a commit id (optional), this commit id is part of the check.
QString localExists(const QUrl& url, QString identity, const std::string& branch);
signals:
// As soon as you can safely open a network connection, this signal is emitted. This can be used to delay early network requests
// which might otherwise fail.
void networkReady();
// The openFile signal is emitted whenever a remote database file shall be opened in the main window. This happens when the
// fetch() call for a database is finished, either by actually downloading the database or opening the local clone.
void openFile(QString path);
// These signals are emitted when the fetch() calls are finished that are not requesting a remote database but other data, like
// a directory listing or the licence list.
void gotDirList(QString json, QVariant userdata);
void gotCurrentVersion(QString version, QString url);
void gotLicenceList(std::vector<std::pair<std::string, std::string>> licences);
void gotBranchList(std::vector<std::string> branches, std::string default_branch);
void gotMetadata(std::vector<RemoteMetadataBranchInfo> branches, std::string commits,
std::vector<RemoteMetadataReleaseInfo> releases, std::vector<RemoteMetadataReleaseInfo> tags,
std::string default_branch, std::string web_page);
// The uploadFinished() signal is emitted when a push() call is finished, i.e. a database upload has completed.
void uploadFinished(std::string url);
private:
void gotEncrypted(QNetworkReply* reply);
void gotReply(QNetworkReply* reply);
void gotError(QNetworkReply* reply, const QList<QSslError>& errors);
void updateProgress(qint64 bytesTransmitted, qint64 bytesTotal);
bool prepareSsl(QNetworkRequest* request, const QString& clientCert);
void prepareProgressDialog(QNetworkReply* reply, bool upload, const QUrl& url);
// Helper functions for managing the list of locally available databases
void localAssureOpened();
QString localAdd(QString filename, QString identity, const QUrl& url, const std::string& new_commit_id, const std::string& branch);
QString localCheckFile(const QString& local_file);
// This function takes a file name and checks with which commit id we had checked out this file or last pushed it.
std::string localLastCommitId(QString clientCert, const QUrl& url, const std::string& branch);
// Helper functions for building multi-part HTTP requests
void addPart(QHttpMultiPart* multipart, const QString& name, const QString& value) const;
void addPart(QHttpMultiPart* multipart, const QString& name, QFile* file, const QString& filename) const;
// This function adds a new local database clone to our internal list. It does so by adding a single
// new record to the remote dbs database. All the fields are extracted from the filename, the identity
// and (most importantly) the url parameters. Note that for the commit id field to be correctly filled we
// require the commit id to be part of the url parameter. Also note that this function doesn't care if the
// database has already been added to the list or not. If you need this information you need to check it before
// calling this function, ideally even before sending out a request to the network. The function returns the full
// path of the newly created/updated file.
QString localAdd(QString filename, QString identity, const QUrl& url, const std::string& new_commit_id, const std::string& branch);
// Before using a new client certificate we need to clear the access and authentication cache of the network manager
// object. Otherwise Qt might reuse the old certificate if the requested URL has been used before.
void clearAccessCache(const QString& clientCert);
private:
// Helper functions for managing the list of locally available databases
void localAssureOpened();
QString localCheckFile(const QString& local_file);
QNetworkAccessManager* m_manager;
QNetworkConfigurationManager* m_configurationManager;
QProgressDialog* m_progress;
QSslConfiguration m_sslConfiguration;
std::map<QString, QSslCertificate> m_clientCertFiles;
sqlite3* m_dbLocal;
};