Backup/restore config

This commit is contained in:
pokamest 2022-08-05 18:59:47 +03:00
parent 71b57bfed1
commit 1e85b25438
12 changed files with 155 additions and 105 deletions

View file

@ -148,21 +148,7 @@ int main(int argc, char *argv[])
Settings settingsTemp; Settings settingsTemp;
} }
QSettings oldSettings(ORGANIZATION_NAME, APPLICATION_NAME);
QSettings newSettings(QSettings::Format::CustomFormat1, QSettings::UserScope,
ORGANIZATION_NAME, APPLICATION_NAME);
// QString newSettingsFileName = newSettings.fileName();
// QFile::remove(newSettingsFileName);
if (!oldSettings.allKeys().isEmpty() && newSettings.allKeys().isEmpty()) {
QString oldSettingsFileName = oldSettings.fileName();
QString newSettingsFileName = newSettings.fileName();
qDebug() << "oldSettingsFileName:" << oldSettingsFileName << QFile::exists(oldSettingsFileName) << oldSettings.isWritable();
qDebug() << "newSettingsFileName:" << newSettingsFileName << QFile::exists(newSettingsFileName) << newSettings.isWritable();
SecureFormat::chiperSettings(oldSettings, newSettings);
}
// MobileUtils::writeToKeychain("testKey", "12345"); // MobileUtils::writeToKeychain("testKey", "12345");
// qDebug() << "MobileUtils::readFromKeychain(\"testKey\"):" << MobileUtils::readFromKeychain("testKey"); // qDebug() << "MobileUtils::readFromKeychain(\"testKey\"):" << MobileUtils::readFromKeychain("testKey");

View file

@ -2,34 +2,52 @@
#include "secureformat.h" #include "secureformat.h"
#include <QDataStream> #include <QDataStream>
#include <QDebug>
SecureQSettings::SecureQSettings(const QString &organization, const QString &application, QObject *parent) SecureQSettings::SecureQSettings(const QString &organization, const QString &application, QObject *parent)
: QObject{parent}, : QObject{parent},
m_setting(organization, application, parent) m_setting(organization, application, parent),
encryptedKeys({"Servers/serversList"})
{ {
encrypted = m_setting.value("encrypted").toBool(); encrypted = m_setting.value("Conf/encrypted").toBool();
// convert settings to encrypted // convert settings to encrypted
if (! encrypted) { if (! encrypted) {
// TODO: convert for (const QString &key : m_setting.allKeys()) {
// m_setting.sync(); if (encryptedKeys.contains(key)) {
const QVariant &val = value(key);
setValue(key, val);
}
}
m_setting.setValue("Conf/encrypted", true);
m_setting.sync();
encrypted = true;
} }
} }
QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue) const QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue) const
{ {
if (encrypted) { if (m_cache.contains(key)) {
QByteArray encryptedValue = m_setting.value(key, defaultValue).toByteArray(); return m_cache.value(key);
}
QVariant retVal;
if (encrypted && encryptedKeys.contains(key)) {
if (!m_setting.contains(key)) return defaultValue;
QByteArray encryptedValue = m_setting.value(key).toByteArray();
QByteArray decryptedValue = decryptText(encryptedValue); QByteArray decryptedValue = decryptText(encryptedValue);
QDataStream ds(&decryptedValue, QIODevice::ReadOnly); QDataStream ds(&decryptedValue, QIODevice::ReadOnly);
QVariant v; ds >> retVal;
ds >> v;
return v;
} }
else { else {
return m_setting.value(key, defaultValue); retVal = m_setting.value(key, defaultValue);
} }
m_cache.insert(key, retVal);
return retVal;
} }
void SecureQSettings::setValue(const QString &key, const QVariant &value) void SecureQSettings::setValue(const QString &key, const QVariant &value)
@ -42,6 +60,55 @@ void SecureQSettings::setValue(const QString &key, const QVariant &value)
QByteArray encryptedValue = encryptText(decryptedValue); QByteArray encryptedValue = encryptText(decryptedValue);
m_setting.setValue(key, encryptedValue); m_setting.setValue(key, encryptedValue);
m_cache.insert(key, value);
sync();
}
void SecureQSettings::remove(const QString &key)
{
m_setting.remove(key);
m_cache.remove(key);
sync();
}
void SecureQSettings::sync()
{
m_setting.sync();
}
QByteArray SecureQSettings::backupAppConfig() const
{
QMap<QString, QVariant> cfg;
for (const QString &key : m_setting.allKeys()) {
cfg.insert(key, value(key));
}
QByteArray ba;
{
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << cfg;
}
return ba.toBase64();
}
void SecureQSettings::restoreAppConfig(const QByteArray &base64Cfg)
{
QByteArray ba = QByteArray::fromBase64(base64Cfg);
QMap<QString, QVariant> cfg;
{
QDataStream ds(&ba, QIODevice::ReadOnly);
ds >> cfg;
}
for (const QString &key : cfg.keys()) {
setValue(key, cfg.value(key));
}
sync();
} }

View file

@ -11,12 +11,19 @@ public:
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
void setValue(const QString &key, const QVariant &value); void setValue(const QString &key, const QVariant &value);
void sync() { m_setting.sync(); } void remove(const QString &key);
void remove(const QString &key) { m_setting.remove(key); } void sync();
QByteArray backupAppConfig() const;
void restoreAppConfig(const QByteArray &base64Cfg);
private: private:
QSettings m_setting; QSettings m_setting;
bool encrypted {false}; bool encrypted {false};
mutable QMap<QString, QVariant> m_cache;
QStringList encryptedKeys; // encode only key listed here
}; };
#endif // SECUREQSETTINGS_H #endif // SECUREQSETTINGS_H

View file

@ -148,71 +148,7 @@ QByteArray decryptText(const QByteArray& qEncryptArray) {
return QByteArray::fromRawData((const char *)decryptPlainText, qEncryptArray.size()); return QByteArray::fromRawData((const char *)decryptPlainText, qEncryptArray.size());
} }
SecureFormat::SecureFormat()
{
m_format = QSettings::registerFormat("sconf",
readSecureFile,
writeSecureFile);
qDebug() << "SecureFormat" << m_format;
}
bool SecureFormat::readSecureFile(QIODevice& device, QSettings::SettingsMap& map) {
if (!device.isOpen()) {
return false;
}
QTextStream inStream(&device);
while (!inStream.atEnd()) {
QString line = inStream.readLine();
QStringList keyValue = line.split("<=>");
QString key = keyValue.first();
QString value = decryptText(keyValue.last().toUtf8());
map.insert(key, value);
qDebug() << "SecureFormat::readSecureFile: " << key << "<=>" << value;
}
return true;
}
bool SecureFormat::writeSecureFile(QIODevice& device, const QSettings::SettingsMap& map) {
// if (!device.isOpen()) {
// return false;
// }
// QTextStream outStream(&device);
// auto keys = map.keys();
// for (auto key : keys) {
// QString value = map.value(key).toString();
// QByteArray qEncryptArray = encryptText(value);
// outStream << key << "<=>" << qEncryptArray << "\n";
// qDebug() << "SecureFormat::writeSecureFile: " << key << "<=>" << qEncryptArray;
// }
return true;
}
void SecureFormat::chiperSettings(const QSettings &oldSetting, QSettings &newSetting) {
// QVariantMap keysValuesPairs;
// QStringList keys = oldSetting.allKeys();
// QStringListIterator it(keys);
// while ( it.hasNext() ) {
// QString currentKey = it.next();
// keysValuesPairs.insert(currentKey, oldSetting.value(currentKey));
// }
// for (const QString& key : keys) {
// QString value = keysValuesPairs.value(key).toString();
// QByteArray qEncryptArray = encryptText(value);
// newSetting.setValue(key, qEncryptArray);
// }
// newSetting.sync();
}
const QSettings::Format& SecureFormat::format() const{
return m_format;
}

View file

@ -12,15 +12,9 @@ class SecureFormat
public: public:
SecureFormat(); SecureFormat();
static bool readSecureFile(QIODevice &device, QSettings::SettingsMap &map);
static bool writeSecureFile(QIODevice &device, const QSettings::SettingsMap &map);
static void chiperSettings(const QSettings &oldSetting, QSettings &newSetting);
const QSettings::Format& format() const;
private:
QSettings::Format m_format;
}; };
#endif // SECUREFORMAT_H #endif // SECUREFORMAT_H

View file

@ -112,8 +112,10 @@ public:
// static constexpr char openNicNs5[] = "94.103.153.176"; // static constexpr char openNicNs5[] = "94.103.153.176";
// static constexpr char openNicNs13[] = "144.76.103.143"; // static constexpr char openNicNs13[] = "144.76.103.143";
QByteArray backupAppConfig() const { return m_settings.backupAppConfig(); }
void restoreAppConfig(const QByteArray &cfg) { m_settings.restoreAppConfig(cfg); }
private: private:
//static SecureFormat m_secureFormat;
SecureQSettings m_settings; SecureQSettings m_settings;
}; };

View file

@ -74,3 +74,26 @@ void AppSettingsLogic::onPushButtonClearLogsClicked()
Debug::clearLogs(); Debug::clearLogs();
Debug::clearServiceLogs(); Debug::clearServiceLogs();
} }
void AppSettingsLogic::onPushButtonBackupAppConfigClicked()
{
uiLogic()->saveTextFile("Backup application config", "AmneziaVPN.backup", ".backup", m_settings.backupAppConfig());
}
void AppSettingsLogic::onPushButtonRestoreAppConfigClicked()
{
QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open backup"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.backup");
if (fileName.isEmpty()) return;
QFile file(fileName);
file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll();
m_settings.restoreAppConfig(data);
emit uiLogic()->goToPage(Page::Vpn);
emit uiLogic()->setStartPage(Page::Vpn);
}

View file

@ -25,6 +25,10 @@ public:
Q_INVOKABLE void onPushButtonExportLogsClicked(); Q_INVOKABLE void onPushButtonExportLogsClicked();
Q_INVOKABLE void onPushButtonClearLogsClicked(); Q_INVOKABLE void onPushButtonClearLogsClicked();
Q_INVOKABLE void onPushButtonBackupAppConfigClicked();
Q_INVOKABLE void onPushButtonRestoreAppConfigClicked();
public: public:
explicit AppSettingsLogic(UiLogic *uiLogic, QObject *parent = nullptr); explicit AppSettingsLogic(UiLogic *uiLogic, QObject *parent = nullptr);
~AppSettingsLogic() = default; ~AppSettingsLogic() = default;

View file

@ -24,7 +24,6 @@ StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent):
m_labelWaitInfoVisible{true}, m_labelWaitInfoVisible{true},
m_labelWaitInfoText{}, m_labelWaitInfoText{},
m_pushButtonBackFromStartVisible{true}, m_pushButtonBackFromStartVisible{true},
m_pushButtonConnectVisible{true},
m_ipAddressPortRegex{Utils::ipAddressPortRegExp()} m_ipAddressPortRegex{Utils::ipAddressPortRegExp()}
{ {
@ -41,7 +40,6 @@ void StartPageLogic::onUpdatePage()
set_labelWaitInfoVisible(false); set_labelWaitInfoVisible(false);
set_labelWaitInfoText(""); set_labelWaitInfoText("");
set_pushButtonConnectVisible(true);
set_pushButtonConnectKeyChecked(false); set_pushButtonConnectKeyChecked(false);

View file

@ -20,7 +20,6 @@ class StartPageLogic : public PageLogicBase
AUTO_PROPERTY(bool, labelWaitInfoVisible) AUTO_PROPERTY(bool, labelWaitInfoVisible)
AUTO_PROPERTY(QString, labelWaitInfoText) AUTO_PROPERTY(QString, labelWaitInfoText)
AUTO_PROPERTY(bool, pushButtonBackFromStartVisible) AUTO_PROPERTY(bool, pushButtonBackFromStartVisible)
AUTO_PROPERTY(bool, pushButtonConnectVisible)
READONLY_PROPERTY(QRegExp, ipAddressPortRegex) READONLY_PROPERTY(QRegExp, ipAddressPortRegex)
public: public:

View file

@ -107,7 +107,7 @@ PageBase {
BlueButtonType { BlueButtonType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 15 Layout.topMargin: 10
Layout.preferredHeight: 41 Layout.preferredHeight: 41
text: qsTr("Export logs") text: qsTr("Export logs")
onClicked: { onClicked: {
@ -117,7 +117,7 @@ PageBase {
BlueButtonType { BlueButtonType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 15 Layout.topMargin: 10
Layout.preferredHeight: 41 Layout.preferredHeight: 41
property string start_text: qsTr("Clear logs") property string start_text: qsTr("Clear logs")
@ -135,6 +135,31 @@ PageBase {
AppSettingsLogic.onPushButtonClearLogsClicked() AppSettingsLogic.onPushButtonClearLogsClicked()
} }
} }
LabelType {
Layout.fillWidth: true
Layout.topMargin: 30
text: qsTr("Backup and restore configuration")
}
BlueButtonType {
Layout.fillWidth: true
Layout.topMargin: 10
Layout.preferredHeight: 41
text: qsTr("Backup app config")
onClicked: {
AppSettingsLogic.onPushButtonBackupAppConfigClicked()
}
}
BlueButtonType {
Layout.fillWidth: true
Layout.topMargin: 10
Layout.preferredHeight: 41
text: qsTr("Restore app config")
onClicked: {
AppSettingsLogic.onPushButtonRestoreAppConfigClicked()
}
}
} }
} }

View file

@ -119,7 +119,6 @@ PageBase {
anchors.topMargin: 40 anchors.topMargin: 40
text: qsTr("Open file") text: qsTr("Open file")
visible: StartPageLogic.pushButtonConnectVisible
onClicked: { onClicked: {
StartPageLogic.onPushButtonImportOpenFile() StartPageLogic.onPushButtonImportOpenFile()
} }
@ -133,7 +132,6 @@ PageBase {
anchors.topMargin: 10 anchors.topMargin: 10
text: qsTr("Scan QR code") text: qsTr("Scan QR code")
visible: StartPageLogic.pushButtonConnectVisible
onClicked: { onClicked: {
if (Qt.platform.os == "ios") { if (Qt.platform.os == "ios") {
UiLogic.goToPage(PageEnum.QrDecoderIos) UiLogic.goToPage(PageEnum.QrDecoderIos)
@ -144,7 +142,19 @@ PageBase {
enabled: StartPageLogic.pushButtonConnectEnabled enabled: StartPageLogic.pushButtonConnectEnabled
} }
BlueButtonType {
id: btn_restore_cfg
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: qr_code_import.bottom
anchors.topMargin: 30
visible: UiLogic.pagesStackDepth == 1
enabled: StartPageLogic.pushButtonConnectEnabled
text: qsTr("Restore app config")
onClicked: {
AppSettingsLogic.onPushButtonRestoreAppConfigClicked()
}
}
} }
@ -270,7 +280,6 @@ PageBase {
anchors.topMargin: 10 anchors.topMargin: 10
text: StartPageLogic.pushButtonConnectText text: StartPageLogic.pushButtonConnectText
visible: StartPageLogic.pushButtonConnectVisible
onClicked: { onClicked: {
StartPageLogic.onPushButtonConnect() StartPageLogic.onPushButtonConnect()
} }