Read s3 creds for upload from URL in private network (VPN) - fix

This commit is contained in:
Yuriy Puchkov
2020-11-18 18:54:36 +02:00
parent 50d5afed8f
commit deee448de4
26 changed files with 401 additions and 492 deletions

View File

@@ -4,22 +4,14 @@
#include <QByteArray>
#include <QDateTime>
#include <QDir>
#include <QEventLoop>
#include <QFileInfo>
#include <QNetworkAccessManager>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QObject>
#include <QSettings>
#include <QTemporaryFile>
#include <QTimer>
ImgS3Settings::ImgS3Settings(QObject* parent)
: QObject(parent)
ImgS3Settings::ImgS3Settings()
{
m_proxy = nullptr;
m_networkConfig = nullptr;
initSettings();
// get remote config url
@@ -47,38 +39,9 @@ void ImgS3Settings::initS3Creds()
m_xApiKey = configHandler.value("S3", "S3_X_API_KEY").toString();
m_url = configHandler.value("S3", "S3_URL").toString();
normalizeS3Creds();
updateConfigFromRemote();
}
bool ImgS3Settings::getConfigRemote(int timeout)
{
if (!m_url.isEmpty() && !m_credsUrl.isEmpty()) {
updateConfigFromRemote();
return true;
}
QNetworkAccessManager* networkConfig = new QNetworkAccessManager(this);
if (proxy() != nullptr) {
networkConfig->setProxy(*m_proxy);
}
QNetworkReply* reply = networkConfig->get(QNetworkRequest(m_s3ConfigUrl));
QEventLoop loop;
QTimer timer;
timer.setSingleShot(true);
connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
connect(reply, SIGNAL(readyRead()), &loop, SLOT(quit()));
timer.start(timeout * 1000); // 30 secs. timeout
loop.exec();
QString data = QString(reply->readAll());
parseConfigurationData(data);
delete reply;
delete networkConfig;
return !data.isEmpty();
}
void ImgS3Settings::parseConfigurationData(const QString& data)
void ImgS3Settings::updateConfigurationData(const QString& data)
{
// read remote and save to the temporary file
QTemporaryFile file;
@@ -88,11 +51,11 @@ void ImgS3Settings::parseConfigurationData(const QString& data)
stream.flush();
// parse and get configuration data
QSettings remoteConfig(file.fileName(), QSettings::IniFormat, this);
QSettings remoteConfig(file.fileName(), QSettings::IniFormat);
remoteConfig.beginGroup("S3");
m_url = remoteConfig.value("S3_URL").toString();
m_credsUrl = remoteConfig.value("S3_CREDS_URL").toString();
m_xApiKey = remoteConfig.value("S3_X_API_KEY").toString();
QString url = remoteConfig.value("S3_URL").toString();
QString credsUrl = remoteConfig.value("S3_CREDS_URL").toString();
QString xApiKey = remoteConfig.value("S3_X_API_KEY").toString();
normalizeS3Creds();
remoteConfig.endGroup();
@@ -101,9 +64,9 @@ void ImgS3Settings::parseConfigurationData(const QString& data)
// cache configuration at the local storage
ConfigHandler configHandler;
configHandler.setValue("S3", "S3_URL", m_url);
configHandler.setValue("S3", "S3_CREDS_URL", m_credsUrl);
configHandler.setValue("S3", "S3_X_API_KEY", m_xApiKey);
configHandler.setValue("S3", "S3_URL", url);
configHandler.setValue("S3", "S3_CREDS_URL", credsUrl);
configHandler.setValue("S3", "S3_X_API_KEY", xApiKey);
// set last update date
QString currentDateTime =
@@ -121,47 +84,6 @@ void ImgS3Settings::normalizeS3Creds()
}
}
void ImgS3Settings::updateConfigFromRemote()
{
// check for outdated s3 creds
ConfigHandler configHandler;
QString credsUpdated =
configHandler.value("S3", "S3_CREDS_UPDATED").toString();
QDateTime dtCredsUpdated =
QDateTime::currentDateTime().fromString(credsUpdated, Qt::ISODate);
QDateTime now = QDateTime::currentDateTime();
dtCredsUpdated = dtCredsUpdated.addDays(1);
if (dtCredsUpdated <= now) {
// Do update config from remote
if (nullptr == m_networkConfig) {
m_networkConfig = new QNetworkAccessManager(this);
if (proxy() != nullptr) {
m_networkConfig->setProxy(*m_proxy);
}
connect(m_networkConfig,
&QNetworkAccessManager::finished,
this,
&ImgS3Settings::handleReplyUpdateConfigFromRemote);
}
m_networkConfig->get(QNetworkRequest(m_s3ConfigUrl));
}
}
void ImgS3Settings::handleReplyUpdateConfigFromRemote(QNetworkReply* reply)
{
if (reply->error() == QNetworkReply::NoError) {
QString configData = QString(reply->readAll());
parseConfigurationData(configData);
} else {
QString reason =
reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute)
.toString();
QString error = reply->errorString();
qWarning() << "Update config from remote status:" << error;
qWarning() << reason;
}
}
const QString& ImgS3Settings::storageLocked()
{
if (m_localSettings->contains("STORAGE_LOCKED")) {

View File

@@ -2,7 +2,6 @@
#define IMG_S3_SETTINGS_H
#define S3_API_IMG_PATH "v2/image/"
#define S3_GET_REMOTE_SETTINGS_TIMEOUT 10
#define S3_CONFIG_LOCAL "config.ini"
#define S3_CONFIG_PROXY "config_proxy.ini"
@@ -13,22 +12,12 @@
class QSettings;
class QNetworkProxy;
class QNetworkAccessManager;
class QNetworkRequest;
class QNetworkReply;
class ImgS3Settings : public QObject
class ImgS3Settings
{
Q_OBJECT
private slots:
void handleReplyUpdateConfigFromRemote(QNetworkReply* reply);
public:
ImgS3Settings(QObject* parent = nullptr);
bool getConfigRemote(int timeout = S3_GET_REMOTE_SETTINGS_TIMEOUT);
void updateConfigFromRemote();
ImgS3Settings();
const QString& storageLocked();
@@ -39,6 +28,8 @@ public:
QNetworkProxy* proxy();
void clearProxy();
void updateConfigurationData(const QString& data);
private:
int proxyType();
const QString& proxyHost();
@@ -48,7 +39,6 @@ private:
void initSettings();
const QString& localConfigFilePath(const QString& fileName);
void parseConfigurationData(const QString& data);
void initS3Creds();
void normalizeS3Creds();
@@ -71,9 +61,6 @@ private:
int m_proxyPort;
QString m_proxyUser;
QString m_proxyPassword;
//
QNetworkAccessManager* m_networkConfig;
};
#endif // IMG_S3_SETTINGS_H

View File

@@ -1,5 +1,4 @@
// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors
// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors
// Copyright(c) 2017-2019 Namecheap inc.
//
// This file is part of Flameshot.
//
@@ -59,6 +58,10 @@ ImgS3Uploader::ImgS3Uploader(QWidget* parent)
ImgS3Uploader::~ImgS3Uploader()
{
clearProxy();
cleanNetworkAccessManagers();
if (nullptr != m_networkAMConfig) {
delete m_networkAMConfig;
}
}
void ImgS3Uploader::init(const QString& title, const QString& label)
@@ -67,6 +70,7 @@ void ImgS3Uploader::init(const QString& title, const QString& label)
m_networkAMUpload = nullptr;
m_networkAMGetCreds = nullptr;
m_networkAMRemove = nullptr;
m_networkAMConfig = nullptr;
resultStatus = false;
setWindowTitle(title);
@@ -161,17 +165,7 @@ void ImgS3Uploader::handleReplyGetCreds(QNetworkReply* reply)
} else {
if (m_s3Settings.credsUrl().length() == 0) {
setInfoLabelText(
tr("Retrieving configuration file with s3 creds..."));
if (!m_s3Settings.getConfigRemote()) {
retry();
}
hide();
if (!m_s3Settings.credsUrl().isEmpty()) {
setInfoLabelText(tr("Uploading Image..."));
upload();
return;
}
tr("S3 Creds URL is not found in your configuration file"));
} else {
setInfoLabelText(reply->errorString());
}
@@ -180,25 +174,6 @@ void ImgS3Uploader::handleReplyGetCreds(QNetworkReply* reply)
new QShortcut(Qt::Key_Escape, this, SLOT(close()));
}
void ImgS3Uploader::retry()
{
setInfoLabelText(
tr("S3 Creds URL is not found in your configuration file"));
if (QMessageBox::Retry ==
QMessageBox::question(nullptr,
tr("Error"),
tr("Unable to get s3 credentials, please check "
"your VPN connection and try again"),
QMessageBox::Retry | QMessageBox::Cancel)) {
setInfoLabelText(tr("Retrieving configuration file with s3 creds..."));
if (!m_s3Settings.getConfigRemote()) {
retry();
}
} else {
hide();
}
}
void ImgS3Uploader::uploadToS3(QJsonDocument& response)
{
// set parameters from "fields"
@@ -281,11 +256,25 @@ void ImgS3Uploader::upload()
{
m_deleteToken.clear();
m_storageImageName.clear();
show();
// read network settings on each call to simplify configuration management
// without restarting init creds and upload network access managers
clearProxy();
// check for outdated s3 creds
ConfigHandler configHandler;
QString credsUpdated =
configHandler.value("S3", "S3_CREDS_UPDATED").toString();
QDateTime dtCredsUpdated =
QDateTime::currentDateTime().fromString(credsUpdated, Qt::ISODate);
QDateTime now = QDateTime::currentDateTime();
dtCredsUpdated = dtCredsUpdated.addDays(1);
if (m_s3Settings.credsUrl().isEmpty() || dtCredsUpdated <= now) {
getConfigRemote();
return;
}
// clean old network connections and start uploading
cleanNetworkAccessManagers();
m_networkAMGetCreds = new QNetworkAccessManager(this);
@@ -345,4 +334,53 @@ void ImgS3Uploader::cleanNetworkAccessManagers()
delete m_networkAMRemove;
m_networkAMRemove = nullptr;
}
}
if (nullptr != m_multiPart) {
delete m_multiPart;
m_multiPart = nullptr;
}
}
void ImgS3Uploader::getConfigRemote()
{
if (nullptr == m_networkAMConfig) {
m_networkAMConfig = new QNetworkAccessManager(this);
connect(m_networkAMConfig,
&QNetworkAccessManager::finished,
this,
&ImgS3Uploader::handleReplyGetConfig);
if (proxy() != nullptr) {
m_networkAMConfig->setProxy(*proxy());
}
}
QNetworkRequest requestConfig(QUrl(S3_REMOTE_CONFIG_URL));
m_networkAMConfig->get(requestConfig);
}
void ImgS3Uploader::handleReplyGetConfig(QNetworkReply* reply)
{
if (reply->error() == QNetworkReply::NoError) {
bool doUpload = m_s3Settings.credsUrl().isEmpty();
QString data = QString(reply->readAll());
m_s3Settings.updateConfigurationData(data);
if (doUpload) {
upload();
} else {
hide();
}
} else {
QString message = reply->errorString() + "\n\n" +
tr("Unable to get s3 credentials, please check "
"your VPN connection and try again");
if (QMessageBox::Retry ==
QMessageBox::question(nullptr,
tr("Error"),
message,
QMessageBox::Retry | QMessageBox::Cancel)) {
setInfoLabelText(
tr("Retrieving configuration file with s3 creds..."));
getConfigRemote();
return;
}
hide();
}
}

View File

@@ -1,4 +1,4 @@
// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors
// Copyright(c) 2017-2019 Namecheap inc.
//
// This file is part of Flameshot.
//
@@ -22,6 +22,10 @@
#include <QUrl>
#include <QWidget>
#define S3_REMOTE_CONFIG_URL \
"https://git.namecheap.net/projects/RND/repos/flameshot_config/raw/" \
"config.ini"
class QNetworkReply;
class QNetworkProxy;
class QNetworkAccessManager;
@@ -48,12 +52,13 @@ private slots:
void handleReplyPostUpload(QNetworkReply* reply);
void handleReplyGetCreds(QNetworkReply* reply);
void handleReplyDeleteResource(QNetworkReply* reply);
void handleReplyGetConfig(QNetworkReply* reply);
private:
void init(const QString& title, const QString& label);
void uploadToS3(QJsonDocument& response);
void removeImagePreview();
void retry();
void getConfigRemote();
void clearProxy();
QNetworkProxy* proxy();
@@ -67,4 +72,5 @@ private:
QNetworkAccessManager* m_networkAMGetCreds;
QNetworkAccessManager* m_networkAMRemove;
QHttpMultiPart* m_multiPart;
QNetworkAccessManager* m_networkAMConfig;
};