From 25f8283edda8fcbbf0784d6860d901036cf06b46 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Thu, 12 Oct 2023 20:48:03 +0500 Subject: [PATCH 01/12] added getting the config from the cloud service --- client/CMakeLists.txt | 4 +- client/amnezia_application.cpp | 15 +- client/amnezia_application.h | 2 + client/configurators/cloak_configurator.cpp | 2 +- client/configurators/ikev2_configurator.cpp | 2 +- client/configurators/openvpn_configurator.cpp | 2 +- client/configurators/openvpn_configurator.h | 4 +- .../shadowsocks_configurator.cpp | 2 +- .../configurators/wireguard_configurator.cpp | 2 +- client/containers/containers_defs.cpp | 2 +- .../serverController.cpp} | 4 +- .../serverController.h} | 4 +- client/core/errorstrings.cpp | 2 +- client/protocols/openvpnprotocol.cpp | 2 +- client/protocols/protocols_defs.h | 8 +- client/translations/amneziavpn_ru.ts | 142 ++++++++++------- client/translations/amneziavpn_zh_CN.ts | 146 +++++++++++------- client/ui/controllers/cloudController.cpp | 109 +++++++++++++ client/ui/controllers/cloudController.h | 43 ++++++ .../ui/controllers/connectionController.cpp | 1 + client/ui/controllers/importController.cpp | 10 +- client/ui/controllers/installController.cpp | 2 +- client/ui/models/containers_model.cpp | 2 +- client/ui/models/servers_model.cpp | 13 ++ client/ui/models/servers_model.h | 3 + client/ui/qml/Components/ConnectButton.qml | 4 + client/vpnconnection.cpp | 6 +- 27 files changed, 399 insertions(+), 139 deletions(-) rename client/core/{servercontroller.cpp => controllers/serverController.cpp} (99%) rename client/core/{servercontroller.h => controllers/serverController.h} (98%) create mode 100644 client/ui/controllers/cloudController.cpp create mode 100644 client/ui/controllers/cloudController.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index cc192268..004b64f9 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -108,7 +108,7 @@ set(HEADERS ${HEADERS} ${CMAKE_CURRENT_LIST_DIR}/core/errorstrings.h ${CMAKE_CURRENT_LIST_DIR}/core/scripts_registry.h ${CMAKE_CURRENT_LIST_DIR}/core/server_defs.h - ${CMAKE_CURRENT_LIST_DIR}/core/servercontroller.h + ${CMAKE_CURRENT_LIST_DIR}/core/controllers/serverController.h ${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h ${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.h ${CMAKE_CURRENT_LIST_DIR}/ui/notificationhandler.h @@ -147,7 +147,7 @@ set(SOURCES ${SOURCES} ${CMAKE_CURRENT_LIST_DIR}/core/errorstrings.cpp ${CMAKE_CURRENT_LIST_DIR}/core/scripts_registry.cpp ${CMAKE_CURRENT_LIST_DIR}/core/server_defs.cpp - ${CMAKE_CURRENT_LIST_DIR}/core/servercontroller.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/controllers/serverController.cpp ${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/notificationhandler.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.cpp diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index d8039d9b..cb1512cc 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -139,7 +139,8 @@ void AmneziaApplication::init() &ConnectionController::openConnection); connect(m_notificationHandler.get(), &NotificationHandler::disconnectRequested, m_connectionController.get(), &ConnectionController::closeConnection); - connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(), &NotificationHandler::onTranslationsUpdated); + connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(), + &NotificationHandler::onTranslationsUpdated); m_engine->load(url); m_systemController->setQmlRoot(m_engine->rootObjects().value(0)); @@ -226,14 +227,13 @@ void AmneziaApplication::loadTranslator() updateTranslator(locale); } - void AmneziaApplication::updateTranslator(const QLocale &locale) { if (!m_translator->isEmpty()) { QCoreApplication::removeTranslator(m_translator.get()); } - QString strFileName = QString(":/translations/amneziavpn")+QLatin1String("_")+locale.name()+".qm"; + QString strFileName = QString(":/translations/amneziavpn") + QLatin1String("_") + locale.name() + ".qm"; if (m_translator->load(strFileName)) { if (QCoreApplication::installTranslator(m_translator.get())) { m_settings->setAppLanguage(locale); @@ -330,7 +330,8 @@ void AmneziaApplication::initControllers() m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel, m_vpnConnection)); m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get()); - connect(this, &AmneziaApplication::translationsUpdated, m_connectionController.get(), &ConnectionController::onTranslationsUpdated); + connect(this, &AmneziaApplication::translationsUpdated, m_connectionController.get(), + &ConnectionController::onTranslationsUpdated); m_pageController.reset(new PageController(m_serversModel, m_settings)); m_engine->rootContext()->setContextProperty("PageController", m_pageController.get()); @@ -361,4 +362,10 @@ void AmneziaApplication::initControllers() m_systemController.reset(new SystemController(m_settings)); m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get()); + + m_cloudController.reset(new CloudController(m_serversModel, m_containersModel)); + m_engine->rootContext()->setContextProperty("CloudController", m_cloudController.get()); + + connect(m_cloudController.get(), &CloudController::serverConfigUpdated, this, + [this]() { m_containersModel->setCurrentlyProcessedServerIndex(m_serversModel->getDefaultServerIndex()); }); } diff --git a/client/amnezia_application.h b/client/amnezia_application.h index 2dd74fcb..394ff943 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -24,6 +24,7 @@ #include "ui/controllers/settingsController.h" #include "ui/controllers/sitesController.h" #include "ui/controllers/systemController.h" +#include "ui/controllers/cloudController.h" #include "ui/models/containers_model.h" #include "ui/models/languageModel.h" #include "ui/models/protocols/cloakConfigModel.h" @@ -116,6 +117,7 @@ private: QScopedPointer m_settingsController; QScopedPointer m_sitesController; QScopedPointer m_systemController; + QScopedPointer m_cloudController; }; #endif // AMNEZIA_APPLICATION_H diff --git a/client/configurators/cloak_configurator.cpp b/client/configurators/cloak_configurator.cpp index fab378e2..9c540967 100644 --- a/client/configurators/cloak_configurator.cpp +++ b/client/configurators/cloak_configurator.cpp @@ -4,7 +4,7 @@ #include #include -#include "core/servercontroller.h" +#include "core/controllers/serverController.h" #include "containers/containers_defs.h" CloakConfigurator::CloakConfigurator(std::shared_ptr settings, QObject *parent): diff --git a/client/configurators/ikev2_configurator.cpp b/client/configurators/ikev2_configurator.cpp index 4ca0e5da..752d1750 100644 --- a/client/configurators/ikev2_configurator.cpp +++ b/client/configurators/ikev2_configurator.cpp @@ -11,7 +11,7 @@ #include "containers/containers_defs.h" #include "core/scripts_registry.h" #include "core/server_defs.h" -#include "core/servercontroller.h" +#include "core/controllers/serverController.h" #include "utilities.h" Ikev2Configurator::Ikev2Configurator(std::shared_ptr settings, QObject *parent) diff --git a/client/configurators/openvpn_configurator.cpp b/client/configurators/openvpn_configurator.cpp index a62bdd9c..e45c8506 100644 --- a/client/configurators/openvpn_configurator.cpp +++ b/client/configurators/openvpn_configurator.cpp @@ -16,7 +16,7 @@ #include "containers/containers_defs.h" #include "core/scripts_registry.h" #include "core/server_defs.h" -#include "core/servercontroller.h" +#include "core/controllers/serverController.h" #include "settings.h" #include "utilities.h" diff --git a/client/configurators/openvpn_configurator.h b/client/configurators/openvpn_configurator.h index 3b84e0a0..342bf753 100644 --- a/client/configurators/openvpn_configurator.h +++ b/client/configurators/openvpn_configurator.h @@ -32,9 +32,9 @@ public: ErrorCode signCert(DockerContainer container, const ServerCredentials &credentials, QString clientId); -private: - ConnectionData createCertRequest(); + static ConnectionData createCertRequest(); +private: ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, ErrorCode *errorCode = nullptr); diff --git a/client/configurators/shadowsocks_configurator.cpp b/client/configurators/shadowsocks_configurator.cpp index a71064c8..99e4158c 100644 --- a/client/configurators/shadowsocks_configurator.cpp +++ b/client/configurators/shadowsocks_configurator.cpp @@ -5,7 +5,7 @@ #include #include "containers/containers_defs.h" -#include "core/servercontroller.h" +#include "core/controllers/serverController.h" ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr settings, QObject *parent): ConfiguratorBase(settings, parent) diff --git a/client/configurators/wireguard_configurator.cpp b/client/configurators/wireguard_configurator.cpp index 14059977..7b7d94d2 100644 --- a/client/configurators/wireguard_configurator.cpp +++ b/client/configurators/wireguard_configurator.cpp @@ -15,7 +15,7 @@ #include "containers/containers_defs.h" #include "core/scripts_registry.h" #include "core/server_defs.h" -#include "core/servercontroller.h" +#include "core/controllers/serverController.h" #include "settings.h" #include "utilities.h" diff --git a/client/containers/containers_defs.cpp b/client/containers/containers_defs.cpp index 20fc59f4..d2231415 100644 --- a/client/containers/containers_defs.cpp +++ b/client/containers/containers_defs.cpp @@ -54,7 +54,7 @@ QVector ContainerProps::protocolsForContainer(amnezia::DockerCon case DockerContainer::ShadowSocks: return { Proto::OpenVpn, Proto::ShadowSocks }; - case DockerContainer::Cloak: return { Proto::OpenVpn, Proto::ShadowSocks, Proto::Cloak }; + case DockerContainer::Cloak: return { Proto::OpenVpn, /*Proto::ShadowSocks,*/ Proto::Cloak }; case DockerContainer::Ipsec: return { Proto::Ikev2 /*, Protocol::L2tp */ }; diff --git a/client/core/servercontroller.cpp b/client/core/controllers/serverController.cpp similarity index 99% rename from client/core/servercontroller.cpp rename to client/core/controllers/serverController.cpp index b0f8146f..96306a58 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/controllers/serverController.cpp @@ -24,8 +24,8 @@ #include "containers/containers_defs.h" #include "logger.h" -#include "scripts_registry.h" -#include "server_defs.h" +#include "core/scripts_registry.h" +#include "core/server_defs.h" #include "settings.h" #include "utilities.h" diff --git a/client/core/servercontroller.h b/client/core/controllers/serverController.h similarity index 98% rename from client/core/servercontroller.h rename to client/core/controllers/serverController.h index 3191386c..ea6fd001 100644 --- a/client/core/servercontroller.h +++ b/client/core/controllers/serverController.h @@ -5,8 +5,8 @@ #include #include "containers/containers_defs.h" -#include "defs.h" -#include "sshclient.h" +#include "core/defs.h" +#include "core/sshclient.h" class Settings; class VpnConfigurator; diff --git a/client/core/errorstrings.cpp b/client/core/errorstrings.cpp index cd66186d..44135bae 100644 --- a/client/core/errorstrings.cpp +++ b/client/core/errorstrings.cpp @@ -58,7 +58,7 @@ QString errorString(ErrorCode code){ case (OpenVpnTapAdapterError): return QObject::tr("Can't setup OpenVPN TAP network adapter"); case (AddressPoolError): return QObject::tr("VPN pool error: no available addresses"); - case (ImportInvalidConfigError): return QObject::tr("The config does not contain any containers and credentiaks for connecting to the server"); + case (ImportInvalidConfigError): return QObject::tr("The config does not contain any containers and credentials for connecting to the server"); case(InternalError): default: diff --git a/client/protocols/openvpnprotocol.cpp b/client/protocols/openvpnprotocol.cpp index c38c6eea..f91cfe09 100644 --- a/client/protocols/openvpnprotocol.cpp +++ b/client/protocols/openvpnprotocol.cpp @@ -214,7 +214,7 @@ ErrorCode OpenVpnProtocol::start() m_openVpnProcess->setProgram(PermittedProcess::OpenVPN); QStringList arguments({ "--config", configPath(), "--management", m_managementHost, QString::number(mgmtPort), - "--management-client" /*, "--log", vpnLogFileNamePath */ + "--management-client" , "--log", "/Users/nethius/Documents/git/log" }); m_openVpnProcess->setArguments(arguments); diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 9472164b..fa326b2a 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -67,7 +67,13 @@ namespace amnezia constexpr char cloak[] = "cloak"; constexpr char sftp[] = "sftp"; - } + constexpr char configVersion[] = "config_version"; + constexpr char apiEdnpoint[] = "api_endpoint"; + constexpr char serviceTypeId[] = "service_type_id"; + constexpr char accessToken[] = "access_token"; + constexpr char certificate[] = "certificate"; + constexpr char publicKey[] = "public_key"; + } namespace protocols { diff --git a/client/translations/amneziavpn_ru.ts b/client/translations/amneziavpn_ru.ts index e0bab018..20a7f022 100644 --- a/client/translations/amneziavpn_ru.ts +++ b/client/translations/amneziavpn_ru.ts @@ -23,44 +23,52 @@ + + CloudController + + + Error when retrieving configuration from cloud server + + + ConnectionController - + VPN Protocols is not installed. Please install VPN container at first - + Connection... - + Connected - + Settings updated successfully, Reconnnection... - + Reconnection... - - - + + + Connect - + Disconnection... @@ -130,7 +138,7 @@ ImportController - + Scanned %1 of %2. @@ -139,50 +147,55 @@ InstallController - + %1 installed successfully. - + %1 is already installed on the server. - + +Added containers that were already installed on the server + + + + Already installed containers were found on the server. All installed containers have been added to the application - + Settings updated successfully - + Server '%1' was removed - + All containers from server '%1' have been removed - + %1 has been removed from the server '%2' - + Please login as the user - + Server added successfully @@ -250,12 +263,12 @@ Already installed containers were found on the server. All installed containers PageHome - + VPN protocol - + Servers @@ -865,71 +878,76 @@ And if you don't like the app, all the more support it - the donation will + Allow application screenshots + + + + Auto start - + Launch the application every time - + starts - + Start minimized - + Launch application minimized - + Language - + Logging - + Enabled - + Disabled - + Reset settings and remove all data from the application - + Reset settings and remove all data from the application? - + All settings will be reset to default. All installed AmneziaVPN services will still remain on the server. - + Continue Продолжить - + Cancel @@ -1525,17 +1543,17 @@ It's okay as long as it's from someone you trust. PageSetupWizardEasy - + What is the level of internet control in your region? - + Set up a VPN yourself - + I want to choose a VPN protocol @@ -1545,7 +1563,7 @@ It's okay as long as it's from someone you trust. Продолжить - + Set up later @@ -1765,13 +1783,17 @@ It's okay as long as it's from someone you trust. - + + File with accessing settings to + + + + Connection to - - + File with connection settings to @@ -1801,23 +1823,19 @@ It's okay as long as it's from someone you trust. - - Protocols - - - - + + Protocol - - + + Connection format - + Share @@ -2264,7 +2282,7 @@ It's okay as long as it's from someone you trust. - The config does not contain any containers and credentiaks for connecting to the server + The config does not contain any containers and credentials for connecting to the server @@ -2433,6 +2451,16 @@ It's okay as long as it's from someone you trust. error 0x%1: %2 + + + WireGuard Configuration Highlighter + + + + + &Randomize colors + + SelectLanguageDrawer @@ -2459,22 +2487,22 @@ It's okay as long as it's from someone you trust. SettingsController - + Software version - + All settings have been reset to default values - + Cached profiles cleared - + Backup file is corrupted @@ -2504,7 +2532,7 @@ It's okay as long as it's from someone you trust. - Show content + Show connection settings @@ -2592,7 +2620,7 @@ It's okay as long as it's from someone you trust. VpnConnection - + Mbps diff --git a/client/translations/amneziavpn_zh_CN.ts b/client/translations/amneziavpn_zh_CN.ts index 37e27786..109ad9c8 100644 --- a/client/translations/amneziavpn_zh_CN.ts +++ b/client/translations/amneziavpn_zh_CN.ts @@ -23,44 +23,52 @@ VPN已连接 + + CloudController + + + Error when retrieving configuration from cloud server + + + ConnectionController - - - + + + Connect 连接 - + VPN Protocols is not installed. Please install VPN container at first 不存在VPN协议,请先安装 - + Connection... 连接中 - + Connected 已连接 - + Reconnection... 重连中 - + Disconnection... 断开中 - + Settings updated successfully, Reconnnection... 配置已更新,重连中 @@ -130,7 +138,7 @@ ImportController - + Scanned %1 of %2. 扫描 %1 of %2. @@ -147,41 +155,46 @@ - + %1 installed successfully. %1 安装成功。 - + %1 is already installed on the server. 服务器上已经安装 %1。 - + +Added containers that were already installed on the server + + + + Already installed containers were found on the server. All installed containers have been added to the application 在服务上发现已经安装协议并添加到应用程序 - + Settings updated successfully 配置更新成功 - + Server '%1' was removed 已移除服务器 '%1' - + All containers from server '%1' have been removed 服务器 '%1' 的所有容器已移除 - + %1 has been removed from the server '%2' %1 已从服务器 '%2' 上移除 @@ -202,12 +215,12 @@ Already installed containers were found on the server. All installed containers 协议已从 - + Please login as the user 请以用户身份登录 - + Server added successfully 服务器添加成功 @@ -275,12 +288,12 @@ Already installed containers were found on the server. All installed containers PageHome - + VPN protocol VPN协议 - + Servers 服务器 @@ -892,71 +905,76 @@ And if you don't like the app, all the more support it - the donation will + Allow application screenshots + + + + Auto start 自动运行 - + Launch the application every time 总是在系统 - + starts 启动时自动运行运用程序 - + Start minimized 最小化 - + Launch application minimized 开启应用程序时窗口最小化 - + Language 语言 - + Logging 日志 - + Enabled 开启 - + Disabled 禁用 - + Reset settings and remove all data from the application 重置并清理应用的所有数据 - + Reset settings and remove all data from the application? 重置并清理应用的所有数据? - + All settings will be reset to default. All installed AmneziaVPN services will still remain on the server. 所有配置恢复为默认值。在服务器上保留所有已安装的AmneziaVPN服务。 - + Continue 继续 - + Cancel 取消 @@ -1561,17 +1579,17 @@ It's okay as long as it's from someone you trust. PageSetupWizardEasy - + What is the level of internet control in your region? 您所在地区的互联网控制力度如何? - + Set up a VPN yourself 自己架设VPN - + I want to choose a VPN protocol 我想选择VPN协议 @@ -1581,7 +1599,7 @@ It's okay as long as it's from someone you trust. 继续 - + Set up later 稍后设置 @@ -1827,33 +1845,37 @@ It's okay as long as it's from someone you trust. - + File with accessing settings to + + + + File with connection settings to 连接配置文件的内容为: - Protocols - 协议 + 协议 - + + Protocol 协议 - + Connection to 连接到 - - + + Connection format 连接方式 - + Share 共享 @@ -2305,8 +2327,12 @@ It's okay as long as it's from someone you trust. + The config does not contain any containers and credentials for connecting to the server + + + The config does not contain any containers and credentiaks for connecting to the server - 该配置不包含任何用于连接到服务器的容器和凭据。 + 该配置不包含任何用于连接到服务器的容器和凭据。 @@ -2469,6 +2495,16 @@ It's okay as long as it's from someone you trust. error 0x%1: %2 错误 0x%1: %2 + + + WireGuard Configuration Highlighter + + + + + &Randomize colors + + SelectLanguageDrawer @@ -2495,22 +2531,22 @@ It's okay as long as it's from someone you trust. SettingsController - + Software version 软件版本 - + Backup file is corrupted 备份文件已损坏 - + All settings have been reset to default values 所配置恢复为默认值 - + Cached profiles cleared 缓存的配置文件已清除 @@ -2540,8 +2576,12 @@ It's okay as long as it's from someone you trust. + Show connection settings + + + Show content - 展示内容 + 展示内容 @@ -2628,7 +2668,7 @@ It's okay as long as it's from someone you trust. VpnConnection - + Mbps diff --git a/client/ui/controllers/cloudController.cpp b/client/ui/controllers/cloudController.cpp new file mode 100644 index 00000000..99309d90 --- /dev/null +++ b/client/ui/controllers/cloudController.cpp @@ -0,0 +1,109 @@ +#include "cloudController.h" + +#include +#include +#include + +#include "configurators/openvpn_configurator.h" + +CloudController::CloudController(const QSharedPointer &serversModel, + const QSharedPointer &containersModel, QObject *parent) + : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel) +{ +} + +QString CloudController::genPublicKey(ServiceTypeId serviceTypeId) +{ + switch (serviceTypeId) + { + case ServiceTypeId::AmneziaFreeRuWG: return "."; + case ServiceTypeId::AmneziaFreeRuCloak: return "."; + case ServiceTypeId::AmneziaFreeRuAWG: return "."; + case ServiceTypeId::AmneziaFreeRuReverseWG: return "."; + case ServiceTypeId::AmneziaFreeRuReverseCloak: return "."; + case ServiceTypeId::AmneziaFreeRuReverseAWG: return "."; + } +} + +QString CloudController::genCertificateRequest(ServiceTypeId serviceTypeId) +{ + switch (serviceTypeId) + { + case ServiceTypeId::AmneziaFreeRuWG: return ""; + case ServiceTypeId::AmneziaFreeRuCloak: { + auto data = OpenVpnConfigurator::createCertRequest(); + return data.request; + } + case ServiceTypeId::AmneziaFreeRuAWG: return ""; + case ServiceTypeId::AmneziaFreeRuReverseWG: return ""; + case ServiceTypeId::AmneziaFreeRuReverseCloak: return ""; + case ServiceTypeId::AmneziaFreeRuReverseAWG: return ""; + } +} + +bool CloudController::updateServerConfigFromCloud() +{ + auto serverConfig = m_serversModel->getDefaultServerConfig(); + + auto containerConfig = serverConfig.value(config_key::containers).toArray(); + + if (serverConfig.value(config_key::configVersion).toInt() && containerConfig.isEmpty()) { + QNetworkAccessManager manager; + + QNetworkRequest request; + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + QString endpoint = serverConfig.value(config_key::apiEdnpoint).toString(); + request.setUrl(endpoint.replace("https", "http")); // + + ServiceTypeId serviceTypeId = static_cast(serverConfig.value(config_key::serviceTypeId).toInt()); + + QJsonObject obj; + obj[config_key::serviceTypeId] = serviceTypeId; + obj[config_key::accessToken] = serverConfig.value(config_key::accessToken); + + obj[config_key::publicKey] = genPublicKey(serviceTypeId); + obj[config_key::certificate] = genCertificateRequest(serviceTypeId); + + QByteArray requestBody = QJsonDocument(obj).toJson(); + + QScopedPointer reply; + reply.reset(manager.post(request, requestBody)); + + QEventLoop wait; + QObject::connect(reply.get(), &QNetworkReply::finished, &wait, &QEventLoop::quit); + wait.exec(); + + if(reply->error() == QNetworkReply::NoError){ + QString contents = QString::fromUtf8(reply->readAll()); + auto data = QJsonDocument::fromJson(contents.toUtf8()).object().value(config_key::config).toString(); + + data.replace("vpn://", ""); + QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); + + QByteArray ba_uncompressed = qUncompress(ba); + if (!ba_uncompressed.isEmpty()) { + ba = ba_uncompressed; + } + + QJsonObject cloudConfig = QJsonDocument::fromJson(ba).object(); + serverConfig.insert("cloudConfig", cloudConfig); + serverConfig.insert(config_key::dns1, cloudConfig.value(config_key::dns1)); + serverConfig.insert(config_key::dns2, cloudConfig.value(config_key::dns2)); + serverConfig.insert(config_key::containers, cloudConfig.value(config_key::containers)); + serverConfig.insert(config_key::hostName, cloudConfig.value(config_key::hostName)); + serverConfig.insert(config_key::defaultContainer, cloudConfig.value(config_key::defaultContainer)); + m_serversModel->editServer(serverConfig); + emit serverConfigUpdated(); + } else{ + QString err = reply->errorString(); + qDebug() << reply->error(); + qDebug() << err; + qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); + emit errorOccurred(tr("Error when retrieving configuration from cloud server")); + return false; + } + + } + + return true; +} diff --git a/client/ui/controllers/cloudController.h b/client/ui/controllers/cloudController.h new file mode 100644 index 00000000..409e0981 --- /dev/null +++ b/client/ui/controllers/cloudController.h @@ -0,0 +1,43 @@ +#ifndef CLOUDCONTROLLER_H +#define CLOUDCONTROLLER_H + +#include + +#include "ui/models/containers_model.h" +#include "ui/models/servers_model.h" + +class CloudController : public QObject +{ + Q_OBJECT + + enum ServiceTypeId + { + AmneziaFreeRuWG = 0, + AmneziaFreeRuCloak, + AmneziaFreeRuAWG, + AmneziaFreeRuReverseWG, + AmneziaFreeRuReverseCloak, + AmneziaFreeRuReverseAWG + + }; + +public: + explicit CloudController(const QSharedPointer &serversModel, + const QSharedPointer &containersModel, QObject *parent = nullptr); + +public slots: + bool updateServerConfigFromCloud(); + +signals: + void errorOccurred(const QString &errorMessage); + void serverConfigUpdated(); + +private: + QString genPublicKey(ServiceTypeId serviceTypeId); + QString genCertificateRequest(ServiceTypeId serviceTypeId); + + QSharedPointer m_serversModel; + QSharedPointer m_containersModel; +}; + +#endif // CLOUDCONTROLLER_H diff --git a/client/ui/controllers/connectionController.cpp b/client/ui/controllers/connectionController.cpp index 74438dcc..de05d624 100644 --- a/client/ui/controllers/connectionController.cpp +++ b/client/ui/controllers/connectionController.cpp @@ -40,6 +40,7 @@ void ConnectionController::openConnection() } qApp->processEvents(); + emit connectToVpn(serverIndex, credentials, container, containerConfig); } diff --git a/client/ui/controllers/importController.cpp b/client/ui/controllers/importController.cpp index aaea8db3..8198a5a1 100644 --- a/client/ui/controllers/importController.cpp +++ b/client/ui/controllers/importController.cpp @@ -141,7 +141,9 @@ void ImportController::importConfig() credentials.userName = m_config.value(config_key::userName).toString(); credentials.secretData = m_config.value(config_key::password).toString(); - if (credentials.isValid() || m_config.contains(config_key::containers)) { + if (credentials.isValid() + || m_config.contains(config_key::containers) + || m_config.contains(config_key::configVersion)) { // todo m_serversModel->addServer(m_config); m_serversModel->setDefaultServerIndex(m_serversModel->getServersCount() - 1); @@ -167,7 +169,11 @@ QJsonObject ImportController::extractAmneziaConfig(QString &data) ba = ba_uncompressed; } - return QJsonDocument::fromJson(ba).object(); + QJsonObject config = QJsonDocument::fromJson(ba).object(); + + qDebug() << config; + + return config; } QJsonObject ImportController::extractOpenVpnConfig(const QString &data) diff --git a/client/ui/controllers/installController.cpp b/client/ui/controllers/installController.cpp index 72cc34b6..4885aa80 100644 --- a/client/ui/controllers/installController.cpp +++ b/client/ui/controllers/installController.cpp @@ -7,7 +7,7 @@ #include #include "core/errorstrings.h" -#include "core/servercontroller.h" +#include "core/controllers/serverController.h" #include "utilities.h" namespace diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 6cf855a6..0ffdc00b 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -1,6 +1,6 @@ #include "containers_model.h" -#include "core/servercontroller.h" +#include "core/controllers/serverController.h" ContainersModel::ContainersModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent) diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index 7eea94e5..e0fe0787 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -168,6 +168,14 @@ void ServersModel::addServer(const QJsonObject &server) endResetModel(); } +void ServersModel::editServer(const QJsonObject &server) +{ + beginResetModel(); + m_settings->editServer(m_currentlyProcessedServerIndex, server); + m_servers = m_settings->serversArray(); + endResetModel(); +} + void ServersModel::removeServer() { beginResetModel(); @@ -219,3 +227,8 @@ ServerCredentials ServersModel::serverCredentials(int index) const return credentials; } + +QJsonObject ServersModel::getDefaultServerConfig() +{ + return m_servers.at(m_defaultServerIndex).toObject(); +} diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h index d7b15844..feff3ec8 100644 --- a/client/ui/models/servers_model.h +++ b/client/ui/models/servers_model.h @@ -55,10 +55,13 @@ public slots: QString getCurrentlyProcessedServerHostName(); void addServer(const QJsonObject &server); + void editServer(const QJsonObject &server); void removeServer(); bool isDefaultServerConfigContainsAmneziaDns(); + QJsonObject getDefaultServerConfig(); + protected: QHash roleNames() const override; diff --git a/client/ui/qml/Components/ConnectButton.qml b/client/ui/qml/Components/ConnectButton.qml index 76e83da5..2fdcb9b2 100644 --- a/client/ui/qml/Components/ConnectButton.qml +++ b/client/ui/qml/Components/ConnectButton.qml @@ -138,6 +138,10 @@ Button { } onClicked: { + if (!CloudController.updateServerConfigFromCloud()) { + return + } + if (!ContainersModel.isAnyContainerInstalled()) { PageController.setTriggeredBtConnectButton(true) diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index 1cff01e6..5cc6a6a0 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include "core/controllers/serverController.h" #ifdef AMNEZIA_DESKTOP #include "core/ipcclient.h" @@ -258,9 +258,7 @@ QJsonObject VpnConnection::createVpnConfiguration(int serverIndex, const ServerC for (ProtocolEnumNS::Proto proto : ContainerProps::protocolsForContainer(container)) { QJsonObject vpnConfigData = QJsonDocument::fromJson(createVpnConfigurationForProto(serverIndex, credentials, container, - containerConfig, proto, errorCode) - .toUtf8()) - .object(); + containerConfig, proto, errorCode).toUtf8()).object(); if (errorCode && *errorCode) { return {}; From 4ae9cddccefd7e3923f0b21d831ce94fd150a0fe Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Mon, 23 Oct 2023 21:43:25 +0500 Subject: [PATCH 02/12] fixed a typo in the serverController include --- client/configurators/awg_configurator.cpp | 2 +- client/core/controllers/serverController.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/configurators/awg_configurator.cpp b/client/configurators/awg_configurator.cpp index c3e42258..9470308a 100644 --- a/client/configurators/awg_configurator.cpp +++ b/client/configurators/awg_configurator.cpp @@ -3,7 +3,7 @@ #include #include -#include "core/servercontroller.h" +#include "core/controllers/serverController.h" AwgConfigurator::AwgConfigurator(std::shared_ptr settings, QObject *parent) : WireguardConfigurator(settings, true, parent) diff --git a/client/core/controllers/serverController.cpp b/client/core/controllers/serverController.cpp index cc81ed94..5786fa68 100644 --- a/client/core/controllers/serverController.cpp +++ b/client/core/controllers/serverController.cpp @@ -1,4 +1,4 @@ -#include "servercontroller.h" +#include "serverController.h" #include #include From 3e03002eaded6f90041e1e4d321c1ee783d363e8 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Mon, 23 Oct 2023 23:55:01 +0500 Subject: [PATCH 03/12] added getting cloud config for cloak --- client/ui/controllers/cloudController.cpp | 29 +++++++++++++++++++---- client/ui/controllers/cloudController.h | 5 ++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/client/ui/controllers/cloudController.cpp b/client/ui/controllers/cloudController.cpp index 99309d90..188e12e3 100644 --- a/client/ui/controllers/cloudController.cpp +++ b/client/ui/controllers/cloudController.cpp @@ -31,8 +31,8 @@ QString CloudController::genCertificateRequest(ServiceTypeId serviceTypeId) { case ServiceTypeId::AmneziaFreeRuWG: return ""; case ServiceTypeId::AmneziaFreeRuCloak: { - auto data = OpenVpnConfigurator::createCertRequest(); - return data.request; + m_certRequest = OpenVpnConfigurator::createCertRequest(); + return m_certRequest.request; } case ServiceTypeId::AmneziaFreeRuAWG: return ""; case ServiceTypeId::AmneziaFreeRuReverseWG: return ""; @@ -41,6 +41,23 @@ QString CloudController::genCertificateRequest(ServiceTypeId serviceTypeId) } } +void CloudController::processCloudConfig(ServiceTypeId serviceTypeId, QString &config) +{ + switch (serviceTypeId) + { + case ServiceTypeId::AmneziaFreeRuWG: return; + case ServiceTypeId::AmneziaFreeRuCloak: { + config.replace("", "\n"); + config.replace("$OPENVPN_PRIV_KEY", m_certRequest.privKey); + return; + } + case ServiceTypeId::AmneziaFreeRuAWG: return; + case ServiceTypeId::AmneziaFreeRuReverseWG: return; + case ServiceTypeId::AmneziaFreeRuReverseCloak: return; + case ServiceTypeId::AmneziaFreeRuReverseAWG: return; + } +} + bool CloudController::updateServerConfigFromCloud() { auto serverConfig = m_serversModel->getDefaultServerConfig(); @@ -53,7 +70,7 @@ bool CloudController::updateServerConfigFromCloud() QNetworkRequest request; request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); QString endpoint = serverConfig.value(config_key::apiEdnpoint).toString(); - request.setUrl(endpoint.replace("https", "http")); // + request.setUrl(endpoint.replace("https", "http")); // todo remove ServiceTypeId serviceTypeId = static_cast(serverConfig.value(config_key::serviceTypeId).toInt()); @@ -85,7 +102,11 @@ bool CloudController::updateServerConfigFromCloud() ba = ba_uncompressed; } - QJsonObject cloudConfig = QJsonDocument::fromJson(ba).object(); + QString configStr = ba; + processCloudConfig(serviceTypeId, configStr); + + QJsonObject cloudConfig = QJsonDocument::fromJson(configStr.toUtf8()).object(); + serverConfig.insert("cloudConfig", cloudConfig); serverConfig.insert(config_key::dns1, cloudConfig.value(config_key::dns1)); serverConfig.insert(config_key::dns2, cloudConfig.value(config_key::dns2)); diff --git a/client/ui/controllers/cloudController.h b/client/ui/controllers/cloudController.h index 409e0981..36c8427b 100644 --- a/client/ui/controllers/cloudController.h +++ b/client/ui/controllers/cloudController.h @@ -5,6 +5,7 @@ #include "ui/models/containers_model.h" #include "ui/models/servers_model.h" +#include "configurators/openvpn_configurator.h" class CloudController : public QObject { @@ -36,8 +37,12 @@ private: QString genPublicKey(ServiceTypeId serviceTypeId); QString genCertificateRequest(ServiceTypeId serviceTypeId); + void processCloudConfig(ServiceTypeId serviceTypeId, QString &config); + QSharedPointer m_serversModel; QSharedPointer m_containersModel; + + OpenVpnConfigurator::ConnectionData m_certRequest; }; #endif // CLOUDCONTROLLER_H From 8497aeeb912bf932f2ac9ddf384aa47569063f87 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Mon, 6 Nov 2023 14:10:31 +0300 Subject: [PATCH 04/12] removed the debugging code --- client/protocols/openvpnprotocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/protocols/openvpnprotocol.cpp b/client/protocols/openvpnprotocol.cpp index f91cfe09..c38c6eea 100644 --- a/client/protocols/openvpnprotocol.cpp +++ b/client/protocols/openvpnprotocol.cpp @@ -214,7 +214,7 @@ ErrorCode OpenVpnProtocol::start() m_openVpnProcess->setProgram(PermittedProcess::OpenVPN); QStringList arguments({ "--config", configPath(), "--management", m_managementHost, QString::number(mgmtPort), - "--management-client" , "--log", "/Users/nethius/Documents/git/log" + "--management-client" /*, "--log", vpnLogFileNamePath */ }); m_openVpnProcess->setArguments(arguments); From 4fd0852bb33a6f93f66f06fffbb15c778598dc29 Mon Sep 17 00:00:00 2001 From: tiaga Date: Mon, 27 Nov 2023 21:47:54 +0700 Subject: [PATCH 05/12] Improve install_docker.sh - add delays before and after Docker activation - cancel installation if `sudo` wasn't found --- client/server_scripts/install_docker.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/server_scripts/install_docker.sh b/client/server_scripts/install_docker.sh index e6708ddf..6f19e090 100644 --- a/client/server_scripts/install_docker.sh +++ b/client/server_scripts/install_docker.sh @@ -7,13 +7,13 @@ if [ "$dist" = "debian" ]; then export DEBIAN_FRONTEND=noninteractive; fi;\ if ! command -v sudo > /dev/null 2>&1; then $pm $check_pkgs; $pm $silent_inst sudo; fi;\ if ! command -v fuser > /dev/null 2>&1; then sudo $pm $check_pkgs; sudo $pm $silent_inst psmisc; fi;\ if ! command -v lsof > /dev/null 2>&1; then sudo $pm $check_pkgs; sudo $pm $silent_inst lsof; fi;\ -if ! command -v docker > /dev/null 2>&1; then sudo $pm $check_pkgs; sudo $pm $silent_inst $docker_pkg;\ - if [ "$dist" = "fedora" ] || [ "$dist" = "centos" ] || [ "$dist" = "debian" ]; then sudo systemctl enable docker && sudo systemctl start docker; fi;\ +if ! command -v docker > /dev/null 2>&1; then \ + sudo $pm $check_pkgs; sudo $pm $silent_inst $docker_pkg;\ + sleep 5; sudo systemctl enable --now docker; sleep 5;\ fi;\ -if [ "$dist" = "debian" ]; then \ - docker_service=$(systemctl list-units --full --all | grep docker.service | grep -v inactive | grep -v dead | grep -v failed);\ - if [ -z "$docker_service" ]; then sudo $pm $check_pkgs; sudo $pm $silent_inst curl $docker_pkg; fi;\ - sleep 3 && sudo systemctl start docker && sleep 3;\ +if [ "$(systemctl is-active docker)" != "active" ]; then \ + sudo $pm $check_pkgs; sudo $pm $silent_inst $docker_pkg;\ + sleep 5; sudo systemctl start docker; sleep 5;\ fi;\ -if ! command -v sudo > /dev/null 2>&1; then echo "Failed to install Docker"; exit 1; fi;\ +if ! command -v sudo > /dev/null 2>&1; then echo "Failed to install sudo, command not found"; exit 1; fi;\ docker --version From 3605f62feb22334d836329f8bb7d52c682717e92 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Tue, 5 Dec 2023 17:28:14 +0700 Subject: [PATCH 06/12] added support for the updated api --- client/protocols/protocols_defs.h | 5 -- client/ui/controllers/cloudController.cpp | 70 +++++++++++------------ client/ui/controllers/cloudController.h | 6 +- 3 files changed, 35 insertions(+), 46 deletions(-) diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index c86d503b..e602e028 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -80,11 +80,6 @@ namespace amnezia constexpr char awg[] = "awg"; constexpr char configVersion[] = "config_version"; - constexpr char apiEdnpoint[] = "api_endpoint"; - constexpr char serviceTypeId[] = "service_type_id"; - constexpr char accessToken[] = "access_token"; - constexpr char certificate[] = "certificate"; - constexpr char publicKey[] = "public_key"; constexpr char splitTunnelSites[] = "splitTunnelSites"; constexpr char splitTunnelType[] = "splitTunnelType"; diff --git a/client/ui/controllers/cloudController.cpp b/client/ui/controllers/cloudController.cpp index 188e12e3..321296ed 100644 --- a/client/ui/controllers/cloudController.cpp +++ b/client/ui/controllers/cloudController.cpp @@ -6,56 +6,49 @@ #include "configurators/openvpn_configurator.h" +namespace { + namespace configKey { + constexpr char cloak[] = "cloak"; + + constexpr char apiEdnpoint[] = "api_endpoint"; + constexpr char accessToken[] = "api_key"; + constexpr char certificate[] = "certificate"; + constexpr char publicKey[] = "public_key"; + constexpr char protocol[] = "protocol"; + } +} + CloudController::CloudController(const QSharedPointer &serversModel, const QSharedPointer &containersModel, QObject *parent) : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel) { } -QString CloudController::genPublicKey(ServiceTypeId serviceTypeId) +QString CloudController::genPublicKey(const QString &protocol) { - switch (serviceTypeId) - { - case ServiceTypeId::AmneziaFreeRuWG: return "."; - case ServiceTypeId::AmneziaFreeRuCloak: return "."; - case ServiceTypeId::AmneziaFreeRuAWG: return "."; - case ServiceTypeId::AmneziaFreeRuReverseWG: return "."; - case ServiceTypeId::AmneziaFreeRuReverseCloak: return "."; - case ServiceTypeId::AmneziaFreeRuReverseAWG: return "."; + if (protocol == configKey::cloak) { + return "."; } + return QString(); } -QString CloudController::genCertificateRequest(ServiceTypeId serviceTypeId) +QString CloudController::genCertificateRequest(const QString &protocol) { - switch (serviceTypeId) - { - case ServiceTypeId::AmneziaFreeRuWG: return ""; - case ServiceTypeId::AmneziaFreeRuCloak: { - m_certRequest = OpenVpnConfigurator::createCertRequest(); - return m_certRequest.request; - } - case ServiceTypeId::AmneziaFreeRuAWG: return ""; - case ServiceTypeId::AmneziaFreeRuReverseWG: return ""; - case ServiceTypeId::AmneziaFreeRuReverseCloak: return ""; - case ServiceTypeId::AmneziaFreeRuReverseAWG: return ""; + if (protocol == configKey::cloak) { + m_certRequest = OpenVpnConfigurator::createCertRequest(); + return m_certRequest.request; } + return QString(); } -void CloudController::processCloudConfig(ServiceTypeId serviceTypeId, QString &config) +void CloudController::processCloudConfig(const QString &protocol, QString &config) { - switch (serviceTypeId) - { - case ServiceTypeId::AmneziaFreeRuWG: return; - case ServiceTypeId::AmneziaFreeRuCloak: { + if (protocol == configKey::cloak) { config.replace("", "\n"); config.replace("$OPENVPN_PRIV_KEY", m_certRequest.privKey); return; } - case ServiceTypeId::AmneziaFreeRuAWG: return; - case ServiceTypeId::AmneziaFreeRuReverseWG: return; - case ServiceTypeId::AmneziaFreeRuReverseCloak: return; - case ServiceTypeId::AmneziaFreeRuReverseAWG: return; - } + return; } bool CloudController::updateServerConfigFromCloud() @@ -69,19 +62,19 @@ bool CloudController::updateServerConfigFromCloud() QNetworkRequest request; request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QString endpoint = serverConfig.value(config_key::apiEdnpoint).toString(); + request.setRawHeader("Authorization", "Api-Key " + serverConfig.value(configKey::accessToken).toString().toUtf8()); + QString endpoint = serverConfig.value(configKey::apiEdnpoint).toString(); request.setUrl(endpoint.replace("https", "http")); // todo remove - ServiceTypeId serviceTypeId = static_cast(serverConfig.value(config_key::serviceTypeId).toInt()); + QString protocol = serverConfig.value(configKey::protocol).toString(); QJsonObject obj; - obj[config_key::serviceTypeId] = serviceTypeId; - obj[config_key::accessToken] = serverConfig.value(config_key::accessToken); - obj[config_key::publicKey] = genPublicKey(serviceTypeId); - obj[config_key::certificate] = genCertificateRequest(serviceTypeId); + obj[configKey::publicKey] = genPublicKey(protocol); + obj[configKey::certificate] = genCertificateRequest(protocol); QByteArray requestBody = QJsonDocument(obj).toJson(); + qDebug() << requestBody; QScopedPointer reply; reply.reset(manager.post(request, requestBody)); @@ -103,7 +96,7 @@ bool CloudController::updateServerConfigFromCloud() } QString configStr = ba; - processCloudConfig(serviceTypeId, configStr); + processCloudConfig(protocol, configStr); QJsonObject cloudConfig = QJsonDocument::fromJson(configStr.toUtf8()).object(); @@ -117,6 +110,7 @@ bool CloudController::updateServerConfigFromCloud() emit serverConfigUpdated(); } else{ QString err = reply->errorString(); + qDebug() << QString::fromUtf8(reply->readAll());; qDebug() << reply->error(); qDebug() << err; qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); diff --git a/client/ui/controllers/cloudController.h b/client/ui/controllers/cloudController.h index 36c8427b..aaaed18e 100644 --- a/client/ui/controllers/cloudController.h +++ b/client/ui/controllers/cloudController.h @@ -34,10 +34,10 @@ signals: void serverConfigUpdated(); private: - QString genPublicKey(ServiceTypeId serviceTypeId); - QString genCertificateRequest(ServiceTypeId serviceTypeId); + QString genPublicKey(const QString &protocol); + QString genCertificateRequest(const QString &protocol); - void processCloudConfig(ServiceTypeId serviceTypeId, QString &config); + void processCloudConfig(const QString &protocol, QString &config); QSharedPointer m_serversModel; QSharedPointer m_containersModel; From c4014518cb630380bffd52711937aa2b22e7f771 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Tue, 5 Dec 2023 17:38:38 +0700 Subject: [PATCH 07/12] renamed CloudController to ApiController --- client/amnezia_application.cpp | 6 ++-- client/amnezia_application.h | 4 +-- ...{cloudController.cpp => apiController.cpp} | 35 ++++++++++--------- .../{cloudController.h => apiController.h} | 27 +++++--------- client/ui/qml/Components/ConnectButton.qml | 2 +- 5 files changed, 33 insertions(+), 41 deletions(-) rename client/ui/controllers/{cloudController.cpp => apiController.cpp} (79%) rename client/ui/controllers/{cloudController.h => apiController.h} (52%) diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index fa947d29..1632835c 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -364,9 +364,9 @@ void AmneziaApplication::initControllers() m_systemController.reset(new SystemController(m_settings)); m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get()); - m_cloudController.reset(new CloudController(m_serversModel, m_containersModel)); - m_engine->rootContext()->setContextProperty("CloudController", m_cloudController.get()); + m_cloudController.reset(new ApiController(m_serversModel, m_containersModel)); + m_engine->rootContext()->setContextProperty("ApiController", m_cloudController.get()); - connect(m_cloudController.get(), &CloudController::serverConfigUpdated, this, + connect(m_cloudController.get(), &ApiController::serverConfigUpdated, this, [this]() { m_containersModel->setCurrentlyProcessedServerIndex(m_serversModel->getDefaultServerIndex()); }); } diff --git a/client/amnezia_application.h b/client/amnezia_application.h index b82bb9bb..a66b42c8 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -24,7 +24,7 @@ #include "ui/controllers/settingsController.h" #include "ui/controllers/sitesController.h" #include "ui/controllers/systemController.h" -#include "ui/controllers/cloudController.h" +#include "ui/controllers/apiController.h" #include "ui/models/containers_model.h" #include "ui/models/languageModel.h" #include "ui/models/protocols/cloakConfigModel.h" @@ -119,7 +119,7 @@ private: QScopedPointer m_settingsController; QScopedPointer m_sitesController; QScopedPointer m_systemController; - QScopedPointer m_cloudController; + QScopedPointer m_cloudController; }; #endif // AMNEZIA_APPLICATION_H diff --git a/client/ui/controllers/cloudController.cpp b/client/ui/controllers/apiController.cpp similarity index 79% rename from client/ui/controllers/cloudController.cpp rename to client/ui/controllers/apiController.cpp index 321296ed..d0c440df 100644 --- a/client/ui/controllers/cloudController.cpp +++ b/client/ui/controllers/apiController.cpp @@ -1,13 +1,15 @@ -#include "cloudController.h" +#include "apiController.h" +#include #include #include -#include #include "configurators/openvpn_configurator.h" -namespace { - namespace configKey { +namespace +{ + namespace configKey + { constexpr char cloak[] = "cloak"; constexpr char apiEdnpoint[] = "api_endpoint"; @@ -18,13 +20,13 @@ namespace { } } -CloudController::CloudController(const QSharedPointer &serversModel, - const QSharedPointer &containersModel, QObject *parent) +ApiController::ApiController(const QSharedPointer &serversModel, + const QSharedPointer &containersModel, QObject *parent) : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel) { } -QString CloudController::genPublicKey(const QString &protocol) +QString ApiController::genPublicKey(const QString &protocol) { if (protocol == configKey::cloak) { return "."; @@ -32,7 +34,7 @@ QString CloudController::genPublicKey(const QString &protocol) return QString(); } -QString CloudController::genCertificateRequest(const QString &protocol) +QString ApiController::genCertificateRequest(const QString &protocol) { if (protocol == configKey::cloak) { m_certRequest = OpenVpnConfigurator::createCertRequest(); @@ -41,7 +43,7 @@ QString CloudController::genCertificateRequest(const QString &protocol) return QString(); } -void CloudController::processCloudConfig(const QString &protocol, QString &config) +void ApiController::processCloudConfig(const QString &protocol, QString &config) { if (protocol == configKey::cloak) { config.replace("", "\n"); @@ -51,7 +53,7 @@ void CloudController::processCloudConfig(const QString &protocol, QString &confi return; } -bool CloudController::updateServerConfigFromCloud() +bool ApiController::updateServerConfigFromApi() { auto serverConfig = m_serversModel->getDefaultServerConfig(); @@ -62,7 +64,8 @@ bool CloudController::updateServerConfigFromCloud() QNetworkRequest request; request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request.setRawHeader("Authorization", "Api-Key " + serverConfig.value(configKey::accessToken).toString().toUtf8()); + request.setRawHeader("Authorization", + "Api-Key " + serverConfig.value(configKey::accessToken).toString().toUtf8()); QString endpoint = serverConfig.value(configKey::apiEdnpoint).toString(); request.setUrl(endpoint.replace("https", "http")); // todo remove @@ -83,12 +86,13 @@ bool CloudController::updateServerConfigFromCloud() QObject::connect(reply.get(), &QNetworkReply::finished, &wait, &QEventLoop::quit); wait.exec(); - if(reply->error() == QNetworkReply::NoError){ + if (reply->error() == QNetworkReply::NoError) { QString contents = QString::fromUtf8(reply->readAll()); auto data = QJsonDocument::fromJson(contents.toUtf8()).object().value(config_key::config).toString(); data.replace("vpn://", ""); - QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); + QByteArray ba = QByteArray::fromBase64(data.toUtf8(), + QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); QByteArray ba_uncompressed = qUncompress(ba); if (!ba_uncompressed.isEmpty()) { @@ -108,16 +112,15 @@ bool CloudController::updateServerConfigFromCloud() serverConfig.insert(config_key::defaultContainer, cloudConfig.value(config_key::defaultContainer)); m_serversModel->editServer(serverConfig); emit serverConfigUpdated(); - } else{ + } else { QString err = reply->errorString(); - qDebug() << QString::fromUtf8(reply->readAll());; + qDebug() << QString::fromUtf8(reply->readAll()); //todo remove debug output qDebug() << reply->error(); qDebug() << err; qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); emit errorOccurred(tr("Error when retrieving configuration from cloud server")); return false; } - } return true; diff --git a/client/ui/controllers/cloudController.h b/client/ui/controllers/apiController.h similarity index 52% rename from client/ui/controllers/cloudController.h rename to client/ui/controllers/apiController.h index aaaed18e..5917f70f 100644 --- a/client/ui/controllers/cloudController.h +++ b/client/ui/controllers/apiController.h @@ -1,33 +1,22 @@ -#ifndef CLOUDCONTROLLER_H -#define CLOUDCONTROLLER_H +#ifndef APICONTROLLER_H +#define APICONTROLLER_H #include +#include "configurators/openvpn_configurator.h" #include "ui/models/containers_model.h" #include "ui/models/servers_model.h" -#include "configurators/openvpn_configurator.h" -class CloudController : public QObject +class ApiController : public QObject { Q_OBJECT - enum ServiceTypeId - { - AmneziaFreeRuWG = 0, - AmneziaFreeRuCloak, - AmneziaFreeRuAWG, - AmneziaFreeRuReverseWG, - AmneziaFreeRuReverseCloak, - AmneziaFreeRuReverseAWG - - }; - public: - explicit CloudController(const QSharedPointer &serversModel, - const QSharedPointer &containersModel, QObject *parent = nullptr); + explicit ApiController(const QSharedPointer &serversModel, + const QSharedPointer &containersModel, QObject *parent = nullptr); public slots: - bool updateServerConfigFromCloud(); + bool updateServerConfigFromApi(); signals: void errorOccurred(const QString &errorMessage); @@ -45,4 +34,4 @@ private: OpenVpnConfigurator::ConnectionData m_certRequest; }; -#endif // CLOUDCONTROLLER_H +#endif // APICONTROLLER_H diff --git a/client/ui/qml/Components/ConnectButton.qml b/client/ui/qml/Components/ConnectButton.qml index 757662ae..a0a57e6a 100644 --- a/client/ui/qml/Components/ConnectButton.qml +++ b/client/ui/qml/Components/ConnectButton.qml @@ -138,7 +138,7 @@ Button { } onClicked: { - if (!CloudController.updateServerConfigFromCloud()) { + if (!ApiController.updateServerConfigFromApi()) { return } From f3f98a50ed220f362da45baea5ecb8a95dd791e5 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Tue, 5 Dec 2023 17:44:13 +0700 Subject: [PATCH 08/12] fixed include path of servercontroller --- client/ui/models/clientManagementModel.cpp | 2 +- client/ui/models/clientManagementModel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ui/models/clientManagementModel.cpp b/client/ui/models/clientManagementModel.cpp index bfc33eb9..8ec31d02 100644 --- a/client/ui/models/clientManagementModel.cpp +++ b/client/ui/models/clientManagementModel.cpp @@ -3,7 +3,7 @@ #include #include -#include "core/servercontroller.h" +#include "core/controllers/serverController.h" #include "logger.h" namespace diff --git a/client/ui/models/clientManagementModel.h b/client/ui/models/clientManagementModel.h index f5312db7..6b6adf68 100644 --- a/client/ui/models/clientManagementModel.h +++ b/client/ui/models/clientManagementModel.h @@ -4,7 +4,7 @@ #include #include -#include "core/servercontroller.h" +#include "core/controllers/serverController.h" #include "settings.h" class ClientManagementModel : public QAbstractListModel From b4c89ad58f8d90697e12c6fc876c29750a94c948 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Fri, 8 Dec 2023 13:50:03 +0700 Subject: [PATCH 09/12] Reworked the interaction between models. Now only serversModel directly interacts with server config --- client/amnezia_application.cpp | 35 ++- client/containers/containers_defs.cpp | 2 +- client/protocols/protocols_defs.h | 1 + .../ui/controllers/connectionController.cpp | 7 +- client/ui/controllers/exportController.cpp | 32 +- client/ui/controllers/installController.cpp | 28 +- client/ui/controllers/settingsController.cpp | 3 +- client/ui/controllers/settingsController.h | 2 + client/ui/models/containers_model.cpp | 157 +--------- client/ui/models/containers_model.h | 29 +- client/ui/models/servers_model.cpp | 295 +++++++++++++++++- client/ui/models/servers_model.h | 45 ++- .../qml/Components/HomeContainersListView.qml | 3 +- client/ui/qml/Pages2/PageHome.qml | 49 +-- .../Pages2/PageServiceTorWebsiteSettings.qml | 2 +- .../ui/qml/Pages2/PageSettingsServersList.qml | 2 +- .../qml/Pages2/PageSetupWizardInstalling.qml | 2 +- client/ui/qml/Pages2/PageShare.qml | 4 +- client/vpnconnection.cpp | 4 +- 19 files changed, 412 insertions(+), 290 deletions(-) diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index 1ef3316b..5079ed87 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -277,19 +277,16 @@ QQmlApplicationEngine *AmneziaApplication::qmlEngine() const void AmneziaApplication::initModels() { - m_containersModel.reset(new ContainersModel(m_settings, this)); + m_containersModel.reset(new ContainersModel(this)); m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get()); - connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, m_containersModel.get(), - &ContainersModel::updateContainersConfig); m_serversModel.reset(new ServersModel(m_settings, this)); m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get()); - connect(m_serversModel.get(), &ServersModel::currentlyProcessedServerIndexChanged, m_containersModel.get(), - &ContainersModel::setCurrentlyProcessedServerIndex); - connect(m_serversModel.get(), &ServersModel::defaultServerIndexChanged, m_containersModel.get(), - &ContainersModel::setCurrentlyProcessedServerIndex); - connect(m_containersModel.get(), &ContainersModel::containersModelUpdated, m_serversModel.get(), - &ServersModel::updateContainersConfig); + connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(), + &ContainersModel::updateModel); + connect(m_serversModel.get(), &ServersModel::defaultContainerChanged, m_containersModel.get(), + &ContainersModel::setDefaultContainer); + m_containersModel->setDefaultContainer(m_serversModel->getDefaultContainer()); // make better? m_languageModel.reset(new LanguageModel(m_settings, this)); m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get()); @@ -298,7 +295,7 @@ void AmneziaApplication::initModels() m_sitesModel.reset(new SitesModel(m_settings, this)); m_engine->rootContext()->setContextProperty("SitesModel", m_sitesModel.get()); - + m_protocolsModel.reset(new ProtocolsModel(m_settings, this)); m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get()); @@ -327,8 +324,13 @@ void AmneziaApplication::initModels() m_clientManagementModel.reset(new ClientManagementModel(m_settings, this)); m_engine->rootContext()->setContextProperty("ClientManagementModel", m_clientManagementModel.get()); - connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, m_clientManagementModel.get(), - &ClientManagementModel::appendClient); + + connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, this, + [this](const QString &clientId, const QString &clientName, const DockerContainer container, + ServerCredentials credentials) { + m_serversModel->reloadContainerConfig(); + m_clientManagementModel->appendClient(clientId, clientName, container, credentials); + }); } void AmneziaApplication::initControllers() @@ -354,7 +356,8 @@ void AmneziaApplication::initControllers() m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings)); m_engine->rootContext()->setContextProperty("ImportController", m_importController.get()); - m_exportController.reset(new ExportController(m_serversModel, m_containersModel, m_clientManagementModel, m_settings, m_configurator)); + m_exportController.reset(new ExportController(m_serversModel, m_containersModel, m_clientManagementModel, + m_settings, m_configurator)); m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get()); m_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_settings)); @@ -362,6 +365,8 @@ void AmneziaApplication::initControllers() if (m_settingsController->isAutoConnectEnabled() && m_serversModel->getDefaultServerIndex() >= 0) { QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); }); } + connect(m_settingsController.get(), &SettingsController::amneziaDnsToggled , m_serversModel.get(), + &ServersModel::toggleAmneziaDns); m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel)); m_engine->rootContext()->setContextProperty("SitesController", m_sitesController.get()); @@ -372,6 +377,6 @@ void AmneziaApplication::initControllers() m_cloudController.reset(new ApiController(m_serversModel, m_containersModel)); m_engine->rootContext()->setContextProperty("ApiController", m_cloudController.get()); - connect(m_cloudController.get(), &ApiController::serverConfigUpdated, this, - [this]() { m_containersModel->setCurrentlyProcessedServerIndex(m_serversModel->getDefaultServerIndex()); }); + // connect(m_cloudController.get(), &ApiController::serverConfigUpdated, this, + // [this]() { m_containersModel->setCurrentlyProcessedServerIndex(m_serversModel->getDefaultServerIndex()); }); } diff --git a/client/containers/containers_defs.cpp b/client/containers/containers_defs.cpp index e133e79e..8bff8b72 100644 --- a/client/containers/containers_defs.cpp +++ b/client/containers/containers_defs.cpp @@ -58,7 +58,7 @@ QVector ContainerProps::protocolsForContainer(amnezia::DockerCon case DockerContainer::Ipsec: return { Proto::Ikev2 /*, Protocol::L2tp */ }; - case DockerContainer::Dns: return {}; + case DockerContainer::Dns: return { Proto::Dns }; case DockerContainer::Sftp: return { Proto::Sftp }; diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index e602e028..8d7d9bfb 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -21,6 +21,7 @@ namespace amnezia constexpr char dns2[] = "dns2"; constexpr char description[] = "description"; + constexpr char name[] = "name"; constexpr char cert[] = "cert"; constexpr char config[] = "config"; diff --git a/client/ui/controllers/connectionController.cpp b/client/ui/controllers/connectionController.cpp index de05d624..81bba3bf 100644 --- a/client/ui/controllers/connectionController.cpp +++ b/client/ui/controllers/connectionController.cpp @@ -26,13 +26,10 @@ ConnectionController::ConnectionController(const QSharedPointer &s void ConnectionController::openConnection() { int serverIndex = m_serversModel->getDefaultServerIndex(); - ServerCredentials credentials = - qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); + ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); DockerContainer container = m_containersModel->getDefaultContainer(); - QModelIndex containerModelIndex = m_containersModel->index(container); - const QJsonObject &containerConfig = - qvariant_cast(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole)); + const QJsonObject &containerConfig = m_containersModel->getContainerConfig(container); if (container == DockerContainer::None) { emit connectionErrorOccurred(tr("VPN Protocols is not installed.\n Please install VPN container at first")); diff --git a/client/ui/controllers/exportController.cpp b/client/ui/controllers/exportController.cpp index 52dadba5..9930926f 100644 --- a/client/ui/controllers/exportController.cpp +++ b/client/ui/controllers/exportController.cpp @@ -84,12 +84,10 @@ void ExportController::generateConnectionConfig(const QString &clientName) clearPreviousConfig(); int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex(); - ServerCredentials credentials = m_serversModel->getCurrentlyProcessedServerCredentials(); + ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); - QModelIndex containerModelIndex = m_containersModel->index(container); - QJsonObject containerConfig = - qvariant_cast(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole)); + QJsonObject containerConfig = m_containersModel->getContainerConfig(container); containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); ErrorCode errorCode = ErrorCode::NoError; @@ -142,12 +140,10 @@ void ExportController::generateOpenVpnConfig(const QString &clientName) clearPreviousConfig(); int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex(); - ServerCredentials credentials = m_serversModel->getCurrentlyProcessedServerCredentials(); + ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); - QModelIndex containerModelIndex = m_containersModel->index(container); - QJsonObject containerConfig = - qvariant_cast(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole)); + QJsonObject containerConfig = m_containersModel->getContainerConfig(container); containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); ErrorCode errorCode = ErrorCode::NoError; @@ -182,12 +178,10 @@ void ExportController::generateWireGuardConfig(const QString &clientName) clearPreviousConfig(); int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex(); - ServerCredentials credentials = m_serversModel->getCurrentlyProcessedServerCredentials(); + ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); - QModelIndex containerModelIndex = m_containersModel->index(container); - QJsonObject containerConfig = - qvariant_cast(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole)); + QJsonObject containerConfig = m_containersModel->getContainerConfig(container); containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); QString clientId; @@ -223,13 +217,10 @@ void ExportController::generateShadowSocksConfig() clearPreviousConfig(); int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex(); - ServerCredentials credentials = - qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); + ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); - QModelIndex containerModelIndex = m_containersModel->index(container); - QJsonObject containerConfig = - qvariant_cast(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole)); + QJsonObject containerConfig = m_containersModel->getContainerConfig(container); containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); ErrorCode errorCode = ErrorCode::NoError; @@ -262,13 +253,10 @@ void ExportController::generateCloakConfig() clearPreviousConfig(); int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex(); - ServerCredentials credentials = - qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); + ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); - QModelIndex containerModelIndex = m_containersModel->index(container); - QJsonObject containerConfig = - qvariant_cast(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole)); + QJsonObject containerConfig = m_containersModel->getContainerConfig(container); containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); ErrorCode errorCode = ErrorCode::NoError; diff --git a/client/ui/controllers/installController.cpp b/client/ui/controllers/installController.cpp index 422d9849..77e25f43 100644 --- a/client/ui/controllers/installController.cpp +++ b/client/ui/controllers/installController.cpp @@ -199,12 +199,9 @@ void InstallController::installContainer(DockerContainer container, QJsonObject if (errorCode == ErrorCode::NoError) { for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) { - auto modelIndex = m_containersModel->index(iterator.key()); - QJsonObject containerConfig = - qvariant_cast(m_containersModel->data(modelIndex, ContainersModel::Roles::ConfigRole)); + QJsonObject containerConfig = m_containersModel->getContainerConfig(iterator.key()); if (containerConfig.isEmpty()) { - m_containersModel->setData(m_containersModel->index(iterator.key()), iterator.value(), - ContainersModel::Roles::ConfigRole); + m_serversModel->addContainerConfig(iterator.key(), iterator.value()); if (container != iterator.key()) { // skip the newly installed container isInstalledContainerAddedToGui = true; } @@ -252,12 +249,9 @@ void InstallController::scanServerForInstalledContainers() bool isInstalledContainerAddedToGui = false; for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) { - auto modelIndex = m_containersModel->index(iterator.key()); - QJsonObject containerConfig = - qvariant_cast(m_containersModel->data(modelIndex, ContainersModel::Roles::ConfigRole)); + QJsonObject containerConfig = m_containersModel->getContainerConfig(iterator.key()); if (containerConfig.isEmpty()) { - m_containersModel->setData(m_containersModel->index(iterator.key()), iterator.value(), - ContainersModel::Roles::ConfigRole); + m_serversModel->addContainerConfig(iterator.key(), iterator.value()); isInstalledContainerAddedToGui = true; } } @@ -276,16 +270,14 @@ void InstallController::updateContainer(QJsonObject config) qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); const DockerContainer container = ContainerProps::containerFromString(config.value(config_key::container).toString()); - auto modelIndex = m_containersModel->index(container); - QJsonObject oldContainerConfig = - qvariant_cast(m_containersModel->data(modelIndex, ContainersModel::Roles::ConfigRole)); + QJsonObject oldContainerConfig = m_containersModel->getContainerConfig(container); ServerController serverController(m_settings); connect(&serverController, &ServerController::serverIsBusy, this, &InstallController::serverIsBusy); auto errorCode = serverController.updateContainer(serverCredentials, container, oldContainerConfig, config); if (errorCode == ErrorCode::NoError) { - m_containersModel->setData(modelIndex, config, ContainersModel::Roles::ConfigRole); + m_serversModel->updateContainerConfig(container, config); m_protocolModel->updateModel(config); if ((serverIndex == m_serversModel->getDefaultServerIndex()) @@ -315,7 +307,7 @@ void InstallController::removeAllContainers() int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex(); QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString(); - ErrorCode errorCode = m_containersModel->removeAllContainers(); + ErrorCode errorCode = m_serversModel->removeAllContainers(); if (errorCode == ErrorCode::NoError) { emit removeAllContainersFinished(tr("All containers from server '%1' have been removed").arg(serverName)); return; @@ -329,12 +321,12 @@ void InstallController::removeCurrentlyProcessedContainer() QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString(); int container = m_containersModel->getCurrentlyProcessedContainerIndex(); - QString containerName = m_containersModel->data(container, ContainersModel::Roles::NameRole).toString(); + QString containerName = m_containersModel->getCurrentlyProcessedContainerName(); - ErrorCode errorCode = m_containersModel->removeCurrentlyProcessedContainer(); + ErrorCode errorCode = m_serversModel->removeContainer(container); if (errorCode == ErrorCode::NoError) { - emit removeCurrentlyProcessedContainerFinished(tr("%1 has been removed from the server '%2'").arg(containerName).arg(serverName)); + emit removeCurrentlyProcessedContainerFinished(tr("%1 has been removed from the server '%2'").arg(containerName, serverName)); return; } emit installationErrorOccurred(errorString(errorCode)); diff --git a/client/ui/controllers/settingsController.cpp b/client/ui/controllers/settingsController.cpp index 78d0dd67..9fa4d76b 100644 --- a/client/ui/controllers/settingsController.cpp +++ b/client/ui/controllers/settingsController.cpp @@ -42,6 +42,7 @@ SettingsController::SettingsController(const QSharedPointer &serve void SettingsController::toggleAmneziaDns(bool enable) { m_settings->setUseAmneziaDns(enable); + emit amneziaDnsToggled(enable); } bool SettingsController::isAmneziaDnsEnabled() @@ -138,7 +139,7 @@ void SettingsController::clearSettings() void SettingsController::clearCachedProfiles() { - m_containersModel->clearCachedProfiles(); + m_serversModel->clearCachedProfiles(); emit changeSettingsFinished(tr("Cached profiles cleared")); } diff --git a/client/ui/controllers/settingsController.h b/client/ui/controllers/settingsController.h index be041f3e..710d255f 100644 --- a/client/ui/controllers/settingsController.h +++ b/client/ui/controllers/settingsController.h @@ -70,6 +70,8 @@ signals: void importBackupFromOutside(QString filePath); + void amneziaDnsToggled(bool enable); + private: QSharedPointer m_serversModel; QSharedPointer m_containersModel; diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 00b04ff4..7e73b2e9 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -1,9 +1,9 @@ #include "containers_model.h" -#include "core/controllers/serverController.h" +#include -ContainersModel::ContainersModel(std::shared_ptr settings, QObject *parent) - : m_settings(settings), QAbstractListModel(parent) +ContainersModel::ContainersModel(QObject *parent) + : QAbstractListModel(parent) { } @@ -13,37 +13,6 @@ int ContainersModel::rowCount(const QModelIndex &parent) const return ContainerProps::allContainers().size(); } -bool ContainersModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - if (!index.isValid() || index.row() < 0 || index.row() >= ContainerProps::allContainers().size()) { - return false; - } - - DockerContainer container = ContainerProps::allContainers().at(index.row()); - - switch (role) { - case ConfigRole: { - m_settings->setContainerConfig(m_currentlyProcessedServerIndex, container, value.toJsonObject()); - m_containers = m_settings->containers(m_currentlyProcessedServerIndex); - if (m_defaultContainerIndex != DockerContainer::None) { - break; - } else if (ContainerProps::containerService(container) == ServiceType::Other) { - break; - } - } - case IsDefaultRole: { //todo remove - m_settings->setDefaultContainer(m_currentlyProcessedServerIndex, container); - m_defaultContainerIndex = container; - emit defaultContainerChanged(); - } - default: break; - } - - emit containersModelUpdated(); - emit dataChanged(index, index); - return true; -} - QVariant ContainersModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() < 0 || index.row() >= ContainerProps::allContainers().size()) { @@ -84,37 +53,32 @@ QVariant ContainersModel::data(const int index, int role) const return data(modelIndex, role); } -void ContainersModel::setCurrentlyProcessedServerIndex(const int index) +void ContainersModel::updateModel(QJsonArray &containers) { beginResetModel(); - m_currentlyProcessedServerIndex = index; - m_containers = m_settings->containers(m_currentlyProcessedServerIndex); - m_defaultContainerIndex = m_settings->defaultContainer(m_currentlyProcessedServerIndex); + m_containers.clear(); + for (const QJsonValue &val : containers) { + m_containers.insert(ContainerProps::containerFromString(val.toObject().value(config_key::container).toString()), + val.toObject()); + } endResetModel(); - emit defaultContainerChanged(); } -void ContainersModel::setCurrentlyProcessedContainerIndex(int index) +void ContainersModel::setDefaultContainer(const int containerIndex) { - m_currentlyProcessedContainerIndex = index; + m_defaultContainerIndex = static_cast(containerIndex); + emit dataChanged(index(containerIndex, 0), index(containerIndex, 0)); } + DockerContainer ContainersModel::getDefaultContainer() { return m_defaultContainerIndex; } -QString ContainersModel::getDefaultContainerName() +void ContainersModel::setCurrentlyProcessedContainerIndex(int index) { - return ContainerProps::containerHumanNames().value(m_defaultContainerIndex); -} - -void ContainersModel::setDefaultContainer(int index) -{ - auto container = static_cast(index); - m_settings->setDefaultContainer(m_currentlyProcessedServerIndex, container); - m_defaultContainerIndex = container; - emit defaultContainerChanged(); + m_currentlyProcessedContainerIndex = index; } int ContainersModel::getCurrentlyProcessedContainerIndex() @@ -127,91 +91,9 @@ QString ContainersModel::getCurrentlyProcessedContainerName() return ContainerProps::containerHumanNames().value(static_cast(m_currentlyProcessedContainerIndex)); } -QJsonObject ContainersModel::getCurrentlyProcessedContainerConfig() +QJsonObject ContainersModel::getContainerConfig(const int containerIndex) { - return qvariant_cast(data(index(m_currentlyProcessedContainerIndex), ConfigRole)); -} - -QStringList ContainersModel::getAllInstalledServicesName(const int serverIndex) -{ - QStringList servicesName; - const auto &containers = m_settings->containers(serverIndex); - for (const DockerContainer &container : containers.keys()) { - if (ContainerProps::containerService(container) == ServiceType::Other && m_containers.contains(container)) { - if (container == DockerContainer::Dns) { - servicesName.append("DNS"); - } else if (container == DockerContainer::Sftp) { - servicesName.append("SFTP"); - } else if (container == DockerContainer::TorWebSite) { - servicesName.append("TOR"); - } - } - } - servicesName.sort(); - return servicesName; -} - -ErrorCode ContainersModel::removeAllContainers() -{ - - ServerController serverController(m_settings); - ErrorCode errorCode = - serverController.removeAllContainers(m_settings->serverCredentials(m_currentlyProcessedServerIndex)); - - if (errorCode == ErrorCode::NoError) { - beginResetModel(); - - m_settings->setContainers(m_currentlyProcessedServerIndex, {}); - m_containers = m_settings->containers(m_currentlyProcessedServerIndex); - - setData(index(DockerContainer::None, 0), true, IsDefaultRole); - endResetModel(); - } - return errorCode; -} - -ErrorCode ContainersModel::removeCurrentlyProcessedContainer() -{ - ServerController serverController(m_settings); - auto credentials = m_settings->serverCredentials(m_currentlyProcessedServerIndex); - auto dockerContainer = static_cast(m_currentlyProcessedContainerIndex); - - ErrorCode errorCode = serverController.removeContainer(credentials, dockerContainer); - - if (errorCode == ErrorCode::NoError) { - beginResetModel(); - m_settings->removeContainerConfig(m_currentlyProcessedServerIndex, dockerContainer); - m_containers = m_settings->containers(m_currentlyProcessedServerIndex); - - if (m_defaultContainerIndex == m_currentlyProcessedContainerIndex) { - if (m_containers.isEmpty()) { - setData(index(DockerContainer::None, 0), true, IsDefaultRole); - } else { - setData(index(m_containers.begin().key(), 0), true, IsDefaultRole); - } - } - endResetModel(); - } - return errorCode; -} - -void ContainersModel::clearCachedProfiles() -{ - const auto &containers = m_settings->containers(m_currentlyProcessedServerIndex); - for (DockerContainer container : containers.keys()) { - m_settings->clearLastConnectionConfig(m_currentlyProcessedServerIndex, container); - } -} - -bool ContainersModel::isAmneziaDnsContainerInstalled() -{ - return m_containers.contains(DockerContainer::Dns); -} - -bool ContainersModel::isAmneziaDnsContainerInstalled(const int serverIndex) -{ - QMap containers = m_settings->containers(serverIndex); - return containers.contains(DockerContainer::Dns); + return qvariant_cast(data(index(containerIndex), ConfigRole)); } bool ContainersModel::isAnyContainerInstalled() @@ -228,11 +110,6 @@ bool ContainersModel::isAnyContainerInstalled() return false; } -void ContainersModel::updateContainersConfig() -{ - m_containers = m_settings->containers(m_currentlyProcessedServerIndex); -} - QHash ContainersModel::roleNames() const { QHash roles; diff --git a/client/ui/models/containers_model.h b/client/ui/models/containers_model.h index 8f087d87..23a91ea5 100644 --- a/client/ui/models/containers_model.h +++ b/client/ui/models/containers_model.h @@ -7,13 +7,12 @@ #include #include "containers/containers_defs.h" -#include "settings.h" class ContainersModel : public QAbstractListModel { Q_OBJECT public: - ContainersModel(std::shared_ptr settings, QObject *parent = nullptr); + ContainersModel(QObject *parent = nullptr); enum Roles { NameRole = Qt::UserRole + 1, @@ -37,37 +36,24 @@ public: int rowCount(const QModelIndex &parent = QModelIndex()) const override; - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const int index, int role) const; - Q_PROPERTY(QString defaultContainerName READ getDefaultContainerName NOTIFY defaultContainerChanged) - public slots: + void updateModel(QJsonArray &containers); + DockerContainer getDefaultContainer(); - QString getDefaultContainerName(); - void setDefaultContainer(int index); + void setDefaultContainer(const int containerIndex); - void setCurrentlyProcessedServerIndex(const int index); - - void setCurrentlyProcessedContainerIndex(int index); + void setCurrentlyProcessedContainerIndex(int containerIndex); int getCurrentlyProcessedContainerIndex(); QString getCurrentlyProcessedContainerName(); - QJsonObject getCurrentlyProcessedContainerConfig(); - QStringList getAllInstalledServicesName(const int serverIndex); - ErrorCode removeAllContainers(); - ErrorCode removeCurrentlyProcessedContainer(); - void clearCachedProfiles(); - - bool isAmneziaDnsContainerInstalled(); - bool isAmneziaDnsContainerInstalled(const int serverIndex); + QJsonObject getContainerConfig(const int containerIndex); bool isAnyContainerInstalled(); - void updateContainersConfig(); - protected: QHash roleNames() const override; @@ -78,11 +64,8 @@ signals: private: QMap m_containers; - int m_currentlyProcessedServerIndex; int m_currentlyProcessedContainerIndex; DockerContainer m_defaultContainerIndex; - - std::shared_ptr m_settings; }; #endif // CONTAINERS_MODEL_H diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index 04ba1fe1..ed1f4b0b 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -1,5 +1,7 @@ #include "servers_model.h" +#include "core/controllers/serverController.h" + ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent) { @@ -8,6 +10,11 @@ ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) m_currentlyProcessedServerIndex = m_defaultServerIndex; connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerNameChanged); + connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerDescriptionChanged); + connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) { + auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString()); + emit ServersModel::defaultContainerChanged(defaultContainer); + }); } int ServersModel::rowCount(const QModelIndex &parent) const @@ -50,14 +57,23 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const } const QJsonObject server = m_servers.at(index.row()).toObject(); - + const auto configVersion = server.value(config_key::configVersion).toInt(); switch (role) { case NameRole: { - auto description = server.value(config_key::description).toString(); - if (description.isEmpty()) { + if (configVersion) { + return server.value(config_key::name).toString(); + } + auto name = server.value(config_key::description).toString(); + if (name.isEmpty()) { return server.value(config_key::hostName).toString(); } - return description; + return name; + } + case ServerDescriptionRole: { + if (configVersion) { + return server.value(config_key::description).toString(); + } + return server.value(config_key::hostName).toString(); } case HostNameRole: return server.value(config_key::hostName).toString(); case CredentialsRole: return QVariant::fromValue(serverCredentials(index.row())); @@ -72,6 +88,9 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const QString primaryDns = server.value(config_key::dns1).toString(); return primaryDns == protocols::dns::amneziaDnsIp; } + case DefaultContainerRole: { + return ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); + } } return QVariant(); @@ -114,6 +133,53 @@ const QString ServersModel::getDefaultServerHostName() return qvariant_cast(data(m_defaultServerIndex, HostNameRole)); } +QString ServersModel::getDefaultServerDescription(const QJsonObject &server) +{ + const auto configVersion = server.value(config_key::configVersion).toInt(); + + QString description; + + if (configVersion) { + return server.value(config_key::description).toString(); + } else if (isDefaultServerHasWriteAccess()) { + if (m_isAmneziaDnsEnabled + && isAmneziaDnsContainerInstalled(m_defaultServerIndex)) { + description += "Amnezia DNS | "; + } + } else { + if (isDefaultServerConfigContainsAmneziaDns()) { + description += "Amnezia DNS | "; + } + } + return description; +} + +const QString ServersModel::getDefaultServerDescriptionCollapsed() +{ + const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); + const auto configVersion = server.value(config_key::configVersion).toInt(); + auto description = getDefaultServerDescription(server); + if (configVersion) { + return description; + } + + auto container = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); + + return description += ContainerProps::containerHumanNames().value(container) + " | " + server.value(config_key::hostName).toString(); +} + +const QString ServersModel::getDefaultServerDescriptionExpanded() +{ + const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); + const auto configVersion = server.value(config_key::configVersion).toInt(); + auto description = getDefaultServerDescription(server); + if (configVersion) { + return description; + } + + return description += server.value(config_key::hostName).toString(); +} + const int ServersModel::getServersCount() { return m_servers.count(); @@ -132,6 +198,7 @@ bool ServersModel::hasServerWithWriteAccess() void ServersModel::setCurrentlyProcessedServerIndex(const int index) { m_currentlyProcessedServerIndex = index; + updateContainersModel(); emit currentlyProcessedServerIndexChanged(m_currentlyProcessedServerIndex); } @@ -150,6 +217,11 @@ const ServerCredentials ServersModel::getCurrentlyProcessedServerCredentials() return serverCredentials(m_currentlyProcessedServerIndex); } +const ServerCredentials ServersModel::getServerCredentials(const int index) +{ + return serverCredentials(index); +} + bool ServersModel::isDefaultServerCurrentlyProcessed() { return m_defaultServerIndex == m_currentlyProcessedServerIndex; @@ -179,6 +251,7 @@ void ServersModel::editServer(const QJsonObject &server) m_settings->editServer(m_currentlyProcessedServerIndex, server); m_servers = m_settings->serversArray(); endResetModel(); + updateContainersModel(); } void ServersModel::removeServer() @@ -206,23 +279,27 @@ bool ServersModel::isDefaultServerConfigContainsAmneziaDns() return primaryDns == protocols::dns::amneziaDnsIp; } -void ServersModel::updateContainersConfig() -{ - auto server = m_settings->server(m_currentlyProcessedServerIndex); - m_servers.replace(m_currentlyProcessedServerIndex, server); -} - QHash ServersModel::roleNames() const { QHash roles; + + roles[NameRole] = "serverName"; roles[NameRole] = "name"; + roles[ServerDescriptionRole] = "serverDescription"; + roles[HostNameRole] = "hostName"; + roles[CredentialsRole] = "credentials"; roles[CredentialsLoginRole] = "credentialsLogin"; + roles[IsDefaultRole] = "isDefault"; roles[IsCurrentlyProcessedRole] = "isCurrentlyProcessed"; + roles[HasWriteAccessRole] = "hasWriteAccess"; + roles[ContainsAmneziaDnsRole] = "containsAmneziaDns"; + + roles[DefaultContainerRole] = "defaultContainer"; return roles; } @@ -239,7 +316,205 @@ ServerCredentials ServersModel::serverCredentials(int index) const return credentials; } +void ServersModel::updateContainersModel() +{ + auto containers = m_servers.at(m_currentlyProcessedServerIndex).toObject().value(config_key::containers).toArray(); + emit containersUpdated(containers); +} + QJsonObject ServersModel::getDefaultServerConfig() { return m_servers.at(m_defaultServerIndex).toObject(); } + +void ServersModel::reloadContainerConfig() +{ + QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject(); + auto container = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); + + auto containers = server.value(config_key::containers).toArray(); + + auto config = m_settings->containerConfig(m_currentlyProcessedServerIndex, container); + for (auto i = 0; i < containers.size(); i++) { + auto c = ContainerProps::containerFromString(containers.at(i).toObject().value(config_key::container).toString()); + if (c == container) { + containers.replace(i, config); + break; + } + } + + server.insert(config_key::containers, containers); + editServer(server); +} + +void ServersModel::updateContainerConfig(const int containerIndex, const QJsonObject config) +{ + auto container = static_cast(containerIndex); + QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject(); + + auto containers = server.value(config_key::containers).toArray(); + for (auto i = 0; i < containers.size(); i++) { + auto c = ContainerProps::containerFromString(containers.at(i).toObject().value(config_key::container).toString()); + if (c == container) { + containers.replace(i, config); + break; + } + } + + server.insert(config_key::containers, containers); + + auto defaultContainer = server.value(config_key::defaultContainer).toString(); + if ((ContainerProps::containerFromString(defaultContainer) == DockerContainer::None || ContainerProps::containerService(container) != ServiceType::Other)) { + server.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); + } + + editServer(server); +} + +void ServersModel::addContainerConfig(const int containerIndex, const QJsonObject config) +{ + auto container = static_cast(containerIndex); + QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject(); + + auto containers = server.value(config_key::containers).toArray(); + containers.push_back(config); + + server.insert(config_key::containers, containers); + + bool isDefaultContainerChanged = false; + auto defaultContainer = server.value(config_key::defaultContainer).toString(); + if ((ContainerProps::containerFromString(defaultContainer) == DockerContainer::None || ContainerProps::containerService(container) != ServiceType::Other)) { + server.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); + isDefaultContainerChanged = true; + } + + editServer(server); + if (isDefaultContainerChanged) { + emit defaultContainerChanged(container); + } +} + +void ServersModel::setDefaultContainer(const int containerIndex) +{ + auto container = static_cast(containerIndex); + QJsonObject s = m_servers.at(m_currentlyProcessedServerIndex).toObject(); + s.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); + editServer(s); //check + emit defaultContainerChanged(container); +} + +DockerContainer ServersModel::getDefaultContainer() +{ + return qvariant_cast(data(m_currentlyProcessedServerIndex, DefaultContainerRole)); +} + +const QString ServersModel::getDefaultContainerName() +{ + auto defaultContainer = getDefaultContainer(); + return ContainerProps::containerHumanNames().value(defaultContainer); +} + +ErrorCode ServersModel::removeAllContainers() +{ + ServerController serverController(m_settings); + ErrorCode errorCode = + serverController.removeAllContainers(m_settings->serverCredentials(m_currentlyProcessedServerIndex)); + + if (errorCode == ErrorCode::NoError) { + QJsonObject s = m_servers.at(m_currentlyProcessedServerIndex).toObject(); + s.insert(config_key::containers, {}); + s.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None)); + + editServer(s); + emit defaultContainerChanged(DockerContainer::None); + } + return errorCode; +} + +ErrorCode ServersModel::removeContainer(const int containerIndex) +{ + ServerController serverController(m_settings); + auto credentials = m_settings->serverCredentials(m_currentlyProcessedServerIndex); + auto dockerContainer = static_cast(containerIndex); + + ErrorCode errorCode = serverController.removeContainer(credentials, dockerContainer); + + if (errorCode == ErrorCode::NoError) { + QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject(); + + auto containers = server.value(config_key::containers).toArray(); + for (auto it = containers.begin(); it != containers.end(); it++) { + if (it->toObject().value(config_key::container).toString() == ContainerProps::containerToString(dockerContainer)) { + containers.erase(it); + break; + } + } + + server.insert(config_key::containers, containers); + + auto defaultContainer = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); + if (defaultContainer == containerIndex) { + if (containers.empty()) { + defaultContainer = DockerContainer::None; + } else { + defaultContainer = ContainerProps::containerFromString(containers.begin()->toObject().value(config_key::container).toString()); + } + server.insert(config_key::defaultContainer, ContainerProps::containerToString(defaultContainer)); + } + + editServer(server); + emit defaultContainerChanged(defaultContainer); + } + return errorCode; +} + +void ServersModel::clearCachedProfiles() +{ + const auto &containers = m_settings->containers(m_currentlyProcessedServerIndex); + for (DockerContainer container : containers.keys()) { + m_settings->clearLastConnectionConfig(m_currentlyProcessedServerIndex, container); + } + + m_servers.replace(m_currentlyProcessedServerIndex, m_settings->server(m_currentlyProcessedServerIndex)); + updateContainersModel(); +} + +bool ServersModel::isAmneziaDnsContainerInstalled(const int serverIndex) +{ + QJsonObject server = m_servers.at(serverIndex).toObject(); + auto containers = server.value(config_key::containers).toArray(); + for (auto it = containers.begin(); it != containers.end(); it++) { + if (it->toObject().value(config_key::container).toString() == ContainerProps::containerToString(DockerContainer::Dns)) { + return true; + } + } + return false; +} + +QStringList ServersModel::getAllInstalledServicesName(const int serverIndex) +{ + QStringList servicesName; + QJsonObject server = m_servers.at(serverIndex).toObject(); + const auto containers = server.value(config_key::containers).toArray(); + for (auto it = containers.begin(); it != containers.end(); it++) { + auto container = ContainerProps::containerFromString(it->toObject().value(config_key::container).toString()); + if (ContainerProps::containerService(container) == ServiceType::Other) { + if (container == DockerContainer::Dns) { + servicesName.append("DNS"); + } else if (container == DockerContainer::Sftp) { + servicesName.append("SFTP"); + } else if (container == DockerContainer::TorWebSite) { + servicesName.append("TOR"); + } + } + } + servicesName.sort(); + return servicesName; +} + +void ServersModel::toggleAmneziaDns(bool enabled) +{ + m_isAmneziaDnsEnabled = enabled; + emit defaultServerDescriptionChanged(); +} + diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h index f2998846..901605e2 100644 --- a/client/ui/models/servers_model.h +++ b/client/ui/models/servers_model.h @@ -11,13 +11,21 @@ class ServersModel : public QAbstractListModel public: enum Roles { NameRole = Qt::UserRole + 1, + ServerDescriptionRole, + HostNameRole, + CredentialsRole, CredentialsLoginRole, + IsDefaultRole, IsCurrentlyProcessedRole, + HasWriteAccessRole, - ContainsAmneziaDnsRole + + ContainsAmneziaDnsRole, + + DefaultContainerRole }; ServersModel(std::shared_ptr settings, QObject *parent = nullptr); @@ -33,6 +41,10 @@ public: Q_PROPERTY(int defaultIndex READ getDefaultServerIndex WRITE setDefaultServerIndex NOTIFY defaultServerIndexChanged) Q_PROPERTY(QString defaultServerName READ getDefaultServerName NOTIFY defaultServerNameChanged) Q_PROPERTY(QString defaultServerHostName READ getDefaultServerHostName NOTIFY defaultServerIndexChanged) + Q_PROPERTY(QString defaultContainerName READ getDefaultContainerName NOTIFY defaultContainerChanged) + Q_PROPERTY(QString defaultServerDescriptionCollapsed READ getDefaultServerDescriptionCollapsed NOTIFY defaultServerDescriptionChanged) + Q_PROPERTY(QString defaultServerDescriptionExpanded READ getDefaultServerDescriptionExpanded NOTIFY defaultServerDescriptionChanged) + Q_PROPERTY(int currentlyProcessedIndex READ getCurrentlyProcessedServerIndex WRITE setCurrentlyProcessedServerIndex NOTIFY currentlyProcessedServerIndexChanged) @@ -41,6 +53,8 @@ public slots: const int getDefaultServerIndex(); const QString getDefaultServerName(); const QString getDefaultServerHostName(); + const QString getDefaultServerDescriptionCollapsed(); + const QString getDefaultServerDescriptionExpanded(); bool isDefaultServerCurrentlyProcessed(); bool isCurrentlyProcessedServerHasWriteAccess(); @@ -54,15 +68,33 @@ public slots: QString getCurrentlyProcessedServerHostName(); const ServerCredentials getCurrentlyProcessedServerCredentials(); + const ServerCredentials getServerCredentials(const int index); void addServer(const QJsonObject &server); void editServer(const QJsonObject &server); void removeServer(); bool isDefaultServerConfigContainsAmneziaDns(); + bool isAmneziaDnsContainerInstalled(const int serverIndex); QJsonObject getDefaultServerConfig(); - void updateContainersConfig(); + + void reloadContainerConfig(); + void updateContainerConfig(const int containerIndex, const QJsonObject config); + void addContainerConfig(const int containerIndex, const QJsonObject config); + + void clearCachedProfiles(); + + ErrorCode removeContainer(const int containerIndex); + ErrorCode removeAllContainers(); + + void setDefaultContainer(const int containerIndex); + DockerContainer getDefaultContainer(); + const QString getDefaultContainerName(); + + QStringList getAllInstalledServicesName(const int serverIndex); + + void toggleAmneziaDns(bool enabled); protected: QHash roleNames() const override; @@ -71,9 +103,16 @@ signals: void currentlyProcessedServerIndexChanged(const int index); void defaultServerIndexChanged(const int index); void defaultServerNameChanged(); + void defaultServerDescriptionChanged(); + + void containersUpdated(QJsonArray &containers); + void defaultContainerChanged(const int containerIndex); private: ServerCredentials serverCredentials(int index) const; + void updateContainersModel(); + + QString getDefaultServerDescription(const QJsonObject &server); QJsonArray m_servers; @@ -81,6 +120,8 @@ private: int m_defaultServerIndex; int m_currentlyProcessedServerIndex; + + bool m_isAmneziaDnsEnabled = m_settings->useAmneziaDns(); }; #endif // SERVERSMODEL_H diff --git a/client/ui/qml/Components/HomeContainersListView.qml b/client/ui/qml/Components/HomeContainersListView.qml index f05b90d6..78ea9330 100644 --- a/client/ui/qml/Components/HomeContainersListView.qml +++ b/client/ui/qml/Components/HomeContainersListView.qml @@ -60,9 +60,8 @@ ListView { } if (checked) { - isDefault = true + ServersModel.setDefaultContainer(proxyContainersModel.mapToSource(index)) - menuContent.currentIndex = index containersDropDown.menuVisible = false } else { if (!isSupported && isInstalled) { diff --git a/client/ui/qml/Pages2/PageHome.qml b/client/ui/qml/Pages2/PageHome.qml index 222f7764..8374dbc3 100644 --- a/client/ui/qml/Pages2/PageHome.qml +++ b/client/ui/qml/Pages2/PageHome.qml @@ -22,10 +22,6 @@ PageType { property string borderColor: "#2C2D30" - property string defaultServerName: ServersModel.defaultServerName - property string defaultServerHostName: ServersModel.defaultServerHostName - property string defaultContainerName: ContainersModel.defaultContainerName - Connections { target: PageController @@ -40,41 +36,6 @@ PageType { } } - Connections { - target: ServersModel - - function onDefaultServerIndexChanged() { - updateDescriptions() - } - } - - Connections { - target: ContainersModel - - function onDefaultContainerChanged() { - updateDescriptions() - } - } - - function updateDescriptions() { - var description = "" - if (ServersModel.isDefaultServerHasWriteAccess()) { - if (SettingsController.isAmneziaDnsEnabled() - && ContainersModel.isAmneziaDnsContainerInstalled(ServersModel.getDefaultServerIndex())) { - description += "Amnezia DNS | " - } - } else { - if (ServersModel.isDefaultServerConfigContainsAmneziaDns()) { - description += "Amnezia DNS | " - } - } - - collapsedServerMenuDescription.text = description + root.defaultContainerName + " | " + root.defaultServerHostName - expandedServersMenuDescription.text = description + root.defaultServerHostName - } - - Component.onCompleted: updateDescriptions() - MouseArea { anchors.fill: parent enabled: buttonContent.state === "expanded" @@ -267,7 +228,7 @@ PageType { maximumLineCount: 2 elide: Qt.ElideRight - text: root.defaultServerName + text: ServersModel.defaultServerName horizontalAlignment: Qt.AlignHCenter Behavior on opacity { @@ -304,6 +265,7 @@ PageType { Layout.bottomMargin: 44 Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter visible: buttonContent.collapsedVisibility + text: ServersModel.defaultServerDescriptionCollapsed } ColumnLayout { @@ -319,7 +281,7 @@ PageType { Layout.leftMargin: 16 Layout.rightMargin: 16 - text: root.defaultServerName + text: ServersModel.defaultServerName horizontalAlignment: Qt.AlignHCenter maximumLineCount: 2 elide: Qt.ElideRight @@ -331,6 +293,7 @@ PageType { Layout.fillWidth: true horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter + text: ServersModel.defaultServerDescriptionExpanded } RowLayout { @@ -349,7 +312,7 @@ PageType { rootButtonTextTopMargin: 8 rootButtonTextBottomMargin: 8 - text: root.defaultContainerName + text: ServersModel.defaultContainerName textColor: "#0E0E11" headerText: qsTr("VPN protocol") headerBackButtonImage: "qrc:/images/controls/arrow-left.svg" @@ -468,7 +431,7 @@ PageType { var description = "" if (hasWriteAccess) { if (SettingsController.isAmneziaDnsEnabled() - && ContainersModel.isAmneziaDnsContainerInstalled(index)) { + && ServersModel.isAmneziaDnsContainerInstalled(index)) { description += "Amnezia DNS | " } } else { diff --git a/client/ui/qml/Pages2/PageServiceTorWebsiteSettings.qml b/client/ui/qml/Pages2/PageServiceTorWebsiteSettings.qml index 3bfa5bb0..aca4575c 100644 --- a/client/ui/qml/Pages2/PageServiceTorWebsiteSettings.qml +++ b/client/ui/qml/Pages2/PageServiceTorWebsiteSettings.qml @@ -66,8 +66,8 @@ PageType { text: qsTr("Website address") descriptionText: { - var config = ContainersModel.getCurrentlyProcessedContainerConfig() var containerIndex = ContainersModel.getCurrentlyProcessedContainerIndex() + var config = ContainersModel.getContainerConfig(containerIndex) return config[ContainerProps.containerTypeToString(containerIndex)]["site"] } diff --git a/client/ui/qml/Pages2/PageSettingsServersList.qml b/client/ui/qml/Pages2/PageSettingsServersList.qml index 040aafc3..dca904ae 100644 --- a/client/ui/qml/Pages2/PageSettingsServersList.qml +++ b/client/ui/qml/Pages2/PageSettingsServersList.qml @@ -77,7 +77,7 @@ PageType { text: name descriptionText: { var servicesNameString = "" - var servicesName = ContainersModel.getAllInstalledServicesName(index) + var servicesName = ServersModel.getAllInstalledServicesName(index) for (var i = 0; i < servicesName.length; i++) { servicesNameString += servicesName[i] + " · " } diff --git a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml index c82ce855..f7e82692 100644 --- a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml +++ b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml @@ -25,7 +25,7 @@ PageType { function onInstallContainerFinished(finishedMessage, isServiceInstall) { if (!ConnectionController.isConnected && !isServiceInstall) { - ContainersModel.setDefaultContainer(ContainersModel.getCurrentlyProcessedContainerIndex()) + ServersModel.setDefaultContainer(ContainersModel.getCurrentlyProcessedContainerIndex()) } PageController.closePage() // close installing page diff --git a/client/ui/qml/Pages2/PageShare.qml b/client/ui/qml/Pages2/PageShare.qml index 67a66931..ac9c7efb 100644 --- a/client/ui/qml/Pages2/PageShare.qml +++ b/client/ui/qml/Pages2/PageShare.qml @@ -354,8 +354,6 @@ PageType { currentIndex: 0 clickedFunction: function() { - protocolSelectorListView.currentItem.y - handler() protocolSelector.menuVisible = false @@ -365,7 +363,7 @@ PageType { target: serverSelector function onSeverSelectorIndexChanged() { - protocolSelectorListView.currentIndex = proxyContainersModel.mapFromSource(ContainersModel.getDefaultContainer()) + protocolSelectorListView.currentIndex = proxyContainersModel.mapFromSource(ServersModel.getDefaultContainer()) protocolSelectorListView.triggerCurrentItem() } } diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index dd4cf185..80163ef1 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -234,8 +234,6 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex, const Ser return ""; } - emit m_configurator->newVpnConfigCreated(clientId, "unnamed client", container, credentials); - QString configDataBeforeLocalProcessing = configData; configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData); @@ -247,6 +245,8 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex, const Ser protoObject.insert(config_key::last_config, configDataBeforeLocalProcessing); m_settings->setProtocolConfig(serverIndex, container, proto, protoObject); } + + emit m_configurator->newVpnConfigCreated(clientId, "unnamed client", container, credentials); } return configData; From e66fbc328987cef77e1434cd82400978e79cb368 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Mon, 11 Dec 2023 13:42:42 +0700 Subject: [PATCH 10/12] added default container installation, after downloading the config from the api --- client/amnezia_application.cpp | 3 --- client/ui/controllers/apiController.cpp | 6 ++++-- client/ui/controllers/apiController.h | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index 5079ed87..40aab515 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -376,7 +376,4 @@ void AmneziaApplication::initControllers() m_cloudController.reset(new ApiController(m_serversModel, m_containersModel)); m_engine->rootContext()->setContextProperty("ApiController", m_cloudController.get()); - - // connect(m_cloudController.get(), &ApiController::serverConfigUpdated, this, - // [this]() { m_containersModel->setCurrentlyProcessedServerIndex(m_serversModel->getDefaultServerIndex()); }); } diff --git a/client/ui/controllers/apiController.cpp b/client/ui/controllers/apiController.cpp index d0c440df..14a05410 100644 --- a/client/ui/controllers/apiController.cpp +++ b/client/ui/controllers/apiController.cpp @@ -109,9 +109,11 @@ bool ApiController::updateServerConfigFromApi() serverConfig.insert(config_key::dns2, cloudConfig.value(config_key::dns2)); serverConfig.insert(config_key::containers, cloudConfig.value(config_key::containers)); serverConfig.insert(config_key::hostName, cloudConfig.value(config_key::hostName)); - serverConfig.insert(config_key::defaultContainer, cloudConfig.value(config_key::defaultContainer)); + + auto defaultContainer = cloudConfig.value(config_key::defaultContainer).toString(); + serverConfig.insert(config_key::defaultContainer, defaultContainer); m_serversModel->editServer(serverConfig); - emit serverConfigUpdated(); + emit m_serversModel->defaultContainerChanged(ContainerProps::containerFromString(defaultContainer)); } else { QString err = reply->errorString(); qDebug() << QString::fromUtf8(reply->readAll()); //todo remove debug output diff --git a/client/ui/controllers/apiController.h b/client/ui/controllers/apiController.h index 5917f70f..1ce933c6 100644 --- a/client/ui/controllers/apiController.h +++ b/client/ui/controllers/apiController.h @@ -20,7 +20,6 @@ public slots: signals: void errorOccurred(const QString &errorMessage); - void serverConfigUpdated(); private: QString genPublicKey(const QString &protocol); From 39d1f1677f780d44ac8d39c5330161351fecdd99 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Wed, 13 Dec 2023 14:14:37 +0700 Subject: [PATCH 11/12] fixed description update, after changing the default protocol --- client/ui/controllers/importController.cpp | 2 -- client/ui/models/servers_model.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/client/ui/controllers/importController.cpp b/client/ui/controllers/importController.cpp index a8aab2b2..062b10a4 100644 --- a/client/ui/controllers/importController.cpp +++ b/client/ui/controllers/importController.cpp @@ -169,8 +169,6 @@ QJsonObject ImportController::extractAmneziaConfig(QString &data) QJsonObject config = QJsonDocument::fromJson(ba).object(); - qDebug() << config; - return config; } diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index ed1f4b0b..ad927fce 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -10,7 +10,7 @@ ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) m_currentlyProcessedServerIndex = m_defaultServerIndex; connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerNameChanged); - connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerDescriptionChanged); + connect(this, &ServersModel::defaultContainerChanged, this, &ServersModel::defaultServerDescriptionChanged); connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) { auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString()); emit ServersModel::defaultContainerChanged(defaultContainer); From f52c3c430ff52336e8ac5add7f3a9d556d66bdc1 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Thu, 14 Dec 2023 11:03:27 +0700 Subject: [PATCH 12/12] added notification after config revokation --- client/ui/qml/Pages2/PageShare.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ui/qml/Pages2/PageShare.qml b/client/ui/qml/Pages2/PageShare.qml index ac9c7efb..38010b8f 100644 --- a/client/ui/qml/Pages2/PageShare.qml +++ b/client/ui/qml/Pages2/PageShare.qml @@ -31,6 +31,7 @@ PageType { ContainersModel.getCurrentlyProcessedContainerIndex(), ServersModel.getCurrentlyProcessedServerCredentials()) PageController.showBusyIndicator(false) + PageController.showNotificationMessage(qsTr("Config revoked")) } Connections {