From a6ca1b12dadb9b00a136e928c475bd26d38f7402 Mon Sep 17 00:00:00 2001 From: Nethius Date: Mon, 1 Apr 2024 20:20:02 +0700 Subject: [PATCH] moved protocol config generation to VpnConfigirationsController (#665) Moved protocol config generation to VpnConfigurationsController --- client/CMakeLists.txt | 4 + client/amnezia_application.cpp | 65 +-- client/amnezia_application.h | 4 +- client/configurators/awg_configurator.cpp | 6 +- client/configurators/awg_configurator.h | 4 +- client/configurators/cloak_configurator.cpp | 16 +- client/configurators/cloak_configurator.h | 6 +- client/configurators/configurator_base.cpp | 22 +- client/configurators/configurator_base.h | 13 +- client/configurators/ikev2_configurator.cpp | 16 +- client/configurators/ikev2_configurator.h | 8 +- client/configurators/openvpn_configurator.cpp | 60 ++- client/configurators/openvpn_configurator.h | 34 +- .../shadowsocks_configurator.cpp | 10 +- .../configurators/shadowsocks_configurator.h | 6 +- client/configurators/vpn_configurator.cpp | 131 ------ client/configurators/vpn_configurator.h | 54 --- .../configurators/wireguard_configurator.cpp | 86 ++-- client/configurators/wireguard_configurator.h | 14 +- client/configurators/xray_configurator.cpp | 31 +- client/configurators/xray_configurator.h | 6 +- client/containers/containers_defs.cpp | 13 + client/containers/containers_defs.h | 2 + .../controllers/apiController.cpp | 53 +-- .../{ui => core}/controllers/apiController.h | 19 +- client/core/controllers/serverController.cpp | 161 +------ client/core/controllers/serverController.h | 7 +- .../vpnConfigurationController.cpp | 137 ++++++ .../controllers/vpnConfigurationController.h | 35 ++ client/protocols/protocols_defs.h | 2 + .../ui/controllers/connectionController.cpp | 117 ++++- client/ui/controllers/connectionController.h | 19 +- client/ui/controllers/exportController.cpp | 272 ++++------- client/ui/controllers/exportController.h | 15 +- client/ui/controllers/installController.cpp | 421 +++++++++++++----- client/ui/controllers/installController.h | 32 +- client/ui/controllers/settingsController.cpp | 6 - client/ui/controllers/settingsController.h | 1 - client/ui/models/clientManagementModel.cpp | 136 ++++-- client/ui/models/clientManagementModel.h | 7 +- client/ui/models/containers_model.cpp | 14 +- client/ui/models/containers_model.h | 8 +- .../protocols/shadowsocksConfigModel.cpp | 4 + .../models/protocols/shadowsocksConfigModel.h | 4 +- .../models/protocols/wireguardConfigModel.cpp | 2 +- client/ui/models/protocols_model.cpp | 1 + client/ui/models/servers_model.cpp | 75 ++-- client/ui/models/servers_model.h | 4 +- client/ui/qml/Components/ConnectButton.qml | 10 +- .../qml/Components/HomeContainersListView.qml | 2 +- .../Components/SettingsContainersListView.qml | 25 +- .../ui/qml/Pages2/PageProtocolAwgSettings.qml | 28 -- .../Pages2/PageProtocolOpenVpnSettings.qml | 32 -- client/ui/qml/Pages2/PageProtocolRaw.qml | 8 +- .../PageProtocolShadowSocksSettings.qml | 6 + .../Pages2/PageProtocolWireGuardSettings.qml | 33 -- .../qml/Pages2/PageProtocolXraySettings.qml | 37 +- .../ui/qml/Pages2/PageServiceDnsSettings.qml | 6 +- .../ui/qml/Pages2/PageServiceSftpSettings.qml | 2 +- .../Pages2/PageServiceTorWebsiteSettings.qml | 4 +- .../ui/qml/Pages2/PageSettingsServerData.qml | 33 +- .../qml/Pages2/PageSettingsServerProtocol.qml | 198 ++++---- .../qml/Pages2/PageSetupWizardCredentials.qml | 2 +- client/ui/qml/Pages2/PageSetupWizardEasy.qml | 2 +- .../qml/Pages2/PageSetupWizardInstalling.qml | 2 +- .../qml/Pages2/PageSetupWizardProtocols.qml | 2 +- client/ui/qml/Pages2/PageShare.qml | 11 +- client/ui/qml/Pages2/PageStart.qml | 4 + client/vpnconnection.cpp | 123 +---- client/vpnconnection.h | 21 +- 70 files changed, 1305 insertions(+), 1449 deletions(-) delete mode 100644 client/configurators/vpn_configurator.cpp delete mode 100644 client/configurators/vpn_configurator.h rename client/{ui => core}/controllers/apiController.cpp (74%) rename client/{ui => core}/controllers/apiController.h (53%) create mode 100644 client/core/controllers/vpnConfigurationController.cpp create mode 100644 client/core/controllers/vpnConfigurationController.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 7dc05311b..8a4af91fe 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -119,7 +119,9 @@ 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/controllers/apiController.h ${CMAKE_CURRENT_LIST_DIR}/core/controllers/serverController.h + ${CMAKE_CURRENT_LIST_DIR}/core/controllers/vpnConfigurationController.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 @@ -159,7 +161,9 @@ 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/controllers/apiController.cpp ${CMAKE_CURRENT_LIST_DIR}/core/controllers/serverController.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/controllers/vpnConfigurationController.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 c288feb49..f57861ed8 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -84,8 +84,7 @@ void AmneziaApplication::init() m_engine->rootContext()->setContextProperty("Debug", &Logger::Instance()); - m_configurator = std::shared_ptr(new VpnConfigurator(m_settings, this)); - m_vpnConnection.reset(new VpnConnection(m_settings, m_configurator)); + m_vpnConnection.reset(new VpnConnection(m_settings)); m_vpnConnection->moveToThread(&m_vpnConnectionThread); m_vpnConnectionThread.start(); @@ -98,18 +97,16 @@ void AmneziaApplication::init() qFatal("Android logging initialization failed"); } AndroidController::instance()->setSaveLogs(m_settings->isSaveLogs()); - connect(m_settings.get(), &Settings::saveLogsChanged, - AndroidController::instance(), &AndroidController::setSaveLogs); + connect(m_settings.get(), &Settings::saveLogsChanged, AndroidController::instance(), &AndroidController::setSaveLogs); AndroidController::instance()->setScreenshotsEnabled(m_settings->isScreenshotsEnabled()); - connect(m_settings.get(), &Settings::screenshotsEnabledChanged, - AndroidController::instance(), &AndroidController::setScreenshotsEnabled); + connect(m_settings.get(), &Settings::screenshotsEnabledChanged, AndroidController::instance(), + &AndroidController::setScreenshotsEnabled); - connect(m_settings.get(), &Settings::serverRemoved, - AndroidController::instance(), &AndroidController::resetLastServer); + connect(m_settings.get(), &Settings::serverRemoved, AndroidController::instance(), + &AndroidController::resetLastServer); - connect(m_settings.get(), &Settings::settingsCleared, - [](){ AndroidController::instance()->resetLastServer(-1); }); + connect(m_settings.get(), &Settings::settingsCleared, []() { AndroidController::instance()->resetLastServer(-1); }); connect(AndroidController::instance(), &AndroidController::initConnectionState, this, [this](Vpn::ConnectionState state) { @@ -146,13 +143,10 @@ void AmneziaApplication::init() m_settingsController->importBackupFromOutside(filePath); }); - QTimer::singleShot(0, this, [this](){ - AmneziaVPN::toggleScreenshots(m_settings->isScreenshotsEnabled()); - }); + QTimer::singleShot(0, this, [this]() { AmneziaVPN::toggleScreenshots(m_settings->isScreenshotsEnabled()); }); - connect(m_settings.get(), &Settings::screenshotsEnabledChanged, [](bool enabled) { - AmneziaVPN::toggleScreenshots(enabled); - }); + connect(m_settings.get(), &Settings::screenshotsEnabledChanged, + [](bool enabled) { AmneziaVPN::toggleScreenshots(enabled); }); #endif m_notificationHandler.reset(NotificationHandler::create(nullptr)); @@ -368,28 +362,30 @@ void AmneziaApplication::initModels() m_engine->rootContext()->setContextProperty("ClientManagementModel", m_clientManagementModel.get()); connect(m_clientManagementModel.get(), &ClientManagementModel::adminConfigRevoked, m_serversModel.get(), &ServersModel::clearCachedProfile); - - connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, this, - [this](const QString &clientId, const QString &clientName, const DockerContainer container, - ServerCredentials credentials) { - m_serversModel->reloadDefaultServerContainerConfig(); - m_clientManagementModel->appendClient(clientId, clientName, container, credentials); - emit m_configurator->clientModelUpdated(); - }); } void AmneziaApplication::initControllers() { - m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel, m_vpnConnection)); + m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel, m_clientManagementModel, + m_vpnConnection, m_settings)); m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get()); + connect(m_connectionController.get(), &ConnectionController::connectionErrorOccurred, this, + [this](const QString &errorMessage) { + emit m_pageController->showErrorMessage(errorMessage); + emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); + }); + connect(m_connectionController.get(), &ConnectionController::connectButtonClicked, m_connectionController.get(), + &ConnectionController::toggleConnection, Qt::QueuedConnection); + 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()); - m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, m_settings)); + m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, + m_clientManagementModel, m_settings)); m_engine->rootContext()->setContextProperty("InstallController", m_installController.get()); connect(m_installController.get(), &InstallController::passphraseRequestStarted, m_pageController.get(), &PageController::showPassphraseRequestDrawer); @@ -401,8 +397,7 @@ 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_engine->rootContext()->setContextProperty("ExportController", m_exportController.get()); m_settingsController.reset( @@ -422,18 +417,4 @@ void AmneziaApplication::initControllers() m_systemController.reset(new SystemController(m_settings)); m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get()); - - m_apiController.reset(new ApiController(m_serversModel, m_containersModel)); - m_engine->rootContext()->setContextProperty("ApiController", m_apiController.get()); - connect(m_apiController.get(), &ApiController::updateStarted, this, - [this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Connecting); }); - connect(m_apiController.get(), &ApiController::errorOccurred, this, [this](const QString &errorMessage) { - if (m_connectionController->isConnectionInProgress()) { - emit m_pageController->showErrorMessage(errorMessage); - } - - emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); - }); - connect(m_apiController.get(), &ApiController::updateFinished, m_connectionController.get(), - &ConnectionController::toggleConnection); } diff --git a/client/amnezia_application.h b/client/amnezia_application.h index 9e073d3f8..aadc6a0c6 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -14,7 +14,7 @@ #include "settings.h" #include "vpnconnection.h" -#include "configurators/vpn_configurator.h" +#include "core/controllers/apiController.h" #include "ui/controllers/connectionController.h" #include "ui/controllers/exportController.h" @@ -24,7 +24,6 @@ #include "ui/controllers/settingsController.h" #include "ui/controllers/sitesController.h" #include "ui/controllers/systemController.h" -#include "ui/controllers/apiController.h" #include "ui/controllers/appSplitTunnelingController.h" #include "ui/models/containers_model.h" #include "ui/models/languageModel.h" @@ -86,7 +85,6 @@ class AmneziaApplication : public AMNEZIA_BASE_CLASS QQmlApplicationEngine *m_engine {}; std::shared_ptr m_settings; - std::shared_ptr m_configurator; QSharedPointer m_containerProps; QSharedPointer m_protocolProps; diff --git a/client/configurators/awg_configurator.cpp b/client/configurators/awg_configurator.cpp index 186d20094..a9b41882a 100644 --- a/client/configurators/awg_configurator.cpp +++ b/client/configurators/awg_configurator.cpp @@ -10,10 +10,10 @@ AwgConfigurator::AwgConfigurator(std::shared_ptr settings, QObject *pa { } -QString AwgConfigurator::genAwgConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode) +QString AwgConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode) { - QString config = WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, clientId, errorCode); + QString config = WireguardConfigurator::createConfig(credentials, container, containerConfig, errorCode); QJsonObject jsonConfig = QJsonDocument::fromJson(config.toUtf8()).object(); QString awgConfig = jsonConfig.value(config_key::config).toString(); diff --git a/client/configurators/awg_configurator.h b/client/configurators/awg_configurator.h index ef40804ca..8decd2d69 100644 --- a/client/configurators/awg_configurator.h +++ b/client/configurators/awg_configurator.h @@ -11,8 +11,8 @@ class AwgConfigurator : public WireguardConfigurator public: AwgConfigurator(std::shared_ptr settings, QObject *parent = nullptr); - QString genAwgConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode = nullptr); + QString createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode); }; #endif // AWGCONFIGURATOR_H diff --git a/client/configurators/cloak_configurator.cpp b/client/configurators/cloak_configurator.cpp index 88be71e13..6c719c70d 100644 --- a/client/configurators/cloak_configurator.cpp +++ b/client/configurators/cloak_configurator.cpp @@ -13,22 +13,24 @@ CloakConfigurator::CloakConfigurator(std::shared_ptr settings, QObject } -QString CloakConfigurator::genCloakConfig(const ServerCredentials &credentials, - DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode) +QString CloakConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode) { - ErrorCode e = ErrorCode::NoError; ServerController serverController(m_settings); QString cloakPublicKey = serverController.getTextFileFromContainer(container, credentials, - amnezia::protocols::cloak::ckPublicKeyPath, &e); + amnezia::protocols::cloak::ckPublicKeyPath, errorCode); cloakPublicKey.replace("\n", ""); + if (errorCode != ErrorCode::NoError) { + return ""; + } + QString cloakBypassUid = serverController.getTextFileFromContainer(container, credentials, - amnezia::protocols::cloak::ckBypassUidKeyPath, &e); + amnezia::protocols::cloak::ckBypassUidKeyPath, errorCode); cloakBypassUid.replace("\n", ""); - if (e) { - if (errorCode) *errorCode = e; + if (errorCode != ErrorCode::NoError) { return ""; } diff --git a/client/configurators/cloak_configurator.h b/client/configurators/cloak_configurator.h index cf6cd002f..5dbfd190f 100644 --- a/client/configurators/cloak_configurator.h +++ b/client/configurators/cloak_configurator.h @@ -7,14 +7,14 @@ using namespace amnezia; -class CloakConfigurator : ConfiguratorBase +class CloakConfigurator : public ConfiguratorBase { Q_OBJECT public: CloakConfigurator(std::shared_ptr settings, QObject *parent = nullptr); - QString genCloakConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); + QString createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode); }; #endif // CLOAK_CONFIGURATOR_H diff --git a/client/configurators/configurator_base.cpp b/client/configurators/configurator_base.cpp index c24d7e1f2..7393cb1a3 100644 --- a/client/configurators/configurator_base.cpp +++ b/client/configurators/configurator_base.cpp @@ -1,8 +1,26 @@ #include "configurator_base.h" ConfiguratorBase::ConfiguratorBase(std::shared_ptr settings, QObject *parent) - : QObject{parent}, - m_settings(settings) + : QObject { parent }, m_settings(settings) { +} + +QString ConfiguratorBase::processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString) +{ + processConfigWithDnsSettings(dns, protocolConfigString); + return protocolConfigString; +} +QString ConfiguratorBase::processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString) +{ + processConfigWithDnsSettings(dns, protocolConfigString); + return protocolConfigString; +} + +void ConfiguratorBase::processConfigWithDnsSettings(const QPair &dns, QString &protocolConfigString) +{ + protocolConfigString.replace("$PRIMARY_DNS", dns.first); + protocolConfigString.replace("$SECONDARY_DNS", dns.second); } diff --git a/client/configurators/configurator_base.h b/client/configurators/configurator_base.h index da43a2bc2..3330e2721 100644 --- a/client/configurators/configurator_base.h +++ b/client/configurators/configurator_base.h @@ -3,10 +3,9 @@ #include -class Settings; - #include "containers/containers_defs.h" #include "core/defs.h" +#include "settings.h" class ConfiguratorBase : public QObject { @@ -14,7 +13,17 @@ class ConfiguratorBase : public QObject public: explicit ConfiguratorBase(std::shared_ptr settings, QObject *parent = nullptr); + virtual QString createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode) = 0; + + virtual QString processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString); + virtual QString processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString); + protected: + void processConfigWithDnsSettings(const QPair &dns, QString &protocolConfigString); + std::shared_ptr m_settings; }; diff --git a/client/configurators/ikev2_configurator.cpp b/client/configurators/ikev2_configurator.cpp index 752d17502..9a8eebb0d 100644 --- a/client/configurators/ikev2_configurator.cpp +++ b/client/configurators/ikev2_configurator.cpp @@ -20,7 +20,7 @@ Ikev2Configurator::Ikev2Configurator(std::shared_ptr settings, QObject } Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const ServerCredentials &credentials, - DockerContainer container, ErrorCode *errorCode) + DockerContainer container, ErrorCode errorCode) { Ikev2Configurator::ConnectionData connData; connData.host = credentials.hostName; @@ -40,17 +40,17 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se .arg(connData.clientId); ServerController serverController(m_settings); - ErrorCode e = serverController.runContainerScript(credentials, container, scriptCreateCert); + errorCode = serverController.runContainerScript(credentials, container, scriptCreateCert); QString scriptExportCert = QString("pk12util -W \"%1\" -d sql:/etc/ipsec.d -n \"%2\" -o \"%3\"") .arg(connData.password) .arg(connData.clientId) .arg(certFileName); - e = serverController.runContainerScript(credentials, container, scriptExportCert); + errorCode = serverController.runContainerScript(credentials, container, scriptExportCert); - connData.clientCert = serverController.getTextFileFromContainer(container, credentials, certFileName, &e); + connData.clientCert = serverController.getTextFileFromContainer(container, credentials, certFileName, errorCode); connData.caCert = - serverController.getTextFileFromContainer(container, credentials, "/etc/ipsec.d/ca_cert_base64.p12", &e); + serverController.getTextFileFromContainer(container, credentials, "/etc/ipsec.d/ca_cert_base64.p12", errorCode); qDebug() << "Ikev2Configurator::ConnectionData client cert size:" << connData.clientCert.size(); qDebug() << "Ikev2Configurator::ConnectionData ca cert size:" << connData.caCert.size(); @@ -58,13 +58,13 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se return connData; } -QString Ikev2Configurator::genIkev2Config(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode *errorCode) +QString Ikev2Configurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode) { Q_UNUSED(containerConfig) ConnectionData connData = prepareIkev2Config(credentials, container, errorCode); - if (errorCode && *errorCode) { + if (errorCode != ErrorCode::NoError) { return ""; } diff --git a/client/configurators/ikev2_configurator.h b/client/configurators/ikev2_configurator.h index a7d379f24..53b825250 100644 --- a/client/configurators/ikev2_configurator.h +++ b/client/configurators/ikev2_configurator.h @@ -7,7 +7,7 @@ #include "configurator_base.h" #include "core/defs.h" -class Ikev2Configurator : ConfiguratorBase +class Ikev2Configurator : public ConfiguratorBase { Q_OBJECT public: @@ -21,15 +21,15 @@ class Ikev2Configurator : ConfiguratorBase QString host; // host ip }; - QString genIkev2Config(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); + QString createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode); QString genIkev2Config(const ConnectionData &connData); QString genMobileConfig(const ConnectionData &connData); QString genStrongSwanConfig(const ConnectionData &connData); ConnectionData prepareIkev2Config(const ServerCredentials &credentials, - DockerContainer container, ErrorCode *errorCode = nullptr); + DockerContainer container, ErrorCode errorCode); }; #endif // IKEV2_CONFIGURATOR_H diff --git a/client/configurators/openvpn_configurator.cpp b/client/configurators/openvpn_configurator.cpp index 0cd331f7b..22628ce7f 100644 --- a/client/configurators/openvpn_configurator.cpp +++ b/client/configurators/openvpn_configurator.cpp @@ -14,9 +14,9 @@ #endif #include "containers/containers_defs.h" +#include "core/controllers/serverController.h" #include "core/scripts_registry.h" #include "core/server_defs.h" -#include "core/controllers/serverController.h" #include "settings.h" #include "utilities.h" @@ -31,59 +31,51 @@ OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr settings, QOb OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, - ErrorCode *errorCode) + ErrorCode errorCode) { OpenVpnConfigurator::ConnectionData connData = OpenVpnConfigurator::createCertRequest(); connData.host = credentials.hostName; if (connData.privKey.isEmpty() || connData.request.isEmpty()) { - if (errorCode) - *errorCode = ErrorCode::OpenSslFailed; + errorCode = ErrorCode::OpenSslFailed; return connData; } QString reqFileName = QString("%1/%2.req").arg(amnezia::protocols::openvpn::clientsDirPath).arg(connData.clientId); ServerController serverController(m_settings); - ErrorCode e = serverController.uploadTextFileToContainer(container, credentials, connData.request, reqFileName); - if (e) { - if (errorCode) - *errorCode = e; + errorCode = serverController.uploadTextFileToContainer(container, credentials, connData.request, reqFileName); + if (errorCode != ErrorCode::NoError) { return connData; } - e = signCert(container, credentials, connData.clientId); - if (e) { - if (errorCode) - *errorCode = e; + errorCode = signCert(container, credentials, connData.clientId); + if (errorCode != ErrorCode::NoError) { return connData; } connData.caCert = serverController.getTextFileFromContainer(container, credentials, - amnezia::protocols::openvpn::caCertPath, &e); + amnezia::protocols::openvpn::caCertPath, errorCode); connData.clientCert = serverController.getTextFileFromContainer( container, credentials, - QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), &e); + QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), errorCode); - if (e) { - if (errorCode) - *errorCode = e; + if (errorCode != ErrorCode::NoError) { return connData; } connData.taKey = serverController.getTextFileFromContainer(container, credentials, - amnezia::protocols::openvpn::taKeyPath, &e); + amnezia::protocols::openvpn::taKeyPath, errorCode); if (connData.caCert.isEmpty() || connData.clientCert.isEmpty() || connData.taKey.isEmpty()) { - if (errorCode) - *errorCode = ErrorCode::SshScpFailureError; + errorCode = ErrorCode::SshScpFailureError; } return connData; } -QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode) +QString OpenVpnConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode) { ServerController serverController(m_settings); QString config = @@ -91,7 +83,7 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia serverController.genVarsForScript(credentials, container, containerConfig)); ConnectionData connData = prepareOpenVpnConfig(credentials, container, errorCode); - if (errorCode && *errorCode) { + if (errorCode != ErrorCode::NoError) { return ""; } @@ -113,17 +105,20 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia QJsonObject jConfig; jConfig[config_key::config] = config; - clientId = connData.clientId; + jConfig[config_key::clientId] = connData.clientId; return QJsonDocument(jConfig).toJson(); } -QString OpenVpnConfigurator::processConfigWithLocalSettings(QString jsonConfig, const int serverIndex) +QString OpenVpnConfigurator::processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString) { - QJsonObject json = QJsonDocument::fromJson(jsonConfig.toUtf8()).object(); + processConfigWithDnsSettings(dns, protocolConfigString); + + QJsonObject json = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object(); QString config = json[config_key::config].toString(); - if (!m_settings->server(serverIndex).value(config_key::configVersion).toInt()) { + if (!isApiConfig) { QRegularExpression regex("redirect-gateway.*"); config.replace(regex, ""); @@ -138,9 +133,9 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(QString jsonConfig, // no redirect-gateway } if (m_settings->routeMode() == Settings::VpnAllExceptSites) { - #ifndef Q_OS_ANDROID +#ifndef Q_OS_ANDROID config.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n"); - #endif +#endif // Prevent ipv6 leak config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n"); config.append("block-ipv6\n"); @@ -164,9 +159,12 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(QString jsonConfig, return QJsonDocument(json).toJson(); } -QString OpenVpnConfigurator::processConfigWithExportSettings(QString jsonConfig) +QString OpenVpnConfigurator::processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString) { - QJsonObject json = QJsonDocument::fromJson(jsonConfig.toUtf8()).object(); + processConfigWithDnsSettings(dns, protocolConfigString); + + QJsonObject json = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object(); QString config = json[config_key::config].toString(); QRegularExpression regex("redirect-gateway.*"); diff --git a/client/configurators/openvpn_configurator.h b/client/configurators/openvpn_configurator.h index 424a20e1b..eb99be40d 100644 --- a/client/configurators/openvpn_configurator.h +++ b/client/configurators/openvpn_configurator.h @@ -7,37 +7,37 @@ #include "configurator_base.h" #include "core/defs.h" -class OpenVpnConfigurator : ConfiguratorBase +class OpenVpnConfigurator : public ConfiguratorBase { Q_OBJECT public: OpenVpnConfigurator(std::shared_ptr settings, QObject *parent = nullptr); - struct ConnectionData { + struct ConnectionData + { QString clientId; - QString request; // certificate request - QString privKey; // client private key + QString request; // certificate request + QString privKey; // client private key QString clientCert; // client signed certificate - QString caCert; // server certificate - QString taKey; // tls-auth key - QString host; // host ip + QString caCert; // server certificate + QString taKey; // tls-auth key + QString host; // host ip }; - QString genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode = nullptr); + QString createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode); - QString processConfigWithLocalSettings(QString jsonConfig, const int serverIndex); - QString processConfigWithExportSettings(QString jsonConfig); - - ErrorCode signCert(DockerContainer container, - const ServerCredentials &credentials, QString clientId); + QString processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString); + QString processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString); static ConnectionData createCertRequest(); private: - ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials, - DockerContainer container, ErrorCode *errorCode = nullptr); - + ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, + ErrorCode errorCode); + ErrorCode signCert(DockerContainer container, const ServerCredentials &credentials, QString clientId); }; #endif // OPENVPN_CONFIGURATOR_H diff --git a/client/configurators/shadowsocks_configurator.cpp b/client/configurators/shadowsocks_configurator.cpp index 99e4158c3..28162962c 100644 --- a/client/configurators/shadowsocks_configurator.cpp +++ b/client/configurators/shadowsocks_configurator.cpp @@ -13,18 +13,16 @@ ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr setti } -QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &credentials, - DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode) +QString ShadowSocksConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode) { - ErrorCode e = ErrorCode::NoError; ServerController serverController(m_settings); QString ssKey = serverController.getTextFileFromContainer(container, credentials, - amnezia::protocols::shadowsocks::ssKeyPath, &e); + amnezia::protocols::shadowsocks::ssKeyPath, errorCode); ssKey.replace("\n", ""); - if (e) { - if (errorCode) *errorCode = e; + if (errorCode != ErrorCode::NoError) { return ""; } diff --git a/client/configurators/shadowsocks_configurator.h b/client/configurators/shadowsocks_configurator.h index b03149eb2..f67045b32 100644 --- a/client/configurators/shadowsocks_configurator.h +++ b/client/configurators/shadowsocks_configurator.h @@ -6,14 +6,14 @@ #include "configurator_base.h" #include "core/defs.h" -class ShadowSocksConfigurator : ConfiguratorBase +class ShadowSocksConfigurator : public ConfiguratorBase { Q_OBJECT public: ShadowSocksConfigurator(std::shared_ptr settings, QObject *parent = nullptr); - QString genShadowSocksConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); + QString createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode); }; #endif // SHADOWSOCKS_CONFIGURATOR_H diff --git a/client/configurators/vpn_configurator.cpp b/client/configurators/vpn_configurator.cpp deleted file mode 100644 index a5dc335d3..000000000 --- a/client/configurators/vpn_configurator.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include "vpn_configurator.h" -#include "cloak_configurator.h" -#include "ikev2_configurator.h" -#include "openvpn_configurator.h" -#include "shadowsocks_configurator.h" -#include "ssh_configurator.h" -#include "wireguard_configurator.h" -#include "awg_configurator.h" -#include "xray_configurator.h" -#include -#include -#include - -#include "containers/containers_defs.h" -#include "settings.h" -#include "core/networkUtilities.h" - -VpnConfigurator::VpnConfigurator(std::shared_ptr settings, QObject *parent) - : ConfiguratorBase(settings, parent) -{ - openVpnConfigurator = std::shared_ptr(new OpenVpnConfigurator(settings, this)); - shadowSocksConfigurator = std::shared_ptr(new ShadowSocksConfigurator(settings, this)); - cloakConfigurator = std::shared_ptr(new CloakConfigurator(settings, this)); - wireguardConfigurator = std::shared_ptr(new WireguardConfigurator(settings, false, this)); - ikev2Configurator = std::shared_ptr(new Ikev2Configurator(settings, this)); - sshConfigurator = std::shared_ptr(new SshConfigurator(settings, this)); - awgConfigurator = std::shared_ptr(new AwgConfigurator(settings, this)); - xrayConfigurator = std::shared_ptr(new XrayConfigurator(settings, this)); -} - -QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, Proto proto, QString &clientId, ErrorCode *errorCode) -{ - switch (proto) { - case Proto::OpenVpn: - return openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, clientId, errorCode); - - case Proto::ShadowSocks: - return shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, errorCode); - - case Proto::Cloak: return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode); - - case Proto::WireGuard: - return wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, clientId, errorCode); - - case Proto::Awg: - return awgConfigurator->genAwgConfig(credentials, container, containerConfig, clientId, errorCode); - - case Proto::Xray: - return xrayConfigurator->genXrayConfig(credentials, container, containerConfig, clientId, errorCode); - - case Proto::Ikev2: return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode); - - default: return ""; - } -} - -QPair VpnConfigurator::getDnsForConfig(int serverIndex) -{ - QPair dns; - - bool useAmneziaDns = m_settings->useAmneziaDns(); - const QJsonObject &server = m_settings->server(serverIndex); - - dns.first = server.value(config_key::dns1).toString(); - dns.second = server.value(config_key::dns2).toString(); - - if (dns.first.isEmpty() || !NetworkUtilities::checkIPv4Format(dns.first)) { - if (useAmneziaDns && m_settings->containers(serverIndex).contains(DockerContainer::Dns)) { - dns.first = protocols::dns::amneziaDnsIp; - } else - dns.first = m_settings->primaryDns(); - } - if (dns.second.isEmpty() || !NetworkUtilities::checkIPv4Format(dns.second)) { - dns.second = m_settings->secondaryDns(); - } - - qDebug() << "VpnConfigurator::getDnsForConfig" << dns.first << dns.second; - return dns; -} - -QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, - QString &config) -{ - auto dns = getDnsForConfig(serverIndex); - - config.replace("$PRIMARY_DNS", dns.first); - config.replace("$SECONDARY_DNS", dns.second); - - return config; -} - -QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, DockerContainer container, Proto proto, - QString &config) -{ - processConfigWithDnsSettings(serverIndex, container, proto, config); - - if (proto == Proto::OpenVpn) { - config = openVpnConfigurator->processConfigWithLocalSettings(config, serverIndex); - } - return config; -} - -QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, - QString &config) -{ - processConfigWithDnsSettings(serverIndex, container, proto, config); - - if (proto == Proto::OpenVpn) { - config = openVpnConfigurator->processConfigWithExportSettings(config); - } - return config; -} - -void VpnConfigurator::updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig, - const QString &stdOut) -{ - Proto mainProto = ContainerProps::defaultProtocol(container); - - if (container == DockerContainer::TorWebSite) { - QJsonObject protocol = containerConfig.value(ProtocolProps::protoToString(mainProto)).toObject(); - - qDebug() << "amnezia-tor onions" << stdOut; - - QString onion = stdOut; - onion.replace("\n", ""); - protocol.insert(config_key::site, onion); - - containerConfig.insert(ProtocolProps::protoToString(mainProto), protocol); - } -} diff --git a/client/configurators/vpn_configurator.h b/client/configurators/vpn_configurator.h deleted file mode 100644 index 453ff6baf..000000000 --- a/client/configurators/vpn_configurator.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef VPN_CONFIGURATOR_H -#define VPN_CONFIGURATOR_H - -#include - -#include "configurator_base.h" -#include "core/defs.h" - -class OpenVpnConfigurator; -class ShadowSocksConfigurator; -class CloakConfigurator; -class WireguardConfigurator; -class Ikev2Configurator; -class SshConfigurator; -class AwgConfigurator; -class XrayConfigurator; - -// Retrieve connection settings from server -class VpnConfigurator : public ConfiguratorBase -{ - Q_OBJECT -public: - explicit VpnConfigurator(std::shared_ptr settings, QObject *parent = nullptr); - - QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, Proto proto, QString &clientId, - ErrorCode *errorCode = nullptr); - - QPair getDnsForConfig(int serverIndex); - QString &processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, QString &config); - - QString &processConfigWithLocalSettings(int serverIndex, DockerContainer container, Proto proto, QString &config); - QString &processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config); - - // workaround for containers which is not support normal configuration - void updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig, - const QString &stdOut); - - std::shared_ptr openVpnConfigurator; - std::shared_ptr shadowSocksConfigurator; - std::shared_ptr cloakConfigurator; - std::shared_ptr wireguardConfigurator; - std::shared_ptr ikev2Configurator; - std::shared_ptr sshConfigurator; - std::shared_ptr awgConfigurator; - std::shared_ptr xrayConfigurator; - -signals: - void newVpnConfigCreated(const QString &clientId, const QString &clientName, const DockerContainer container, - ServerCredentials credentials); - void clientModelUpdated(); -}; - -#endif // VPN_CONFIGURATOR_H diff --git a/client/configurators/wireguard_configurator.cpp b/client/configurators/wireguard_configurator.cpp index 03c9a5b94..9dfd27f94 100644 --- a/client/configurators/wireguard_configurator.cpp +++ b/client/configurators/wireguard_configurator.cpp @@ -13,23 +13,22 @@ #include #include "containers/containers_defs.h" +#include "core/controllers/serverController.h" #include "core/scripts_registry.h" #include "core/server_defs.h" -#include "core/controllers/serverController.h" #include "settings.h" #include "utilities.h" WireguardConfigurator::WireguardConfigurator(std::shared_ptr settings, bool isAwg, QObject *parent) : ConfiguratorBase(settings, parent), m_isAwg(isAwg) { - m_serverConfigPath = m_isAwg ? amnezia::protocols::awg::serverConfigPath - : amnezia::protocols::wireguard::serverConfigPath; - m_serverPublicKeyPath = m_isAwg ? amnezia::protocols::awg::serverPublicKeyPath - : amnezia::protocols::wireguard::serverPublicKeyPath; - m_serverPskKeyPath = m_isAwg ? amnezia::protocols::awg::serverPskKeyPath - : amnezia::protocols::wireguard::serverPskKeyPath; - m_configTemplate = m_isAwg ? ProtocolScriptType::awg_template - : ProtocolScriptType::wireguard_template; + m_serverConfigPath = + m_isAwg ? amnezia::protocols::awg::serverConfigPath : amnezia::protocols::wireguard::serverConfigPath; + m_serverPublicKeyPath = + m_isAwg ? amnezia::protocols::awg::serverPublicKeyPath : amnezia::protocols::wireguard::serverPublicKeyPath; + m_serverPskKeyPath = + m_isAwg ? amnezia::protocols::awg::serverPskKeyPath : amnezia::protocols::wireguard::serverPskKeyPath; + m_configTemplate = m_isAwg ? ProtocolScriptType::awg_template : ProtocolScriptType::wireguard_template; m_protocolName = m_isAwg ? config_key::awg : config_key::wireguard; m_defaultPort = m_isAwg ? protocols::wireguard::defaultPort : protocols::awg::defaultPort; @@ -69,19 +68,17 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys() WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, - ErrorCode *errorCode) + ErrorCode errorCode) { WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys(); connData.host = credentials.hostName; connData.port = containerConfig.value(m_protocolName).toObject().value(config_key::port).toString(m_defaultPort); if (connData.clientPrivKey.isEmpty() || connData.clientPubKey.isEmpty()) { - if (errorCode) - *errorCode = ErrorCode::InternalError; + errorCode = ErrorCode::InternalError; return connData; } - ErrorCode e = ErrorCode::NoError; ServerController serverController(m_settings); // Get list of already created clients (only IP addresses) @@ -94,9 +91,8 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon return ErrorCode::NoError; }; - e = serverController.runContainerScript(credentials, container, script, cbReadStdOut); - if (errorCode && e) { - *errorCode = e; + errorCode = serverController.runContainerScript(credentials, container, script, cbReadStdOut); + if (errorCode != ErrorCode::NoError) { return connData; } @@ -110,8 +106,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon } else { int next = ips.last().split(".").last().toInt() + 1; if (next > 254) { - if (errorCode) - *errorCode = ErrorCode::AddressPoolError; + errorCode = ErrorCode::AddressPoolError; return connData; } nextIpNumber = QString::number(next); @@ -123,8 +118,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon { QStringList l = subnetIp.split(".", Qt::SkipEmptyParts); if (l.isEmpty()) { - if (errorCode) - *errorCode = ErrorCode::AddressPoolError; + errorCode = ErrorCode::AddressPoolError; return connData; } l.removeLast(); @@ -134,20 +128,17 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon } // Get keys - connData.serverPubKey = serverController.getTextFileFromContainer(container, credentials, m_serverPublicKeyPath, &e); + connData.serverPubKey = + serverController.getTextFileFromContainer(container, credentials, m_serverPublicKeyPath, errorCode); connData.serverPubKey.replace("\n", ""); - if (e) { - if (errorCode) - *errorCode = e; + if (errorCode != ErrorCode::NoError) { return connData; } - connData.pskKey = serverController.getTextFileFromContainer(container, credentials, m_serverPskKeyPath, &e); + connData.pskKey = serverController.getTextFileFromContainer(container, credentials, m_serverPskKeyPath, errorCode); connData.pskKey.replace("\n", ""); - if (e) { - if (errorCode) - *errorCode = e; + if (errorCode != ErrorCode::NoError) { return connData; } @@ -158,26 +149,24 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon "AllowedIPs = %3/32\n\n") .arg(connData.clientPubKey, connData.pskKey, connData.clientIP); - e = serverController.uploadTextFileToContainer(container, credentials, configPart, m_serverConfigPath, - libssh::ScpOverwriteMode::ScpAppendToExisting); + errorCode = serverController.uploadTextFileToContainer(container, credentials, configPart, m_serverConfigPath, + libssh::ScpOverwriteMode::ScpAppendToExisting); - if (e) { - if (errorCode) - *errorCode = e; + if (errorCode != ErrorCode::NoError) { return connData; } QString script = QString("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'") .arg(m_serverConfigPath); - e = serverController.runScript( + errorCode = serverController.runScript( credentials, serverController.replaceVars(script, serverController.genVarsForScript(credentials, container))); return connData; } -QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode) +QString WireguardConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode) { ServerController serverController(m_settings); QString scriptData = amnezia::scriptData(m_configTemplate, container); @@ -185,7 +174,7 @@ QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &crede scriptData, serverController.genVarsForScript(credentials, container, containerConfig)); ConnectionData connData = prepareWireguardConfig(credentials, container, containerConfig, errorCode); - if (errorCode && *errorCode) { + if (errorCode != ErrorCode::NoError) { return ""; } @@ -205,30 +194,25 @@ QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &crede jConfig[config_key::client_pub_key] = connData.clientPubKey; jConfig[config_key::psk_key] = connData.pskKey; jConfig[config_key::server_pub_key] = connData.serverPubKey; - jConfig[config_key::mtu] = wireguarConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu); - clientId = connData.clientPubKey; + jConfig[config_key::clientId] = connData.clientPubKey; return QJsonDocument(jConfig).toJson(); } -QString WireguardConfigurator::processConfigWithLocalSettings(QString config) +QString WireguardConfigurator::processConfigWithLocalSettings(const QPair &dns, + const bool isApiConfig, QString &protocolConfigString) { - // TODO replace DNS if it already set - config.replace("$PRIMARY_DNS", m_settings->primaryDns()); - config.replace("$SECONDARY_DNS", m_settings->secondaryDns()); + processConfigWithDnsSettings(dns, protocolConfigString); - QJsonObject jConfig; - jConfig[config_key::config] = config; - - return QJsonDocument(jConfig).toJson(); + return protocolConfigString; } -QString WireguardConfigurator::processConfigWithExportSettings(QString config) +QString WireguardConfigurator::processConfigWithExportSettings(const QPair &dns, + const bool isApiConfig, QString &protocolConfigString) { - config.replace("$PRIMARY_DNS", m_settings->primaryDns()); - config.replace("$SECONDARY_DNS", m_settings->secondaryDns()); + processConfigWithDnsSettings(dns, protocolConfigString); - return config; + return protocolConfigString; } diff --git a/client/configurators/wireguard_configurator.h b/client/configurators/wireguard_configurator.h index d24229816..0448a04ed 100644 --- a/client/configurators/wireguard_configurator.h +++ b/client/configurators/wireguard_configurator.h @@ -25,18 +25,20 @@ class WireguardConfigurator : public ConfiguratorBase QString port; }; - QString genWireguardConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode = nullptr); + QString createConfig(const ServerCredentials &credentials, DockerContainer container, + const QJsonObject &containerConfig, ErrorCode errorCode); - QString processConfigWithLocalSettings(QString config); - QString processConfigWithExportSettings(QString config); + QString processConfigWithLocalSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString); + QString processConfigWithExportSettings(const QPair &dns, const bool isApiConfig, + QString &protocolConfigString); static ConnectionData genClientKeys(); private: ConnectionData prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); - + const QJsonObject &containerConfig, ErrorCode errorCode); + bool m_isAwg; QString m_serverConfigPath; QString m_serverPublicKeyPath; diff --git a/client/configurators/xray_configurator.cpp b/client/configurators/xray_configurator.cpp index f450527fe..44a045615 100644 --- a/client/configurators/xray_configurator.cpp +++ b/client/configurators/xray_configurator.cpp @@ -1,43 +1,36 @@ #include "xray_configurator.h" #include -#include #include +#include -#include "core/scripts_registry.h" #include "containers/containers_defs.h" #include "core/controllers/serverController.h" +#include "core/scripts_registry.h" -XrayConfigurator::XrayConfigurator(std::shared_ptr settings, QObject *parent): - ConfiguratorBase(settings, parent) +XrayConfigurator::XrayConfigurator(std::shared_ptr settings, QObject *parent) : ConfiguratorBase(settings, parent) { - } -QString XrayConfigurator::genXrayConfig(const ServerCredentials &credentials, - DockerContainer container, const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode) +QString XrayConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, + ErrorCode errorCode) { - ErrorCode e = ErrorCode::NoError; ServerController serverController(m_settings); - QString config = - serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::xray_template, container), - serverController.genVarsForScript(credentials, container, containerConfig)); + QString config = serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::xray_template, container), + serverController.genVarsForScript(credentials, container, containerConfig)); - QString xrayPublicKey = serverController.getTextFileFromContainer(container, credentials, - amnezia::protocols::xray::PublicKeyPath, &e); + QString xrayPublicKey = + serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::xray::PublicKeyPath, errorCode); xrayPublicKey.replace("\n", ""); - QString xrayUuid = serverController.getTextFileFromContainer(container, credentials, - amnezia::protocols::xray::uuidPath, &e); + QString xrayUuid = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::xray::uuidPath, errorCode); xrayUuid.replace("\n", ""); - QString xrayShortId = serverController.getTextFileFromContainer(container, credentials, - amnezia::protocols::xray::shortidPath, &e); + QString xrayShortId = serverController.getTextFileFromContainer(container, credentials, amnezia::protocols::xray::shortidPath, errorCode); xrayShortId.replace("\n", ""); - if (e) { - if (errorCode) *errorCode = e; + if (errorCode != ErrorCode::NoError) { return ""; } diff --git a/client/configurators/xray_configurator.h b/client/configurators/xray_configurator.h index cefdc9c24..746a5762b 100644 --- a/client/configurators/xray_configurator.h +++ b/client/configurators/xray_configurator.h @@ -6,14 +6,14 @@ #include "configurator_base.h" #include "core/defs.h" -class XrayConfigurator : ConfiguratorBase +class XrayConfigurator : public ConfiguratorBase { Q_OBJECT public: XrayConfigurator(std::shared_ptr settings, QObject *parent = nullptr); - QString genXrayConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode = nullptr); + QString createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, + ErrorCode errorCode); }; #endif // XRAY_CONFIGURATOR_H diff --git a/client/containers/containers_defs.cpp b/client/containers/containers_defs.cpp index 2ed12d19f..0dcaa31a3 100644 --- a/client/containers/containers_defs.cpp +++ b/client/containers/containers_defs.cpp @@ -1,5 +1,8 @@ #include "containers_defs.h" +#include "QJsonObject" +#include "QJsonDocument" + QDebug operator<<(QDebug debug, const amnezia::DockerContainer &c) { QDebugStateSaver saver(debug); @@ -363,3 +366,13 @@ bool ContainerProps::isShareable(DockerContainer container) default: return true; } } + +QJsonObject ContainerProps::getProtocolConfigFromContainer(const Proto protocol, const QJsonObject &containerConfig) +{ + QString protocolConfigString = containerConfig.value(ProtocolProps::protoToString(protocol)) + .toObject() + .value(config_key::last_config) + .toString(); + + return QJsonDocument::fromJson(protocolConfigString.toUtf8()).object(); +} diff --git a/client/containers/containers_defs.h b/client/containers/containers_defs.h index fa10deb48..ac6e92016 100644 --- a/client/containers/containers_defs.h +++ b/client/containers/containers_defs.h @@ -68,6 +68,8 @@ namespace amnezia static int easySetupOrder(amnezia::DockerContainer container); static bool isShareable(amnezia::DockerContainer container); + + static QJsonObject getProtocolConfigFromContainer(const amnezia::Proto protocol, const QJsonObject &containerConfig); }; static void declareQmlContainerEnum() diff --git a/client/ui/controllers/apiController.cpp b/client/core/controllers/apiController.cpp similarity index 74% rename from client/ui/controllers/apiController.cpp rename to client/core/controllers/apiController.cpp index f9df5f4b6..4114c4683 100644 --- a/client/ui/controllers/apiController.cpp +++ b/client/core/controllers/apiController.cpp @@ -5,9 +5,8 @@ #include #include -#include "configurators/openvpn_configurator.h" -#include "configurators/wireguard_configurator.h" #include "core/errorstrings.h" +#include "configurators/wireguard_configurator.h" namespace { @@ -24,9 +23,7 @@ namespace } } -ApiController::ApiController(const QSharedPointer &serversModel, - const QSharedPointer &containersModel, QObject *parent) - : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel) +ApiController::ApiController(QObject *parent) : QObject(parent) { } @@ -67,21 +64,14 @@ QJsonObject ApiController::fillApiPayload(const QString &protocol, const ApiCont return obj; } -void ApiController::updateServerConfigFromApi() +ErrorCode ApiController::updateServerConfigFromApi(QJsonObject &serverConfig) { - QtConcurrent::run([this]() { - if (m_isConfigUpdateStarted) { - emit updateFinished(false); - return; - } + QFutureWatcher watcher; - auto serverConfig = m_serversModel->getDefaultServerConfig(); + QFuture future = QtConcurrent::run([this, &serverConfig]() { auto containerConfig = serverConfig.value(config_key::containers).toArray(); - if (serverConfig.value(config_key::configVersion).toInt() && containerConfig.isEmpty()) { - emit updateStarted(); - m_isConfigUpdateStarted = true; - + if (serverConfig.value(config_key::configVersion).toInt()) { QNetworkAccessManager manager; QNetworkRequest request; @@ -114,9 +104,7 @@ void ApiController::updateServerConfigFromApi() QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); if (ba.isEmpty()) { - emit errorOccurred(errorString(ApiConfigDownloadError)); - m_isConfigUpdateStarted = false; - return; + return ErrorCode::ApiConfigDownloadError; } QByteArray ba_uncompressed = qUncompress(ba); @@ -136,35 +124,22 @@ void ApiController::updateServerConfigFromApi() auto defaultContainer = apiConfig.value(config_key::defaultContainer).toString(); serverConfig.insert(config_key::defaultContainer, defaultContainer); - m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex()); } else { QString err = reply->errorString(); qDebug() << QString::fromUtf8(reply->readAll()); qDebug() << reply->error(); qDebug() << err; qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); - emit errorOccurred(errorString(ApiConfigDownloadError)); - m_isConfigUpdateStarted = false; - return; + return ErrorCode::ApiConfigDownloadError; } } - - emit updateFinished(m_isConfigUpdateStarted); - m_isConfigUpdateStarted = false; - return; + return ErrorCode::NoError; }); -} - -void ApiController::clearApiConfig() -{ - auto serverConfig = m_serversModel->getDefaultServerConfig(); - - serverConfig.remove(config_key::dns1); - serverConfig.remove(config_key::dns2); - serverConfig.remove(config_key::containers); - serverConfig.remove(config_key::hostName); - serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None)); + QEventLoop wait; + connect(&watcher, &QFutureWatcher::finished, &wait, &QEventLoop::quit); + watcher.setFuture(future); + wait.exec(); - m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex()); + return watcher.result(); } diff --git a/client/ui/controllers/apiController.h b/client/core/controllers/apiController.h similarity index 53% rename from client/ui/controllers/apiController.h rename to client/core/controllers/apiController.h index 2a1393c42..430572c56 100644 --- a/client/ui/controllers/apiController.h +++ b/client/core/controllers/apiController.h @@ -4,26 +4,16 @@ #include #include "configurators/openvpn_configurator.h" -#include "ui/models/containers_model.h" -#include "ui/models/servers_model.h" class ApiController : public QObject { Q_OBJECT public: - explicit ApiController(const QSharedPointer &serversModel, - const QSharedPointer &containersModel, QObject *parent = nullptr); + explicit ApiController(QObject *parent = nullptr); public slots: - void updateServerConfigFromApi(); - - void clearApiConfig(); - -signals: - void updateStarted(); - void updateFinished(bool isConfigUpdateStarted); - void errorOccurred(const QString &errorMessage); + ErrorCode updateServerConfigFromApi(QJsonObject &serverConfig); private: struct ApiPayloadData { @@ -36,11 +26,6 @@ public slots: ApiPayloadData generateApiPayloadData(const QString &protocol); QJsonObject fillApiPayload(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData); void processApiConfig(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData, QString &config); - - QSharedPointer m_serversModel; - QSharedPointer m_containersModel; - - bool m_isConfigUpdateStarted = false; }; #endif // APICONTROLLER_H diff --git a/client/core/controllers/serverController.cpp b/client/core/controllers/serverController.cpp index 88d8cbdc7..163c3d2b0 100644 --- a/client/core/controllers/serverController.cpp +++ b/client/core/controllers/serverController.cpp @@ -29,8 +29,7 @@ #include "core/networkUtilities.h" #include "settings.h" #include "utilities.h" - -#include +#include "vpnConfigurationController.h" namespace { @@ -179,11 +178,10 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, } QByteArray ServerController::getTextFileFromContainer(DockerContainer container, const ServerCredentials &credentials, - const QString &path, ErrorCode *errorCode) + const QString &path, ErrorCode errorCode) { - if (errorCode) - *errorCode = ErrorCode::NoError; + errorCode = ErrorCode::NoError; QString script = QString("sudo docker exec -i %1 sh -c \"xxd -p \'%2\'\"") .arg(ContainerProps::containerToString(container)) @@ -195,7 +193,7 @@ QByteArray ServerController::getTextFileFromContainer(DockerContainer container, return ErrorCode::NoError; }; - *errorCode = runScript(credentials, script, cbReadStdOut); + errorCode = runScript(credentials, script, cbReadStdOut); return QByteArray::fromHex(stdOut.toUtf8()); } @@ -498,7 +496,7 @@ ErrorCode ServerController::configureContainerWorker(const ServerCredentials &cr genVarsForScript(credentials, container, config)), cbReadStdOut, cbReadStdErr); - m_configurator->updateContainerConfigAfterInstallation(container, config, stdOut); + VpnConfigurationsController::updateContainerConfigAfterInstallation(container, config, stdOut); return e; } @@ -662,7 +660,7 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential return vars; } -QString ServerController::checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode) +QString ServerController::checkSshConnection(const ServerCredentials &credentials, ErrorCode errorCode) { QString stdOut; auto cbReadStdOut = [&](const QString &data, libssh::Client &) { @@ -674,11 +672,7 @@ QString ServerController::checkSshConnection(const ServerCredentials &credential return ErrorCode::NoError; }; - ErrorCode e = - runScript(credentials, amnezia::scriptData(SharedScriptType::check_connection), cbReadStdOut, cbReadStdErr); - - if (errorCode) - *errorCode = e; + errorCode = runScript(credentials, amnezia::scriptData(SharedScriptType::check_connection), cbReadStdOut, cbReadStdErr); return stdOut; } @@ -839,147 +833,6 @@ ErrorCode ServerController::isServerDpkgBusy(const ServerCredentials &credential return future.result(); } -ErrorCode ServerController::getAlreadyInstalledContainers(const ServerCredentials &credentials, - QMap &installedContainers) -{ - QString stdOut; - auto cbReadStdOut = [&](const QString &data, libssh::Client &) { - stdOut += data + "\n"; - return ErrorCode::NoError; - }; - auto cbReadStdErr = [&](const QString &data, libssh::Client &) { - stdOut += data + "\n"; - return ErrorCode::NoError; - }; - - QString script = QString("sudo docker ps --format '{{.Names}} {{.Ports}}'"); - - ErrorCode errorCode = runScript(credentials, script, cbReadStdOut, cbReadStdErr); - if (errorCode != ErrorCode::NoError) { - return errorCode; - } - - auto containersInfo = stdOut.split("\n"); - for (auto &containerInfo : containersInfo) { - if (containerInfo.isEmpty()) { - continue; - } - const static QRegularExpression containerAndPortRegExp("(amnezia[-a-z]*).*?:([0-9]*)->[0-9]*/(udp|tcp).*"); - QRegularExpressionMatch containerAndPortMatch = containerAndPortRegExp.match(containerInfo); - if (containerAndPortMatch.hasMatch()) { - QString name = containerAndPortMatch.captured(1); - QString port = containerAndPortMatch.captured(2); - QString transportProto = containerAndPortMatch.captured(3); - DockerContainer container = ContainerProps::containerFromString(name); - - QJsonObject config; - Proto mainProto = ContainerProps::defaultProtocol(container); - for (auto protocol : ContainerProps::protocolsForContainer(container)) { - QJsonObject containerConfig; - if (protocol == mainProto) { - containerConfig.insert(config_key::port, port); - containerConfig.insert(config_key::transport_proto, transportProto); - - if (protocol == Proto::Awg) { - QString serverConfig = getTextFileFromContainer(container, credentials, protocols::awg::serverConfigPath, &errorCode); - - QMap serverConfigMap; - auto serverConfigLines = serverConfig.split("\n"); - for (auto &line : serverConfigLines) { - auto trimmedLine = line.trimmed(); - if (trimmedLine.startsWith("[") && trimmedLine.endsWith("]")) { - continue; - } else { - QStringList parts = trimmedLine.split(" = "); - if (parts.count() == 2) { - serverConfigMap.insert(parts[0].trimmed(), parts[1].trimmed()); - } - } - } - - containerConfig[config_key::junkPacketCount] = serverConfigMap.value(config_key::junkPacketCount); - containerConfig[config_key::junkPacketMinSize] = serverConfigMap.value(config_key::junkPacketMinSize); - containerConfig[config_key::junkPacketMaxSize] = serverConfigMap.value(config_key::junkPacketMaxSize); - containerConfig[config_key::initPacketJunkSize] = serverConfigMap.value(config_key::initPacketJunkSize); - containerConfig[config_key::responsePacketJunkSize] = serverConfigMap.value(config_key::responsePacketJunkSize); - containerConfig[config_key::initPacketMagicHeader] = serverConfigMap.value(config_key::initPacketMagicHeader); - containerConfig[config_key::responsePacketMagicHeader] = serverConfigMap.value(config_key::responsePacketMagicHeader); - containerConfig[config_key::underloadPacketMagicHeader] = serverConfigMap.value(config_key::underloadPacketMagicHeader); - containerConfig[config_key::transportPacketMagicHeader] = serverConfigMap.value(config_key::transportPacketMagicHeader); - } else if (protocol == Proto::Sftp) { - stdOut.clear(); - script = QString("sudo docker inspect --format '{{.Config.Cmd}}' %1").arg(name); - - ErrorCode errorCode = runScript(credentials, script, cbReadStdOut, cbReadStdErr); - if (errorCode != ErrorCode::NoError) { - return errorCode; - } - - auto sftpInfo = stdOut.split(":"); - if (sftpInfo.size() < 2) { - logger.error() << "Key parameters for the sftp container are missing"; - continue; - } - auto userName = sftpInfo.at(0); - userName = userName.remove(0, 1); - auto password = sftpInfo.at(1); - - containerConfig.insert(config_key::userName, userName); - containerConfig.insert(config_key::password, password); - } - - config.insert(config_key::container, ContainerProps::containerToString(container)); - } - config.insert(ProtocolProps::protoToString(protocol), containerConfig); - } - installedContainers.insert(container, config); - } - const static QRegularExpression torOrDnsRegExp("(amnezia-(?:torwebsite|dns)).*?([0-9]*)/(udp|tcp).*"); - QRegularExpressionMatch torOrDnsRegMatch = torOrDnsRegExp.match(containerInfo); - if (torOrDnsRegMatch.hasMatch()) { - QString name = torOrDnsRegMatch.captured(1); - QString port = torOrDnsRegMatch.captured(2); - QString transportProto = torOrDnsRegMatch.captured(3); - DockerContainer container = ContainerProps::containerFromString(name); - - QJsonObject config; - Proto mainProto = ContainerProps::defaultProtocol(container); - for (auto protocol : ContainerProps::protocolsForContainer(container)) { - QJsonObject containerConfig; - if (protocol == mainProto) { - containerConfig.insert(config_key::port, port); - containerConfig.insert(config_key::transport_proto, transportProto); - - if (protocol == Proto::TorWebSite) { - stdOut.clear(); - script = QString("sudo docker exec -i %1 sh -c 'cat /var/lib/tor/hidden_service/hostname'").arg(name); - - ErrorCode errorCode = runScript(credentials, script, cbReadStdOut, cbReadStdErr); - if (errorCode != ErrorCode::NoError) { - return errorCode; - } - - if (stdOut.isEmpty()) { - logger.error() << "Key parameters for the tor container are missing"; - continue; - } - - QString onion = stdOut; - onion.replace("\n", ""); - containerConfig.insert(config_key::site, onion); - } - - config.insert(config_key::container, ContainerProps::containerToString(container)); - } - config.insert(ProtocolProps::protoToString(protocol), containerConfig); - } - installedContainers.insert(container, config); - } - } - - return ErrorCode::NoError; -} - ErrorCode ServerController::getDecryptedPrivateKey(const ServerCredentials &credentials, QString &decryptedPrivateKey, const std::function &callback) { diff --git a/client/core/controllers/serverController.h b/client/core/controllers/serverController.h index 7caad3667..3df3bdca5 100644 --- a/client/core/controllers/serverController.h +++ b/client/core/controllers/serverController.h @@ -30,9 +30,6 @@ class ServerController : public QObject ErrorCode updateContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &oldConfig, QJsonObject &newConfig); - ErrorCode getAlreadyInstalledContainers(const ServerCredentials &credentials, - QMap &installedContainers); - ErrorCode startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject()); @@ -40,7 +37,7 @@ class ServerController : public QObject DockerContainer container, const ServerCredentials &credentials, const QString &file, const QString &path, libssh::ScpOverwriteMode overwriteMode = libssh::ScpOverwriteMode::ScpOverwriteExisting); QByteArray getTextFileFromContainer(DockerContainer container, const ServerCredentials &credentials, - const QString &path, ErrorCode *errorCode = nullptr); + const QString &path, ErrorCode errorCode); QString replaceVars(const QString &script, const Vars &vars); Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, @@ -55,7 +52,7 @@ class ServerController : public QObject const std::function &cbReadStdOut = nullptr, const std::function &cbReadStdErr = nullptr); - QString checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr); + QString checkSshConnection(const ServerCredentials &credentials, ErrorCode errorCode); void cancelInstallation(); diff --git a/client/core/controllers/vpnConfigurationController.cpp b/client/core/controllers/vpnConfigurationController.cpp new file mode 100644 index 000000000..ba2106694 --- /dev/null +++ b/client/core/controllers/vpnConfigurationController.cpp @@ -0,0 +1,137 @@ +#include "vpnConfigurationController.h" + +#include "configurators/awg_configurator.h" +#include "configurators/cloak_configurator.h" +#include "configurators/ikev2_configurator.h" +#include "configurators/openvpn_configurator.h" +#include "configurators/shadowsocks_configurator.h" +#include "configurators/wireguard_configurator.h" +#include "configurators/xray_configurator.h" + +VpnConfigurationsController::VpnConfigurationsController(const std::shared_ptr &settings, QObject *parent) + : QObject { parent }, m_settings(settings) +{ +} + +QScopedPointer VpnConfigurationsController::createConfigurator(const Proto protocol) +{ + switch (protocol) { + case Proto::OpenVpn: return QScopedPointer(new OpenVpnConfigurator(m_settings)); + case Proto::ShadowSocks: return QScopedPointer(new ShadowSocksConfigurator(m_settings)); + case Proto::Cloak: return QScopedPointer(new CloakConfigurator(m_settings)); + case Proto::WireGuard: return QScopedPointer(new WireguardConfigurator(m_settings, false)); + case Proto::Awg: return QScopedPointer(new AwgConfigurator(m_settings)); + case Proto::Ikev2: return QScopedPointer(new Ikev2Configurator(m_settings)); + case Proto::Xray: return QScopedPointer(new XrayConfigurator(m_settings)); + default: return QScopedPointer(); + } +} + +ErrorCode VpnConfigurationsController::createProtocolConfigForContainer(const ServerCredentials &credentials, + const DockerContainer container, QJsonObject &containerConfig) +{ + ErrorCode errorCode = ErrorCode::NoError; + + if (ContainerProps::containerService(container) == ServiceType::Other) { + return errorCode; + } + + for (Proto protocol : ContainerProps::protocolsForContainer(container)) { + QJsonObject protocolConfig = containerConfig.value(ProtocolProps::protoToString(protocol)).toObject(); + + auto configurator = createConfigurator(protocol); + QString protocolConfigString = configurator->createConfig(credentials, container, containerConfig, errorCode); + if (errorCode != ErrorCode::NoError) { + return errorCode; + } + + protocolConfig.insert(config_key::last_config, protocolConfigString); + containerConfig.insert(ProtocolProps::protoToString(protocol), protocolConfig); + } + + return errorCode; +} + +ErrorCode VpnConfigurationsController::createProtocolConfigString(const bool isApiConfig, const QPair &dns, + const ServerCredentials &credentials, const DockerContainer container, + const QJsonObject &containerConfig, const Proto protocol, + QString &protocolConfigString) +{ + ErrorCode errorCode = ErrorCode::NoError; + + if (ContainerProps::containerService(container) == ServiceType::Other) { + return errorCode; + } + + auto configurator = createConfigurator(protocol); + + protocolConfigString = configurator->createConfig(credentials, container, containerConfig, errorCode); + if (errorCode != ErrorCode::NoError) { + return errorCode; + } + protocolConfigString = configurator->processConfigWithExportSettings(dns, isApiConfig, protocolConfigString); + + return errorCode; +} + +QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair &dns, const QJsonObject &serverConfig, + const QJsonObject &containerConfig, const DockerContainer container, + ErrorCode errorCode) +{ + QJsonObject vpnConfiguration {}; + + if (ContainerProps::containerService(container) == ServiceType::Other) { + return vpnConfiguration; + } + + bool isApiConfig = serverConfig.value(config_key::configVersion).toInt(); + + for (ProtocolEnumNS::Proto proto : ContainerProps::protocolsForContainer(container)) { + if (isApiConfig && container == DockerContainer::Cloak && proto == ProtocolEnumNS::Proto::ShadowSocks) { + continue; + } + + QString protocolConfigString = + containerConfig.value(ProtocolProps::protoToString(proto)).toObject().value(config_key::last_config).toString(); + + auto configurator = createConfigurator(proto); + protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString); + + QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object(); + vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object(); + vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData); + } + + Proto proto = ContainerProps::defaultProtocol(container); + vpnConfiguration[config_key::vpnproto] = ProtocolProps::protoToString(proto); + + vpnConfiguration[config_key::dns1] = dns.first; + vpnConfiguration[config_key::dns2] = dns.second; + + vpnConfiguration[config_key::hostName] = serverConfig.value(config_key::hostName).toString(); + vpnConfiguration[config_key::description] = serverConfig.value(config_key::description).toString(); + + vpnConfiguration[config_key::configVersion] = serverConfig.value(config_key::configVersion).toInt(); + // TODO: try to get hostName, port, description for 3rd party configs + // vpnConfiguration[config_key::port] = ...; + + return vpnConfiguration; +} + +void VpnConfigurationsController::updateContainerConfigAfterInstallation(const DockerContainer container, QJsonObject &containerConfig, + const QString &stdOut) +{ + Proto mainProto = ContainerProps::defaultProtocol(container); + + if (container == DockerContainer::TorWebSite) { + QJsonObject protocol = containerConfig.value(ProtocolProps::protoToString(mainProto)).toObject(); + + qDebug() << "amnezia-tor onions" << stdOut; + + QString onion = stdOut; + onion.replace("\n", ""); + protocol.insert(config_key::site, onion); + + containerConfig.insert(ProtocolProps::protoToString(mainProto), protocol); + } +} diff --git a/client/core/controllers/vpnConfigurationController.h b/client/core/controllers/vpnConfigurationController.h new file mode 100644 index 000000000..ac0b0ac5e --- /dev/null +++ b/client/core/controllers/vpnConfigurationController.h @@ -0,0 +1,35 @@ +#ifndef VPNCONFIGIRATIONSCONTROLLER_H +#define VPNCONFIGIRATIONSCONTROLLER_H + +#include + +#include "configurators/configurator_base.h" +#include "containers/containers_defs.h" +#include "core/defs.h" +#include "settings.h" + +class VpnConfigurationsController : public QObject +{ + Q_OBJECT +public: + explicit VpnConfigurationsController(const std::shared_ptr &settings, QObject *parent = nullptr); + +public slots: + ErrorCode createProtocolConfigForContainer(const ServerCredentials &credentials, const DockerContainer container, + QJsonObject &containerConfig); + ErrorCode createProtocolConfigString(const bool isApiConfig, const QPair &dns, const ServerCredentials &credentials, + const DockerContainer container, const QJsonObject &containerConfig, const Proto protocol, + QString &protocolConfigString); + QJsonObject createVpnConfiguration(const QPair &dns, const QJsonObject &serverConfig, + const QJsonObject &containerConfig, const DockerContainer container, ErrorCode errorCode); + + static void updateContainerConfigAfterInstallation(const DockerContainer container, QJsonObject &containerConfig, const QString &stdOut); +signals: + +private: + QScopedPointer createConfigurator(const Proto protocol); + + std::shared_ptr m_settings; +}; + +#endif // VPNCONFIGIRATIONSCONTROLLER_H diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 8cf7cfd2c..feee11f3c 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -94,6 +94,8 @@ namespace amnezia constexpr char crc[] = "crc"; + constexpr char clientId[] = "clientId"; + } namespace protocols diff --git a/client/ui/controllers/connectionController.cpp b/client/ui/controllers/connectionController.cpp index 43f23f349..d2189101d 100644 --- a/client/ui/controllers/connectionController.cpp +++ b/client/ui/controllers/connectionController.cpp @@ -5,13 +5,23 @@ #else #include #endif +#include +#include "core/controllers/apiController.h" +#include "core/controllers/vpnConfigurationController.h" #include "core/errorstrings.h" ConnectionController::ConnectionController(const QSharedPointer &serversModel, const QSharedPointer &containersModel, - const QSharedPointer &vpnConnection, QObject *parent) - : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel), m_vpnConnection(vpnConnection) + const QSharedPointer &clientManagementModel, + const QSharedPointer &vpnConnection, + const std::shared_ptr &settings, QObject *parent) + : QObject(parent), + m_serversModel(serversModel), + m_containersModel(containersModel), + m_clientManagementModel(clientManagementModel), + m_vpnConnection(vpnConnection), + m_settings(settings) { connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, this, &ConnectionController::onConnectionStateChanged); @@ -26,16 +36,31 @@ ConnectionController::ConnectionController(const QSharedPointer &s void ConnectionController::openConnection() { int serverIndex = m_serversModel->getDefaultServerIndex(); + auto serverConfig = m_serversModel->getServerConfig(serverIndex); + + ErrorCode errorCode = ErrorCode::NoError; + + emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Preparing); + + if (serverConfig.value(config_key::configVersion).toInt() + && !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) { + ApiController apiController; + errorCode = apiController.updateServerConfigFromApi(serverConfig); + if (errorCode != ErrorCode::NoError) { + emit connectionErrorOccurred(errorString(errorCode)); + return; + } + m_serversModel->editServer(serverConfig, serverIndex); + } if (!m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) { emit noInstalledContainers(); + emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); return; } - ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); - - DockerContainer container = qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole)); - const QJsonObject &containerConfig = m_containersModel->getContainerConfig(container); + DockerContainer container = + qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole)); if (container == DockerContainer::None) { emit connectionErrorOccurred(tr("VPN Protocols is not installed.\n Please install VPN container at first")); @@ -44,7 +69,27 @@ void ConnectionController::openConnection() qApp->processEvents(); - emit connectToVpn(serverIndex, credentials, container, containerConfig); + VpnConfigurationsController vpnConfigurationController(m_settings); + + QJsonObject containerConfig = m_containersModel->getContainerConfig(container); + ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); + errorCode = updateProtocolConfig(container, credentials, containerConfig); + if (errorCode != ErrorCode::NoError) { + emit connectionErrorOccurred(errorString(errorCode)); + return; + } + + auto dns = m_serversModel->getDnsPair(serverIndex); + serverConfig = m_serversModel->getServerConfig(serverIndex); + + auto vpnConfiguration = + vpnConfigurationController.createVpnConfiguration(dns, serverConfig, containerConfig, container, errorCode); + if (errorCode != ErrorCode::NoError) { + emit connectionErrorOccurred(tr("unable to create configuration")); + return; + } + + emit connectToVpn(serverIndex, credentials, container, vpnConfiguration); } void ConnectionController::closeConnection() @@ -91,6 +136,7 @@ void ConnectionController::onConnectionStateChanged(Vpn::ConnectionState state) } case Vpn::ConnectionState::Preparing: { m_isConnectionInProgress = true; + m_connectionStateText = tr("Preparing..."); break; } case Vpn::ConnectionState::Error: { @@ -135,9 +181,14 @@ QString ConnectionController::connectionStateText() const return m_connectionStateText; } -void ConnectionController::toggleConnection(bool skipConnectionInProgressCheck) +void ConnectionController::toggleConnection() { - if (!skipConnectionInProgressCheck && isConnectionInProgress()) { + if (m_state == Vpn::ConnectionState::Preparing) { + emit preparingConfig(); + return; + } + + if (isConnectionInProgress()) { closeConnection(); } else if (isConnected()) { closeConnection(); @@ -155,3 +206,51 @@ bool ConnectionController::isConnected() const { return m_isConnected; } + +bool ConnectionController::isProtocolConfigExists(const QJsonObject &containerConfig, const DockerContainer container) +{ + for (Proto protocol : ContainerProps::protocolsForContainer(container)) { + QString protocolConfig = containerConfig.value(ProtocolProps::protoToString(protocol)) + .toObject() + .value(config_key::last_config) + .toString(); + + if (protocolConfig.isEmpty()) { + return false; + } + } + return true; +} + +ErrorCode ConnectionController::updateProtocolConfig(const DockerContainer container, + const ServerCredentials &credentials, QJsonObject &containerConfig) +{ + QFutureWatcher watcher; + + QFuture future = QtConcurrent::run([this, container, &credentials, &containerConfig]() { + ErrorCode errorCode = ErrorCode::NoError; + if (!isProtocolConfigExists(containerConfig, container)) { + VpnConfigurationsController vpnConfigurationController(m_settings); + errorCode = + vpnConfigurationController.createProtocolConfigForContainer(credentials, container, containerConfig); + if (errorCode != ErrorCode::NoError) { + return errorCode; + } + m_serversModel->updateContainerConfig(container, containerConfig); + + errorCode = m_clientManagementModel->appendClient(container, credentials, containerConfig, + QString("Admin [%1]").arg(QSysInfo::prettyProductName())); + if (errorCode != ErrorCode::NoError) { + return errorCode; + } + } + return errorCode; + }); + + QEventLoop wait; + connect(&watcher, &QFutureWatcher::finished, &wait, &QEventLoop::quit); + watcher.setFuture(future); + wait.exec(); + + return watcher.result(); +} diff --git a/client/ui/controllers/connectionController.h b/client/ui/controllers/connectionController.h index 9972a1185..b139dddbe 100644 --- a/client/ui/controllers/connectionController.h +++ b/client/ui/controllers/connectionController.h @@ -2,6 +2,7 @@ #define CONNECTIONCONTROLLER_H #include "protocols/vpnprotocol.h" +#include "ui/models/clientManagementModel.h" #include "ui/models/containers_model.h" #include "ui/models/servers_model.h" #include "vpnconnection.h" @@ -17,7 +18,9 @@ class ConnectionController : public QObject explicit ConnectionController(const QSharedPointer &serversModel, const QSharedPointer &containersModel, - const QSharedPointer &vpnConnection, QObject *parent = nullptr); + const QSharedPointer &clientManagementModel, + const QSharedPointer &vpnConnection, + const std::shared_ptr &settings, QObject *parent = nullptr); ~ConnectionController() = default; @@ -26,7 +29,7 @@ class ConnectionController : public QObject QString connectionStateText() const; public slots: - void toggleConnection(bool skipConnectionInProgressCheck); + void toggleConnection(); void openConnection(); void closeConnection(); @@ -38,9 +41,12 @@ public slots: void onTranslationsUpdated(); + ErrorCode updateProtocolConfig(const DockerContainer container, const ServerCredentials &credentials, + QJsonObject &containerConfig); + signals: void connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig); + const QJsonObject &vpnConfiguration); void disconnectFromVpn(); void connectionStateChanged(); @@ -49,14 +55,21 @@ public slots: void noInstalledContainers(); + void connectButtonClicked(); + void preparingConfig(); + private: Vpn::ConnectionState getCurrentConnectionState(); + bool isProtocolConfigExists(const QJsonObject &containerConfig, const DockerContainer container); QSharedPointer m_serversModel; QSharedPointer m_containersModel; + QSharedPointer m_clientManagementModel; QSharedPointer m_vpnConnection; + std::shared_ptr m_settings; + bool m_isConnected = false; bool m_isConnectionInProgress = false; QString m_connectionStateText = tr("Connect"); diff --git a/client/ui/controllers/exportController.cpp b/client/ui/controllers/exportController.cpp index c60627fed..9d68dfce6 100644 --- a/client/ui/controllers/exportController.cpp +++ b/client/ui/controllers/exportController.cpp @@ -8,11 +8,7 @@ #include #include -#include "configurators/awg_configurator.h" -#include "configurators/cloak_configurator.h" -#include "configurators/openvpn_configurator.h" -#include "configurators/shadowsocks_configurator.h" -#include "configurators/wireguard_configurator.h" +#include "core/controllers/vpnConfigurationController.h" #include "core/errorstrings.h" #include "systemController.h" #ifdef Q_OS_ANDROID @@ -20,25 +16,20 @@ #endif #include "qrcodegen.hpp" -ExportController::ExportController(const QSharedPointer &serversModel, - const QSharedPointer &containersModel, +ExportController::ExportController(const QSharedPointer &serversModel, const QSharedPointer &containersModel, const QSharedPointer &clientManagementModel, - const std::shared_ptr &settings, - const std::shared_ptr &configurator, QObject *parent) + const std::shared_ptr &settings, QObject *parent) : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel), m_clientManagementModel(clientManagementModel), - m_settings(settings), - m_configurator(configurator) + m_settings(settings) { #ifdef Q_OS_ANDROID m_authResultNotifier.reset(new AuthResultNotifier); m_authResultReceiver.reset(new AuthResultReceiver(m_authResultNotifier)); - connect(m_authResultNotifier.get(), &AuthResultNotifier::authFailed, this, - [this]() { emit exportErrorOccurred(tr("Access error!")); }); - connect(m_authResultNotifier.get(), &AuthResultNotifier::authSuccessful, this, - &ExportController::generateFullAccessConfig); + connect(m_authResultNotifier.get(), &AuthResultNotifier::authFailed, this, [this]() { emit exportErrorOccurred(tr("Access error!")); }); + connect(m_authResultNotifier.get(), &AuthResultNotifier::authSuccessful, this, &ExportController::generateFullAccessConfig); #endif } @@ -47,9 +38,9 @@ void ExportController::generateFullAccessConfig() clearPreviousConfig(); int serverIndex = m_serversModel->getProcessedServerIndex(); - QJsonObject config = m_settings->server(serverIndex); + QJsonObject serverConfig = m_serversModel->getServerConfig(serverIndex); - QJsonArray containers = config.value(config_key::containers).toArray(); + QJsonArray containers = serverConfig.value(config_key::containers).toArray(); for (auto i = 0; i < containers.size(); i++) { auto containerConfig = containers.at(i).toObject(); auto containerType = ContainerProps::containerFromString(containerConfig.value(config_key::container).toString()); @@ -63,13 +54,11 @@ void ExportController::generateFullAccessConfig() containers.replace(i, containerConfig); } - config[config_key::containers] = containers; + serverConfig[config_key::containers] = containers; - QByteArray compressedConfig = QJsonDocument(config).toJson(); + QByteArray compressedConfig = QJsonDocument(serverConfig).toJson(); compressedConfig = qCompress(compressedConfig, 8); - m_config = QString("vpn://%1") - .arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding - | QByteArray::OmitTrailingEquals))); + m_config = QString("vpn://%1").arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals))); m_qrCodes = generateQrCodeImageSeries(compressedConfig); emit exportConfigChanged(); @@ -83,8 +72,7 @@ void ExportController::generateFullAccessConfigAndroid() auto appContext = activity.callObjectMethod("getApplicationContext", "()Landroid/content/Context;"); if (appContext.isValid()) { auto intent = QJniObject::callStaticObjectMethod("org/amnezia/vpn/AuthHelper", "getAuthIntent", - "(Landroid/content/Context;)Landroid/content/Intent;", - appContext.object()); + "(Landroid/content/Context;)Landroid/content/Intent;", appContext.object()); if (intent.isValid()) { if (intent.object() != nullptr) { QtAndroidPrivate::startActivity(intent.object(), 1, m_authResultReceiver.get()); @@ -103,116 +91,108 @@ void ExportController::generateConnectionConfig(const QString &clientName) int serverIndex = m_serversModel->getProcessedServerIndex(); ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); - DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); + DockerContainer container = static_cast(m_containersModel->getProcessedContainerIndex()); QJsonObject containerConfig = m_containersModel->getContainerConfig(container); containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); - ErrorCode errorCode = ErrorCode::NoError; - for (Proto protocol : ContainerProps::protocolsForContainer(container)) { - QJsonObject protocolConfig = m_settings->protocolConfig(serverIndex, container, protocol); - - QString clientId; - QString vpnConfig = m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, protocol, - clientId, &errorCode); - if (errorCode) { - emit exportErrorOccurred(errorString(errorCode)); - return; - } - protocolConfig.insert(config_key::last_config, vpnConfig); - containerConfig.insert(ProtocolProps::protoToString(protocol), protocolConfig); - if (protocol == Proto::OpenVpn || protocol == Proto::Awg || protocol == Proto::WireGuard) { - errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials); - if (errorCode) { - emit exportErrorOccurred(errorString(errorCode)); - return; - } - } + VpnConfigurationsController vpnConfigurationController(m_settings); + ErrorCode errorCode = vpnConfigurationController.createProtocolConfigForContainer(credentials, container, containerConfig); + + errorCode = m_clientManagementModel->appendClient(container, credentials, containerConfig, clientName); + if (errorCode != ErrorCode::NoError) { + emit exportErrorOccurred(errorString(errorCode)); + return; } - QJsonObject config = m_settings->server(serverIndex); // todo change to servers_model + QJsonObject serverConfig = m_serversModel->getServerConfig(serverIndex); if (!errorCode) { - config.remove(config_key::userName); - config.remove(config_key::password); - config.remove(config_key::port); - config.insert(config_key::containers, QJsonArray { containerConfig }); - config.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); - - auto dns = m_configurator->getDnsForConfig(serverIndex); - config.insert(config_key::dns1, dns.first); - config.insert(config_key::dns2, dns.second); + serverConfig.remove(config_key::userName); + serverConfig.remove(config_key::password); + serverConfig.remove(config_key::port); + serverConfig.insert(config_key::containers, QJsonArray { containerConfig }); + serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); + + auto dns = m_serversModel->getDnsPair(serverIndex); + serverConfig.insert(config_key::dns1, dns.first); + serverConfig.insert(config_key::dns2, dns.second); } - QByteArray compressedConfig = QJsonDocument(config).toJson(); + QByteArray compressedConfig = QJsonDocument(serverConfig).toJson(); compressedConfig = qCompress(compressedConfig, 8); - m_config = QString("vpn://%1") - .arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding - | QByteArray::OmitTrailingEquals))); + m_config = QString("vpn://%1").arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals))); m_qrCodes = generateQrCodeImageSeries(compressedConfig); emit exportConfigChanged(); } -void ExportController::generateOpenVpnConfig(const QString &clientName) +ErrorCode ExportController::generateNativeConfig(const DockerContainer container, const QString &clientName, const Proto &protocol, + QJsonObject &jsonNativeConfig) { clearPreviousConfig(); int serverIndex = m_serversModel->getProcessedServerIndex(); ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); + auto dns = m_serversModel->getDnsPair(serverIndex); + bool isApiConfig = qvariant_cast(m_serversModel->data(serverIndex, ServersModel::IsServerFromApiRole)); - DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); QJsonObject containerConfig = m_containersModel->getContainerConfig(container); containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); + VpnConfigurationsController vpnConfigurationController(m_settings); + + QString protocolConfigString; + + ErrorCode errorCode = vpnConfigurationController.createProtocolConfigString(isApiConfig, dns, credentials, container, containerConfig, + protocol, protocolConfigString); + if (errorCode != ErrorCode::NoError) { + return errorCode; + } + + jsonNativeConfig = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object(); + + if (protocol == Proto::OpenVpn || protocol == Proto::WireGuard || protocol == Proto::Awg) { + auto clientId = jsonNativeConfig.value(config_key::clientId).toString(); + errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials); + } + return errorCode; +} + +void ExportController::generateOpenVpnConfig(const QString &clientName) +{ + QJsonObject nativeConfig; + DockerContainer container = static_cast(m_containersModel->getProcessedContainerIndex()); ErrorCode errorCode = ErrorCode::NoError; - QString clientId; - QString config = m_configurator->openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, - clientId, &errorCode); + + if (container == DockerContainer::Cloak || container == DockerContainer::ShadowSocks) { + errorCode = generateNativeConfig(container, clientName, Proto::OpenVpn, nativeConfig); + } else { + errorCode = generateNativeConfig(container, clientName, ContainerProps::defaultProtocol(container), nativeConfig); + } + if (errorCode) { emit exportErrorOccurred(errorString(errorCode)); return; } - config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::OpenVpn, config); - auto configJson = QJsonDocument::fromJson(config.toUtf8()).object(); - QStringList lines = configJson.value(config_key::config).toString().replace("\r", "").split("\n"); + QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n"); for (const QString &line : lines) { m_config.append(line + "\n"); } m_qrCodes = generateQrCodeImageSeries(m_config.toUtf8()); - - errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials); - if (errorCode) { - emit exportErrorOccurred(errorString(errorCode)); - return; - } - emit exportConfigChanged(); } void ExportController::generateWireGuardConfig(const QString &clientName) { - clearPreviousConfig(); - - int serverIndex = m_serversModel->getProcessedServerIndex(); - ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); - - DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); - QJsonObject containerConfig = m_containersModel->getContainerConfig(container); - containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); - - QString clientId; - ErrorCode errorCode = ErrorCode::NoError; - QString config = m_configurator->wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, - clientId, &errorCode); + QJsonObject nativeConfig; + ErrorCode errorCode = generateNativeConfig(DockerContainer::WireGuard, clientName, Proto::WireGuard, nativeConfig); if (errorCode) { emit exportErrorOccurred(errorString(errorCode)); return; } - config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::WireGuard, config); - auto configJson = QJsonDocument::fromJson(config.toUtf8()).object(); - QStringList lines = configJson.value(config_key::config).toString().replace("\r", "").split("\n"); + QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n"); for (const QString &line : lines) { m_config.append(line + "\n"); } @@ -220,38 +200,19 @@ void ExportController::generateWireGuardConfig(const QString &clientName) qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(m_config.toUtf8(), qrcodegen::QrCode::Ecc::LOW); m_qrCodes << svgToBase64(QString::fromStdString(toSvgString(qr, 1))); - errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials); - if (errorCode) { - emit exportErrorOccurred(errorString(errorCode)); - return; - } - emit exportConfigChanged(); } void ExportController::generateAwgConfig(const QString &clientName) { - clearPreviousConfig(); - - int serverIndex = m_serversModel->getProcessedServerIndex(); - ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); - - DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); - QJsonObject containerConfig = m_containersModel->getContainerConfig(container); - containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); - - QString clientId; - ErrorCode errorCode = ErrorCode::NoError; - QString config = m_configurator->awgConfigurator->genAwgConfig(credentials, container, containerConfig, - clientId, &errorCode); + QJsonObject nativeConfig; + ErrorCode errorCode = generateNativeConfig(DockerContainer::Awg, clientName, Proto::Awg, nativeConfig); if (errorCode) { emit exportErrorOccurred(errorString(errorCode)); return; } - config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::Awg, config); - auto configJson = QJsonDocument::fromJson(config.toUtf8()).object(); - QStringList lines = configJson.value(config_key::config).toString().replace("\r", "").split("\n"); + QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n"); for (const QString &line : lines) { m_config.append(line + "\n"); } @@ -259,42 +220,34 @@ void ExportController::generateAwgConfig(const QString &clientName) qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(m_config.toUtf8(), qrcodegen::QrCode::Ecc::LOW); m_qrCodes << svgToBase64(QString::fromStdString(toSvgString(qr, 1))); - errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials); - if (errorCode) { - emit exportErrorOccurred(errorString(errorCode)); - return; - } - emit exportConfigChanged(); } void ExportController::generateShadowSocksConfig() { - clearPreviousConfig(); - - int serverIndex = m_serversModel->getProcessedServerIndex(); - ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); - - DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); - QJsonObject containerConfig = m_containersModel->getContainerConfig(container); - containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); - + QJsonObject nativeConfig; + DockerContainer container = static_cast(m_containersModel->getProcessedContainerIndex()); ErrorCode errorCode = ErrorCode::NoError; - QString config = m_configurator->shadowSocksConfigurator->genShadowSocksConfig(credentials, container, - containerConfig, &errorCode); - config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::ShadowSocks, config); - QJsonObject configJson = QJsonDocument::fromJson(config.toUtf8()).object(); + if (container == DockerContainer::Cloak) { + errorCode = generateNativeConfig(container, "", Proto::ShadowSocks, nativeConfig); + } else { + errorCode = generateNativeConfig(container, "", ContainerProps::defaultProtocol(container), nativeConfig); + } + + if (errorCode) { + emit exportErrorOccurred(errorString(errorCode)); + return; + } - QStringList lines = QString(QJsonDocument(configJson).toJson()).replace("\r", "").split("\n"); + QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n"); for (const QString &line : lines) { m_config.append(line + "\n"); } - m_nativeConfigString = - QString("%1:%2@%3:%4") - .arg(configJson.value("method").toString(), configJson.value("password").toString(), - configJson.value("server").toString(), configJson.value("server_port").toString()); + m_nativeConfigString = QString("%1:%2@%3:%4") + .arg(nativeConfig.value("method").toString(), nativeConfig.value("password").toString(), + nativeConfig.value("server").toString(), nativeConfig.value("server_port").toString()); m_nativeConfigString = "ss://" + m_nativeConfigString.toUtf8().toBase64(); @@ -306,30 +259,17 @@ void ExportController::generateShadowSocksConfig() void ExportController::generateCloakConfig() { - clearPreviousConfig(); - - int serverIndex = m_serversModel->getProcessedServerIndex(); - ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); - - DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); - QJsonObject containerConfig = m_containersModel->getContainerConfig(container); - containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); - - ErrorCode errorCode = ErrorCode::NoError; - QString config = - m_configurator->cloakConfigurator->genCloakConfig(credentials, container, containerConfig, &errorCode); - + QJsonObject nativeConfig; + ErrorCode errorCode = generateNativeConfig(DockerContainer::Cloak, "", Proto::Cloak, nativeConfig); if (errorCode) { emit exportErrorOccurred(errorString(errorCode)); return; } - config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::Cloak, config); - QJsonObject configJson = QJsonDocument::fromJson(config.toUtf8()).object(); - configJson.remove(config_key::transport_proto); - configJson.insert("ProxyMethod", "shadowsocks"); + nativeConfig.remove(config_key::transport_proto); + nativeConfig.insert("ProxyMethod", "shadowsocks"); - QStringList lines = QString(QJsonDocument(configJson).toJson()).replace("\r", "").split("\n"); + QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n"); for (const QString &line : lines) { m_config.append(line + "\n"); } @@ -339,29 +279,14 @@ void ExportController::generateCloakConfig() void ExportController::generateXrayConfig() { - clearPreviousConfig(); - - int serverIndex = m_serversModel->getProcessedServerIndex(); - ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); - - DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); - QJsonObject containerConfig = m_containersModel->getContainerConfig(container); - containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); - - ErrorCode errorCode = ErrorCode::NoError; - - QString clientId; - QString config = - m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, Proto::Xray, clientId, &errorCode); - + QJsonObject nativeConfig; + ErrorCode errorCode = generateNativeConfig(DockerContainer::Xray, "", Proto::Xray, nativeConfig); if (errorCode) { emit exportErrorOccurred(errorString(errorCode)); return; } - config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::Xray, config); - QJsonObject configJson = QJsonDocument::fromJson(config.toUtf8()).object(); - QStringList lines = QString(QJsonDocument(configJson).toJson()).replace("\r", "").split("\n"); + QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n"); for (const QString &line : lines) { m_config.append(line + "\n"); } @@ -399,8 +324,7 @@ void ExportController::updateClientManagementModel(const DockerContainer contain void ExportController::revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials) { - ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials, - m_serversModel->getProcessedServerIndex()); + ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials, m_serversModel->getProcessedServerIndex()); if (errorCode != ErrorCode::NoError) { emit exportErrorOccurred(errorString(errorCode)); } diff --git a/client/ui/controllers/exportController.h b/client/ui/controllers/exportController.h index 06d620032..b978137e4 100644 --- a/client/ui/controllers/exportController.h +++ b/client/ui/controllers/exportController.h @@ -3,10 +3,9 @@ #include -#include "configurators/vpn_configurator.h" +#include "ui/models/clientManagementModel.h" #include "ui/models/containers_model.h" #include "ui/models/servers_model.h" -#include "ui/models/clientManagementModel.h" #ifdef Q_OS_ANDROID #include "platforms/android/authResultReceiver.h" #endif @@ -15,11 +14,9 @@ class ExportController : public QObject { Q_OBJECT public: - explicit ExportController(const QSharedPointer &serversModel, - const QSharedPointer &containersModel, - const QSharedPointer &clientManagementModel, - const std::shared_ptr &settings, - const std::shared_ptr &configurator, QObject *parent = nullptr); + explicit ExportController(const QSharedPointer &serversModel, const QSharedPointer &containersModel, + const QSharedPointer &clientManagementModel, const std::shared_ptr &settings, + QObject *parent = nullptr); Q_PROPERTY(QList qrCodes READ getQrCodes NOTIFY exportConfigChanged) Q_PROPERTY(int qrCodesCount READ getQrCodesCount NOTIFY exportConfigChanged) @@ -65,11 +62,13 @@ public slots: void clearPreviousConfig(); + ErrorCode generateNativeConfig(const DockerContainer container, const QString &clientName, const Proto &protocol, + QJsonObject &jsonNativeConfig); + QSharedPointer m_serversModel; QSharedPointer m_containersModel; QSharedPointer m_clientManagementModel; std::shared_ptr m_settings; - std::shared_ptr m_configurator; QString m_config; QString m_nativeConfigString; diff --git a/client/ui/controllers/installController.cpp b/client/ui/controllers/installController.cpp index 120a7e7c0..e0da065c3 100644 --- a/client/ui/controllers/installController.cpp +++ b/client/ui/controllers/installController.cpp @@ -4,11 +4,13 @@ #include #include #include -#include #include +#include -#include "core/errorstrings.h" #include "core/controllers/serverController.h" +#include "core/controllers/vpnConfigurationController.h" +#include "core/errorstrings.h" +#include "logger.h" #include "core/networkUtilities.h" #include "utilities.h" #include "ui/models/protocols/awgConfigModel.h" @@ -16,6 +18,8 @@ namespace { + Logger logger("ServerController"); + #ifdef Q_OS_WINDOWS QString getNextDriverLetter() { @@ -42,14 +46,15 @@ namespace #endif } -InstallController::InstallController(const QSharedPointer &serversModel, - const QSharedPointer &containersModel, +InstallController::InstallController(const QSharedPointer &serversModel, const QSharedPointer &containersModel, const QSharedPointer &protocolsModel, + const QSharedPointer &clientManagementModel, const std::shared_ptr &settings, QObject *parent) : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel), m_protocolModel(protocolsModel), + m_clientManagementModel(clientManagementModel), m_settings(settings) { } @@ -74,8 +79,7 @@ void InstallController::install(DockerContainer container, int port, TransportPr if (protocol == mainProto) { containerConfig.insert(config_key::port, QString::number(port)); - containerConfig.insert(config_key::transport_proto, - ProtocolProps::transportProtoToString(transportProto, protocol)); + containerConfig.insert(config_key::transport_proto, ProtocolProps::transportProtoToString(transportProto, protocol)); if (container == DockerContainer::Awg) { QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(3, 10)); @@ -107,9 +111,7 @@ void InstallController::install(DockerContainer container, int port, TransportPr containerConfig[config_key::responsePacketMagicHeader] = responsePacketMagicHeader; containerConfig[config_key::underloadPacketMagicHeader] = underloadPacketMagicHeader; containerConfig[config_key::transportPacketMagicHeader] = transportPacketMagicHeader; - } - - if (container == DockerContainer::Sftp) { + } else if (container == DockerContainer::Sftp) { containerConfig.insert(config_key::userName, protocols::sftp::defaultUserName); containerConfig.insert(config_key::password, Utils::getRandomString(10)); } @@ -119,109 +121,132 @@ void InstallController::install(DockerContainer container, int port, TransportPr config.insert(ProtocolProps::protoToString(protocol), containerConfig); } + ServerCredentials serverCredentials; if (m_shouldCreateServer) { if (isServerAlreadyExists()) { return; } - installServer(container, config); + serverCredentials = m_processedServerCredentials; } else { - installContainer(container, config); + int serverIndex = m_serversModel->getProcessedServerIndex(); + serverCredentials = qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); } -} -void InstallController::installServer(DockerContainer container, QJsonObject &config) -{ ServerController serverController(m_settings); connect(&serverController, &ServerController::serverIsBusy, this, &InstallController::serverIsBusy); connect(this, &InstallController::cancelInstallation, &serverController, &ServerController::cancelInstallation); QMap installedContainers; - ErrorCode errorCode = - serverController.getAlreadyInstalledContainers(m_currentlyInstalledServerCredentials, installedContainers); + ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, installedContainers); + if (errorCode) { + emit installationErrorOccurred(errorString(errorCode)); + return; + } QString finishMessage = ""; if (!installedContainers.contains(container)) { - errorCode = serverController.setupContainer(m_currentlyInstalledServerCredentials, container, config); + errorCode = serverController.setupContainer(serverCredentials, container, config); + if (errorCode) { + emit installationErrorOccurred(errorString(errorCode)); + return; + } + installedContainers.insert(container, config); finishMessage = tr("%1 installed successfully. ").arg(ContainerProps::containerHumanNames().value(container)); } else { finishMessage = tr("%1 is already installed on the server. ").arg(ContainerProps::containerHumanNames().value(container)); } + + if (errorCode) { + emit installationErrorOccurred(errorString(errorCode)); + return; + } + + if (m_shouldCreateServer) { + installServer(container, installedContainers, serverCredentials, finishMessage); + } else { + installContainer(container, installedContainers, serverCredentials, finishMessage); + } +} + +void InstallController::installServer(const DockerContainer container, const QMap &installedContainers, + const ServerCredentials &serverCredentials, QString &finishMessage) +{ if (installedContainers.size() > 1) { finishMessage += tr("\nAdded containers that were already installed on the server"); } - if (errorCode == ErrorCode::NoError) { - QJsonObject server; - server.insert(config_key::hostName, m_currentlyInstalledServerCredentials.hostName); - server.insert(config_key::userName, m_currentlyInstalledServerCredentials.userName); - server.insert(config_key::password, m_currentlyInstalledServerCredentials.secretData); - server.insert(config_key::port, m_currentlyInstalledServerCredentials.port); - server.insert(config_key::description, m_settings->nextAvailableServerName()); - - QJsonArray containerConfigs; - for (const QJsonObject &containerConfig : qAsConst(installedContainers)) { - containerConfigs.append(containerConfig); + QJsonObject server; + server.insert(config_key::hostName, m_processedServerCredentials.hostName); + server.insert(config_key::userName, m_processedServerCredentials.userName); + server.insert(config_key::password, m_processedServerCredentials.secretData); + server.insert(config_key::port, m_processedServerCredentials.port); + server.insert(config_key::description, m_settings->nextAvailableServerName()); + + QJsonArray containerConfigs; + VpnConfigurationsController vpnConfigurationController(m_settings); + for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) { + auto containerConfig = iterator.value(); + auto errorCode = + vpnConfigurationController.createProtocolConfigForContainer(m_processedServerCredentials, iterator.key(), containerConfig); + if (errorCode) { + emit installationErrorOccurred(errorString(errorCode)); + return; } + containerConfigs.append(containerConfig); - server.insert(config_key::containers, containerConfigs); - server.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); + errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig, + QString("Admin [%1]").arg(QSysInfo::prettyProductName())); + if (errorCode) { + emit installationErrorOccurred(errorString(errorCode)); + return; + } + } - m_serversModel->addServer(server); + server.insert(config_key::containers, containerConfigs); + server.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); - emit installServerFinished(finishMessage); - return; - } + m_serversModel->addServer(server); - emit installationErrorOccurred(errorString(errorCode)); + emit installServerFinished(finishMessage); } -void InstallController::installContainer(DockerContainer container, QJsonObject &config) +void InstallController::installContainer(const DockerContainer container, const QMap &installedContainers, + const ServerCredentials &serverCredentials, QString &finishMessage) { - int serverIndex = m_serversModel->getProcessedServerIndex(); - ServerCredentials serverCredentials = - qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); - - ServerController serverController(m_settings); - connect(&serverController, &ServerController::serverIsBusy, this, &InstallController::serverIsBusy); - connect(this, &InstallController::cancelInstallation, &serverController, &ServerController::cancelInstallation); - - QMap installedContainers; - ErrorCode errorCode = serverController.getAlreadyInstalledContainers(serverCredentials, installedContainers); - - QString finishMessage = ""; + bool isInstalledContainerAddedToGui = false; - if (!installedContainers.contains(container)) { - errorCode = serverController.setupContainer(serverCredentials, container, config); - installedContainers.insert(container, config); - finishMessage = tr("%1 installed successfully. ").arg(ContainerProps::containerHumanNames().value(container)); - } else { - finishMessage = tr("%1 is already installed on the server. ").arg(ContainerProps::containerHumanNames().value(container)); - } + VpnConfigurationsController vpnConfigurationController(m_settings); + for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) { + QJsonObject containerConfig = m_containersModel->getContainerConfig(iterator.key()); + if (containerConfig.isEmpty()) { + containerConfig = iterator.value(); + auto errorCode = vpnConfigurationController.createProtocolConfigForContainer(serverCredentials, iterator.key(), containerConfig); + if (errorCode) { + emit installationErrorOccurred(errorString(errorCode)); + return; + } + m_serversModel->addContainerConfig(iterator.key(), containerConfig); - bool isInstalledContainerAddedToGui = false; + errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig, + QString("Admin [%1]").arg(QSysInfo::prettyProductName())); + if (errorCode) { + emit installationErrorOccurred(errorString(errorCode)); + return; + } - if (errorCode == ErrorCode::NoError) { - for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) { - QJsonObject containerConfig = m_containersModel->getContainerConfig(iterator.key()); - if (containerConfig.isEmpty()) { - m_serversModel->addContainerConfig(iterator.key(), iterator.value()); - if (container != iterator.key()) { // skip the newly installed container - isInstalledContainerAddedToGui = true; - } + if (container != iterator.key()) { // skip the newly installed container + isInstalledContainerAddedToGui = true; } } - if (isInstalledContainerAddedToGui) { - finishMessage += tr("\nAlready installed containers were found on the server. " - "All installed containers have been added to the application"); - } - - emit installContainerFinished(finishMessage, ContainerProps::containerService(container) == ServiceType::Other); - return; + } + if (isInstalledContainerAddedToGui) { + finishMessage += tr("\nAlready installed containers were found on the server. " + "All installed containers have been added to the application"); } - emit installationErrorOccurred(errorString(errorCode)); + emit installContainerFinished(finishMessage, ContainerProps::containerService(container) == ServiceType::Other); } bool InstallController::isServerAlreadyExists() @@ -230,8 +255,7 @@ bool InstallController::isServerAlreadyExists() auto modelIndex = m_serversModel->index(i); const ServerCredentials credentials = qvariant_cast(m_serversModel->data(modelIndex, ServersModel::Roles::CredentialsRole)); - if (m_currentlyInstalledServerCredentials.hostName == credentials.hostName - && m_currentlyInstalledServerCredentials.port == credentials.port) { + if (m_processedServerCredentials.hostName == credentials.hostName && m_processedServerCredentials.port == credentials.port) { emit serverAlreadyExists(i); return true; } @@ -248,15 +272,31 @@ void InstallController::scanServerForInstalledContainers() ServerController serverController(m_settings); QMap installedContainers; - ErrorCode errorCode = serverController.getAlreadyInstalledContainers(serverCredentials, installedContainers); + ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, installedContainers); if (errorCode == ErrorCode::NoError) { bool isInstalledContainerAddedToGui = false; + VpnConfigurationsController vpnConfigurationController(m_settings); for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) { QJsonObject containerConfig = m_containersModel->getContainerConfig(iterator.key()); if (containerConfig.isEmpty()) { - m_serversModel->addContainerConfig(iterator.key(), iterator.value()); + containerConfig = iterator.value(); + auto errorCode = + vpnConfigurationController.createProtocolConfigForContainer(serverCredentials, iterator.key(), containerConfig); + if (errorCode) { + emit installationErrorOccurred(errorString(errorCode)); + return; + } + m_serversModel->addContainerConfig(iterator.key(), containerConfig); + + errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig, + QString("Admin [%1]").arg(QSysInfo::prettyProductName())); + if (errorCode) { + emit installationErrorOccurred(errorString(errorCode)); + return; + } + isInstalledContainerAddedToGui = true; } } @@ -268,6 +308,151 @@ void InstallController::scanServerForInstalledContainers() emit installationErrorOccurred(errorString(errorCode)); } +ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentials &credentials, + QMap &installedContainers) +{ + QString stdOut; + auto cbReadStdOut = [&](const QString &data, libssh::Client &) { + stdOut += data + "\n"; + return ErrorCode::NoError; + }; + auto cbReadStdErr = [&](const QString &data, libssh::Client &) { + stdOut += data + "\n"; + return ErrorCode::NoError; + }; + + ServerController serverController(m_settings); + QString script = QString("sudo docker ps --format '{{.Names}} {{.Ports}}'"); + + ErrorCode errorCode = serverController.runScript(credentials, script, cbReadStdOut, cbReadStdErr); + if (errorCode != ErrorCode::NoError) { + return errorCode; + } + + auto containersInfo = stdOut.split("\n"); + for (auto &containerInfo : containersInfo) { + if (containerInfo.isEmpty()) { + continue; + } + const static QRegularExpression containerAndPortRegExp("(amnezia[-a-z]*).*?:([0-9]*)->[0-9]*/(udp|tcp).*"); + QRegularExpressionMatch containerAndPortMatch = containerAndPortRegExp.match(containerInfo); + if (containerAndPortMatch.hasMatch()) { + QString name = containerAndPortMatch.captured(1); + QString port = containerAndPortMatch.captured(2); + QString transportProto = containerAndPortMatch.captured(3); + DockerContainer container = ContainerProps::containerFromString(name); + + QJsonObject config; + Proto mainProto = ContainerProps::defaultProtocol(container); + for (auto protocol : ContainerProps::protocolsForContainer(container)) { + QJsonObject containerConfig; + if (protocol == mainProto) { + containerConfig.insert(config_key::port, port); + containerConfig.insert(config_key::transport_proto, transportProto); + + if (protocol == Proto::Awg) { + QString serverConfig = serverController.getTextFileFromContainer(container, credentials, + protocols::awg::serverConfigPath, errorCode); + + QMap serverConfigMap; + auto serverConfigLines = serverConfig.split("\n"); + for (auto &line : serverConfigLines) { + auto trimmedLine = line.trimmed(); + if (trimmedLine.startsWith("[") && trimmedLine.endsWith("]")) { + continue; + } else { + QStringList parts = trimmedLine.split(" = "); + if (parts.count() == 2) { + serverConfigMap.insert(parts[0].trimmed(), parts[1].trimmed()); + } + } + } + + containerConfig[config_key::junkPacketCount] = serverConfigMap.value(config_key::junkPacketCount); + containerConfig[config_key::junkPacketMinSize] = serverConfigMap.value(config_key::junkPacketMinSize); + containerConfig[config_key::junkPacketMaxSize] = serverConfigMap.value(config_key::junkPacketMaxSize); + containerConfig[config_key::initPacketJunkSize] = serverConfigMap.value(config_key::initPacketJunkSize); + containerConfig[config_key::responsePacketJunkSize] = serverConfigMap.value(config_key::responsePacketJunkSize); + containerConfig[config_key::initPacketMagicHeader] = serverConfigMap.value(config_key::initPacketMagicHeader); + containerConfig[config_key::responsePacketMagicHeader] = serverConfigMap.value(config_key::responsePacketMagicHeader); + containerConfig[config_key::underloadPacketMagicHeader] = + serverConfigMap.value(config_key::underloadPacketMagicHeader); + containerConfig[config_key::transportPacketMagicHeader] = + serverConfigMap.value(config_key::transportPacketMagicHeader); + } else if (protocol == Proto::Sftp) { + stdOut.clear(); + script = QString("sudo docker inspect --format '{{.Config.Cmd}}' %1").arg(name); + + ErrorCode errorCode = serverController.runScript(credentials, script, cbReadStdOut, cbReadStdErr); + if (errorCode != ErrorCode::NoError) { + return errorCode; + } + + auto sftpInfo = stdOut.split(":"); + if (sftpInfo.size() < 2) { + logger.error() << "Key parameters for the sftp container are missing"; + continue; + } + auto userName = sftpInfo.at(0); + userName = userName.remove(0, 1); + auto password = sftpInfo.at(1); + + containerConfig.insert(config_key::userName, userName); + containerConfig.insert(config_key::password, password); + } + + config.insert(config_key::container, ContainerProps::containerToString(container)); + } + config.insert(ProtocolProps::protoToString(protocol), containerConfig); + } + installedContainers.insert(container, config); + } + const static QRegularExpression torOrDnsRegExp("(amnezia-(?:torwebsite|dns)).*?([0-9]*)/(udp|tcp).*"); + QRegularExpressionMatch torOrDnsRegMatch = torOrDnsRegExp.match(containerInfo); + if (torOrDnsRegMatch.hasMatch()) { + QString name = torOrDnsRegMatch.captured(1); + QString port = torOrDnsRegMatch.captured(2); + QString transportProto = torOrDnsRegMatch.captured(3); + DockerContainer container = ContainerProps::containerFromString(name); + + QJsonObject config; + Proto mainProto = ContainerProps::defaultProtocol(container); + for (auto protocol : ContainerProps::protocolsForContainer(container)) { + QJsonObject containerConfig; + if (protocol == mainProto) { + containerConfig.insert(config_key::port, port); + containerConfig.insert(config_key::transport_proto, transportProto); + + if (protocol == Proto::TorWebSite) { + stdOut.clear(); + script = QString("sudo docker exec -i %1 sh -c 'cat /var/lib/tor/hidden_service/hostname'").arg(name); + + ErrorCode errorCode = serverController.runScript(credentials, script, cbReadStdOut, cbReadStdErr); + if (errorCode != ErrorCode::NoError) { + return errorCode; + } + + if (stdOut.isEmpty()) { + logger.error() << "Key parameters for the tor container are missing"; + continue; + } + + QString onion = stdOut; + onion.replace("\n", ""); + containerConfig.insert(config_key::site, onion); + } + + config.insert(config_key::container, ContainerProps::containerToString(container)); + } + config.insert(ProtocolProps::protoToString(protocol), containerConfig); + } + installedContainers.insert(container, config); + } + } + + return ErrorCode::NoError; +} + void InstallController::updateContainer(QJsonObject config) { int serverIndex = m_serversModel->getProcessedServerIndex(); @@ -284,6 +469,7 @@ void InstallController::updateContainer(QJsonObject config) connect(this, &InstallController::cancelInstallation, &serverController, &ServerController::cancelInstallation); errorCode = serverController.updateContainer(serverCredentials, container, oldContainerConfig, config); + clearCachedProfile(); } if (errorCode == ErrorCode::NoError) { @@ -334,23 +520,51 @@ void InstallController::removeAllContainers() emit installationErrorOccurred(errorString(errorCode)); } -void InstallController::removeCurrentlyProcessedContainer() +void InstallController::removeProcessedContainer() { int serverIndex = m_serversModel->getProcessedServerIndex(); QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString(); - int container = m_containersModel->getCurrentlyProcessedContainerIndex(); - QString containerName = m_containersModel->getCurrentlyProcessedContainerName(); + int container = m_containersModel->getProcessedContainerIndex(); + QString containerName = m_containersModel->getProcessedContainerName(); ErrorCode errorCode = m_serversModel->removeContainer(container); if (errorCode == ErrorCode::NoError) { - emit removeCurrentlyProcessedContainerFinished(tr("%1 has been removed from the server '%2'").arg(containerName, serverName)); + emit removeProcessedContainerFinished(tr("%1 has been removed from the server '%2'").arg(containerName, serverName)); return; } emit installationErrorOccurred(errorString(errorCode)); } +void InstallController::removeApiConfig() +{ + auto serverConfig = m_serversModel->getServerConfig(m_serversModel->getDefaultServerIndex()); + + serverConfig.remove(config_key::dns1); + serverConfig.remove(config_key::dns2); + serverConfig.remove(config_key::containers); + serverConfig.remove(config_key::hostName); + + serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None)); + + m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex()); +} + +void InstallController::clearCachedProfile() +{ + int serverIndex = m_serversModel->getProcessedServerIndex(); + DockerContainer container = static_cast(m_containersModel->getProcessedContainerIndex()); + QJsonObject containerConfig = m_containersModel->getContainerConfig(container); + ServerCredentials serverCredentials = + qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); + + m_serversModel->clearCachedProfile(container); + m_clientManagementModel->revokeClient(containerConfig, container, serverCredentials, serverIndex); + + emit cachedProfileCleared(tr("%1 cached profile cleared").arg(ContainerProps::containerHumanNames().value(container))); +} + QRegularExpression InstallController::ipAddressPortRegExp() { return NetworkUtilities::ipAddressPortRegExp(); @@ -361,17 +575,15 @@ QRegularExpression InstallController::ipAddressRegExp() return NetworkUtilities::ipAddressRegExp(); } -void InstallController::setCurrentlyInstalledServerCredentials(const QString &hostName, const QString &userName, - const QString &secretData) +void InstallController::setProcessedServerCredentials(const QString &hostName, const QString &userName, const QString &secretData) { - m_currentlyInstalledServerCredentials.hostName = hostName; - if (m_currentlyInstalledServerCredentials.hostName.contains(":")) { - m_currentlyInstalledServerCredentials.port = - m_currentlyInstalledServerCredentials.hostName.split(":").at(1).toInt(); - m_currentlyInstalledServerCredentials.hostName = m_currentlyInstalledServerCredentials.hostName.split(":").at(0); + m_processedServerCredentials.hostName = hostName; + if (m_processedServerCredentials.hostName.contains(":")) { + m_processedServerCredentials.port = m_processedServerCredentials.hostName.split(":").at(1).toInt(); + m_processedServerCredentials.hostName = m_processedServerCredentials.hostName.split(":").at(0); } - m_currentlyInstalledServerCredentials.userName = userName; - m_currentlyInstalledServerCredentials.secretData = secretData; + m_processedServerCredentials.userName = userName; + m_processedServerCredentials.secretData = secretData; } void InstallController::setShouldCreateServer(bool shouldCreateServer) @@ -398,8 +610,7 @@ void InstallController::mountSftpDrive(const QString &port, const QString &passw cmd = "C:\\Program Files\\SSHFS-Win\\bin\\sshfs.exe"; #elif defined AMNEZIA_DESKTOP - mountPath = - QString("%1/sftp:%2:%3").arg(QStandardPaths::writableLocation(QStandardPaths::HomeLocation), hostname, port); + mountPath = QString("%1/sftp:%2:%3").arg(QStandardPaths::writableLocation(QStandardPaths::HomeLocation), hostname, port); QDir dir(mountPath); if (!dir.exists()) { dir.mkpath(mountPath); @@ -461,8 +672,7 @@ bool InstallController::checkSshConnection() ErrorCode errorCode = ErrorCode::NoError; m_privateKeyPassphrase = ""; - if (m_currentlyInstalledServerCredentials.secretData.contains("BEGIN") - && m_currentlyInstalledServerCredentials.secretData.contains("PRIVATE KEY")) { + if (m_processedServerCredentials.secretData.contains("BEGIN") && m_processedServerCredentials.secretData.contains("PRIVATE KEY")) { auto passphraseCallback = [this]() { emit passphraseRequestStarted(); QEventLoop loop; @@ -473,10 +683,9 @@ bool InstallController::checkSshConnection() }; QString decryptedPrivateKey; - errorCode = serverController.getDecryptedPrivateKey(m_currentlyInstalledServerCredentials, decryptedPrivateKey, - passphraseCallback); + errorCode = serverController.getDecryptedPrivateKey(m_processedServerCredentials, decryptedPrivateKey, passphraseCallback); if (errorCode == ErrorCode::NoError) { - m_currentlyInstalledServerCredentials.secretData = decryptedPrivateKey; + m_processedServerCredentials.secretData = decryptedPrivateKey; } else { emit installationErrorOccurred(errorString(errorCode)); return false; @@ -484,7 +693,7 @@ bool InstallController::checkSshConnection() } QString output; - output = serverController.checkSshConnection(m_currentlyInstalledServerCredentials, &errorCode); + output = serverController.checkSshConnection(m_processedServerCredentials, errorCode); if (errorCode != ErrorCode::NoError) { emit installationErrorOccurred(errorString(errorCode)); @@ -508,10 +717,10 @@ void InstallController::setEncryptedPassphrase(QString passphrase) void InstallController::addEmptyServer() { QJsonObject server; - server.insert(config_key::hostName, m_currentlyInstalledServerCredentials.hostName); - server.insert(config_key::userName, m_currentlyInstalledServerCredentials.userName); - server.insert(config_key::password, m_currentlyInstalledServerCredentials.secretData); - server.insert(config_key::port, m_currentlyInstalledServerCredentials.port); + server.insert(config_key::hostName, m_processedServerCredentials.hostName); + server.insert(config_key::userName, m_processedServerCredentials.userName); + server.insert(config_key::password, m_processedServerCredentials.secretData); + server.insert(config_key::port, m_processedServerCredentials.port); server.insert(config_key::description, m_settings->nextAvailableServerName()); server.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None)); @@ -532,17 +741,17 @@ bool InstallController::isUpdateDockerContainerRequired(const DockerContainer co const AwgConfig oldConfig(oldProtoConfig); const AwgConfig newConfig(newProtoConfig); - if (!oldConfig.hasEqualServerSettings(newConfig)) { - return true; + if (oldConfig.hasEqualServerSettings(newConfig)) { + return false; } } else if (container == DockerContainer::WireGuard) { const WgConfig oldConfig(oldProtoConfig); const WgConfig newConfig(newProtoConfig); - if (!oldConfig.hasEqualServerSettings(newConfig)) { - return true; + if (oldConfig.hasEqualServerSettings(newConfig)) { + return false; } } - return false; + return true; } diff --git a/client/ui/controllers/installController.h b/client/ui/controllers/installController.h index 490903499..b44b25202 100644 --- a/client/ui/controllers/installController.h +++ b/client/ui/controllers/installController.h @@ -6,24 +6,24 @@ #include "containers/containers_defs.h" #include "core/defs.h" +#include "ui/models/clientManagementModel.h" #include "ui/models/containers_model.h" -#include "ui/models/servers_model.h" #include "ui/models/protocols_model.h" +#include "ui/models/servers_model.h" class InstallController : public QObject { Q_OBJECT public: - explicit InstallController(const QSharedPointer &serversModel, - const QSharedPointer &containersModel, + explicit InstallController(const QSharedPointer &serversModel, const QSharedPointer &containersModel, const QSharedPointer &protocolsModel, + const QSharedPointer &clientManagementModel, const std::shared_ptr &settings, QObject *parent = nullptr); ~InstallController(); public slots: void install(DockerContainer container, int port, TransportProto transportProto); - void setCurrentlyInstalledServerCredentials(const QString &hostName, const QString &userName, - const QString &secretData); + void setProcessedServerCredentials(const QString &hostName, const QString &userName, const QString &secretData); void setShouldCreateServer(bool shouldCreateServer); void scanServerForInstalledContainers(); @@ -33,7 +33,11 @@ public slots: void removeProcessedServer(); void rebootProcessedServer(); void removeAllContainers(); - void removeCurrentlyProcessedContainer(); + void removeProcessedContainer(); + + void removeApiConfig(); + + void clearCachedProfile(); QRegularExpression ipAddressPortRegExp(); QRegularExpression ipAddressRegExp(); @@ -50,14 +54,14 @@ public slots: void installContainerFinished(const QString &finishMessage, bool isServiceInstall); void installServerFinished(const QString &finishMessage); - void updateContainerFinished(const QString& message); + void updateContainerFinished(const QString &message); void scanServerFinished(bool isInstalledContainerFound); void rebootProcessedServerFinished(const QString &finishedMessage); void removeProcessedServerFinished(const QString &finishedMessage); void removeAllContainersFinished(const QString &finishedMessage); - void removeCurrentlyProcessedContainerFinished(const QString &finishedMessage); + void removeProcessedContainerFinished(const QString &finishedMessage); void installationErrorOccurred(const QString &errorMessage); @@ -71,19 +75,25 @@ public slots: void currentContainerUpdated(); + void cachedProfileCleared(const QString &message); + private: - void installServer(DockerContainer container, QJsonObject &config); - void installContainer(DockerContainer container, QJsonObject &config); + void installServer(const DockerContainer container, const QMap &installedContainers, + const ServerCredentials &serverCredentials, QString &finishMessage); + void installContainer(const DockerContainer container, const QMap &installedContainers, + const ServerCredentials &serverCredentials, QString &finishMessage); bool isServerAlreadyExists(); + ErrorCode getAlreadyInstalledContainers(const ServerCredentials &credentials, QMap &installedContainers); bool isUpdateDockerContainerRequired(const DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig); QSharedPointer m_serversModel; QSharedPointer m_containersModel; QSharedPointer m_protocolModel; + QSharedPointer m_clientManagementModel; std::shared_ptr m_settings; - ServerCredentials m_currentlyInstalledServerCredentials; + ServerCredentials m_processedServerCredentials; bool m_shouldCreateServer; diff --git a/client/ui/controllers/settingsController.cpp b/client/ui/controllers/settingsController.cpp index 16787ef8a..4ac675048 100644 --- a/client/ui/controllers/settingsController.cpp +++ b/client/ui/controllers/settingsController.cpp @@ -153,12 +153,6 @@ void SettingsController::clearSettings() #endif } -void SettingsController::clearCachedProfiles() -{ - m_serversModel->clearCachedProfiles(); - emit changeSettingsFinished(tr("Cached profiles cleared")); -} - bool SettingsController::isAutoConnectEnabled() { return m_settings->isAutoConnect(); diff --git a/client/ui/controllers/settingsController.h b/client/ui/controllers/settingsController.h index 72ba72e92..2678c65d5 100644 --- a/client/ui/controllers/settingsController.h +++ b/client/ui/controllers/settingsController.h @@ -46,7 +46,6 @@ public slots: QString getAppVersion(); void clearSettings(); - void clearCachedProfiles(); bool isAutoConnectEnabled(); void toggleAutoConnect(bool enable); diff --git a/client/ui/models/clientManagementModel.cpp b/client/ui/models/clientManagementModel.cpp index 7c81c80ec..ae4c48dc6 100644 --- a/client/ui/models/clientManagementModel.cpp +++ b/client/ui/models/clientManagementModel.cpp @@ -10,7 +10,8 @@ namespace { Logger logger("ClientManagementModel"); - namespace configKey { + namespace configKey + { constexpr char clientId[] = "clientId"; constexpr char clientName[] = "clientName"; constexpr char container[] = "container"; @@ -61,7 +62,6 @@ void ClientManagementModel::migration(const QByteArray &clientsTableString) m_clientsTable.push_back(client); } - } ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCredentials credentials) @@ -74,15 +74,13 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr ErrorCode error = ErrorCode::NoError; QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable"); - if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks - || container == DockerContainer::Cloak) { + if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn)); } else { clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container)); } - const QByteArray clientsTableString = - serverController.getTextFileFromContainer(container, credentials, clientsTableFile, &error); + const QByteArray clientsTableString = serverController.getTextFileFromContainer(container, credentials, clientsTableFile, error); if (error != ErrorCode::NoError) { logger.error() << "Failed to get the clientsTable file from the server"; endResetModel(); @@ -96,8 +94,7 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr int count = 0; - if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks - || container == DockerContainer::Cloak) { + if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { error = getOpenVpnClients(serverController, container, credentials, count); } else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) { error = getWireGuardClients(serverController, container, credentials, count); @@ -109,8 +106,7 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr const QByteArray newClientsTableString = QJsonDocument(m_clientsTable).toJson(); if (clientsTableString != newClientsTableString) { - error = serverController.uploadTextFileToContainer(container, credentials, newClientsTableString, - clientsTableFile); + error = serverController.uploadTextFileToContainer(container, credentials, newClientsTableString, clientsTableFile); if (error != ErrorCode::NoError) { logger.error() << "Failed to upload the clientsTable file to the server"; } @@ -121,7 +117,8 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr return error; } -ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverController, DockerContainer container, ServerCredentials credentials, int &count) +ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverController, DockerContainer container, + ServerCredentials credentials, int &count) { ErrorCode error = ErrorCode::NoError; QString stdOut; @@ -130,10 +127,8 @@ ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverContr return ErrorCode::NoError; }; - const QString getOpenVpnClientsList = - "sudo docker exec -i $CONTAINER_NAME bash -c 'ls /opt/amnezia/openvpn/pki/issued'"; - QString script = serverController.replaceVars(getOpenVpnClientsList, - serverController.genVarsForScript(credentials, container)); + const QString getOpenVpnClientsList = "sudo docker exec -i $CONTAINER_NAME bash -c 'ls /opt/amnezia/openvpn/pki/issued'"; + QString script = serverController.replaceVars(getOpenVpnClientsList, serverController.genVarsForScript(credentials, container)); error = serverController.runScript(credentials, script, cbReadStdOut); if (error != ErrorCode::NoError) { logger.error() << "Failed to retrieve the list of issued certificates on the server"; @@ -163,14 +158,13 @@ ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverContr return error; } -ErrorCode ClientManagementModel::getWireGuardClients(ServerController &serverController, DockerContainer container, ServerCredentials credentials, int &count) +ErrorCode ClientManagementModel::getWireGuardClients(ServerController &serverController, DockerContainer container, + ServerCredentials credentials, int &count) { ErrorCode error = ErrorCode::NoError; - const QString wireGuardConfigFile = - QString("opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg"); - const QString wireguardConfigString = - serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, &error); + const QString wireGuardConfigFile = QString("opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg"); + const QString wireguardConfigString = serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, error); if (error != ErrorCode::NoError) { logger.error() << "Failed to get the wg conf file from the server"; return error; @@ -215,10 +209,27 @@ bool ClientManagementModel::isClientExists(const QString &clientId) return false; } -ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QString &clientName, - const DockerContainer container, ServerCredentials credentials) +ErrorCode ClientManagementModel::appendClient(const DockerContainer container, const ServerCredentials &credentials, + const QJsonObject &containerConfig, const QString &clientName) { - ErrorCode error; + Proto protocol; + if (container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { + protocol = Proto::OpenVpn; + } else if (container == DockerContainer::OpenVpn || container == DockerContainer::WireGuard || container == DockerContainer::Awg) { + protocol = ContainerProps::defaultProtocol(container); + } else { + return ErrorCode::NoError; + } + + auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig); + + return appendClient(protocolConfig.value(config_key::clientId).toString(), clientName, container, credentials); +} + +ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QString &clientName, const DockerContainer container, + ServerCredentials credentials) +{ + ErrorCode error = ErrorCode::NoError; error = updateModel(container, credentials); if (error != ErrorCode::NoError) { @@ -246,8 +257,7 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt ServerController serverController(m_settings); QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable"); - if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks - || container == DockerContainer::Cloak) { + if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn)); } else { clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container)); @@ -279,15 +289,13 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie ServerController serverController(m_settings); QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable"); - if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks - || container == DockerContainer::Cloak) { + if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn)); } else { clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container)); } - ErrorCode error = - serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); + ErrorCode error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); if (error != ErrorCode::NoError) { logger.error() << "Failed to upload the clientsTable file to the server"; } @@ -295,15 +303,14 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie return error; } -ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContainer container, - ServerCredentials credentials, const int serverIndex) +ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContainer container, ServerCredentials credentials, + const int serverIndex) { ErrorCode errorCode = ErrorCode::NoError; auto client = m_clientsTable.at(row).toObject(); QString clientId = client.value(configKey::clientId).toString(); - if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks - || container == DockerContainer::Cloak) { + if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { errorCode = revokeOpenVpn(row, container, credentials, serverIndex); } else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) { errorCode = revokeWireGuard(row, container, credentials); @@ -333,8 +340,50 @@ ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContain return errorCode; } -ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContainer container, - ServerCredentials credentials, const int serverIndex) +ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig, const DockerContainer container, ServerCredentials credentials, + const int serverIndex) +{ + ErrorCode errorCode = ErrorCode::NoError; + errorCode = updateModel(container, credentials); + if (errorCode != ErrorCode::NoError) { + return errorCode; + } + + Proto protocol; + if (container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { + protocol = Proto::OpenVpn; + } else if (container == DockerContainer::OpenVpn || container == DockerContainer::WireGuard || container == DockerContainer::Awg) { + protocol = ContainerProps::defaultProtocol(container); + } else { + return ErrorCode::NoError; + } + + auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig); + + int row; + bool clientExists = false; + QString clientId = protocolConfig.value(config_key::clientId).toString(); + for (row = 0; row < rowCount(); row++) { + auto client = m_clientsTable.at(row).toObject(); + if (clientId == client.value(configKey::clientId).toString()) { + clientExists = true; + break; + } + } + if (!clientExists) { + return errorCode; + } + + if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { + errorCode = revokeOpenVpn(row, container, credentials, serverIndex); + } else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) { + errorCode = revokeWireGuard(row, container, credentials); + } + return errorCode; +} + +ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContainer container, ServerCredentials credentials, + const int serverIndex) { auto client = m_clientsTable.at(row).toObject(); QString clientId = client.value(configKey::clientId).toString(); @@ -348,8 +397,7 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai .arg(clientId); ServerController serverController(m_settings); - const QString script = - serverController.replaceVars(getOpenVpnCertData, serverController.genVarsForScript(credentials, container)); + const QString script = serverController.replaceVars(getOpenVpnCertData, serverController.genVarsForScript(credentials, container)); ErrorCode error = serverController.runScript(credentials, script); if (error != ErrorCode::NoError) { logger.error() << "Failed to revoke the certificate"; @@ -373,16 +421,14 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai return ErrorCode::NoError; } -ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerContainer container, - ServerCredentials credentials) +ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerContainer container, ServerCredentials credentials) { - ErrorCode error; + ErrorCode error = ErrorCode::NoError; ServerController serverController(m_settings); const QString wireGuardConfigFile = QString("/opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg"); - const QString wireguardConfigString = - serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, &error); + const QString wireguardConfigString = serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, error); if (error != ErrorCode::NoError) { logger.error() << "Failed to get the wg conf file from the server"; return error; @@ -413,8 +459,7 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson(); QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable"); - if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks - || container == DockerContainer::Cloak) { + if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) { clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn)); } else { clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container)); @@ -428,8 +473,7 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont const QString script = "sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'"; error = serverController.runScript( credentials, - serverController.replaceVars(script.arg(wireGuardConfigFile), - serverController.genVarsForScript(credentials, container))); + serverController.replaceVars(script.arg(wireGuardConfigFile), serverController.genVarsForScript(credentials, container))); if (error != ErrorCode::NoError) { logger.error() << "Failed to execute the command 'wg syncconf' on the server"; return error; diff --git a/client/ui/models/clientManagementModel.h b/client/ui/models/clientManagementModel.h index c003881b3..836207bae 100644 --- a/client/ui/models/clientManagementModel.h +++ b/client/ui/models/clientManagementModel.h @@ -24,11 +24,14 @@ class ClientManagementModel : public QAbstractListModel public slots: ErrorCode updateModel(DockerContainer container, ServerCredentials credentials); + ErrorCode appendClient(const DockerContainer container, const ServerCredentials &credentials, const QJsonObject &containerConfig, + const QString &clientName); ErrorCode appendClient(const QString &clientId, const QString &clientName, const DockerContainer container, ServerCredentials credentials); - ErrorCode renameClient(const int row, const QString &userName, const DockerContainer container, - ServerCredentials credentials, bool addTimeStamp = false); + ErrorCode renameClient(const int row, const QString &userName, const DockerContainer container, ServerCredentials credentials, + bool addTimeStamp = false); ErrorCode revokeClient(const int index, const DockerContainer container, ServerCredentials credentials, const int serverIndex); + ErrorCode revokeClient(const QJsonObject &containerConfig, const DockerContainer container, ServerCredentials credentials, const int serverIndex); protected: QHash roleNames() const override; diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 38e547df2..877865775 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -38,7 +38,7 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const case EasySetupDescriptionRole: return ContainerProps::easySetupDescription(container); case EasySetupOrderRole: return ContainerProps::easySetupOrder(container); case IsInstalledRole: return m_containers.contains(container); - case IsCurrentlyProcessedRole: return container == static_cast(m_currentlyProcessedContainerIndex); + case IsCurrentlyProcessedRole: return container == static_cast(m_processedContainerIndex); case IsSupportedRole: return ContainerProps::isSupportedByCurrentPlatform(container); case IsShareableRole: return ContainerProps::isShareable(container); } @@ -63,19 +63,19 @@ void ContainersModel::updateModel(const QJsonArray &containers) endResetModel(); } -void ContainersModel::setCurrentlyProcessedContainerIndex(int index) +void ContainersModel::setProcessedContainerIndex(int index) { - m_currentlyProcessedContainerIndex = index; + m_processedContainerIndex = index; } -int ContainersModel::getCurrentlyProcessedContainerIndex() +int ContainersModel::getProcessedContainerIndex() { - return m_currentlyProcessedContainerIndex; + return m_processedContainerIndex; } -QString ContainersModel::getCurrentlyProcessedContainerName() +QString ContainersModel::getProcessedContainerName() { - return ContainerProps::containerHumanNames().value(static_cast(m_currentlyProcessedContainerIndex)); + return ContainerProps::containerHumanNames().value(static_cast(m_processedContainerIndex)); } QJsonObject ContainersModel::getContainerConfig(const int containerIndex) diff --git a/client/ui/models/containers_model.h b/client/ui/models/containers_model.h index 385adf572..740e54b42 100644 --- a/client/ui/models/containers_model.h +++ b/client/ui/models/containers_model.h @@ -42,10 +42,10 @@ class ContainersModel : public QAbstractListModel public slots: void updateModel(const QJsonArray &containers); - void setCurrentlyProcessedContainerIndex(int containerIndex); - int getCurrentlyProcessedContainerIndex(); + void setProcessedContainerIndex(int containerIndex); + int getProcessedContainerIndex(); - QString getCurrentlyProcessedContainerName(); + QString getProcessedContainerName(); QJsonObject getContainerConfig(const int containerIndex); @@ -58,7 +58,7 @@ public slots: private: QMap m_containers; - int m_currentlyProcessedContainerIndex; + int m_processedContainerIndex; }; #endif // CONTAINERS_MODEL_H diff --git a/client/ui/models/protocols/shadowsocksConfigModel.cpp b/client/ui/models/protocols/shadowsocksConfigModel.cpp index 60c8feeea..2fe2d2a9d 100644 --- a/client/ui/models/protocols/shadowsocksConfigModel.cpp +++ b/client/ui/models/protocols/shadowsocksConfigModel.cpp @@ -37,6 +37,8 @@ QVariant ShadowSocksConfigModel::data(const QModelIndex &index, int role) const case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort); case Roles::CipherRole: return m_protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher); + case Roles::IsPortEditableRole: return m_container == DockerContainer::ShadowSocks ? true : false; + case Roles::IsCipherEditableRole: return m_container == DockerContainer::ShadowSocks ? true : false; } return QVariant(); @@ -71,6 +73,8 @@ QHash ShadowSocksConfigModel::roleNames() const roles[PortRole] = "port"; roles[CipherRole] = "cipher"; + roles[IsPortEditableRole] = "isPortEditable"; + roles[IsCipherEditableRole] = "isCipherEditable"; return roles; } diff --git a/client/ui/models/protocols/shadowsocksConfigModel.h b/client/ui/models/protocols/shadowsocksConfigModel.h index d8fa036b1..566df7683 100644 --- a/client/ui/models/protocols/shadowsocksConfigModel.h +++ b/client/ui/models/protocols/shadowsocksConfigModel.h @@ -13,7 +13,9 @@ class ShadowSocksConfigModel : public QAbstractListModel public: enum Roles { PortRole = Qt::UserRole + 1, - CipherRole + CipherRole, + IsPortEditableRole, + IsCipherEditableRole }; explicit ShadowSocksConfigModel(QObject *parent = nullptr); diff --git a/client/ui/models/protocols/wireguardConfigModel.cpp b/client/ui/models/protocols/wireguardConfigModel.cpp index 60f6685fc..8903f40f6 100644 --- a/client/ui/models/protocols/wireguardConfigModel.cpp +++ b/client/ui/models/protocols/wireguardConfigModel.cpp @@ -63,7 +63,7 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config) QJsonObject WireGuardConfigModel::getConfig() { - const WgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject()); + const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject()); const WgConfig newConfig(m_protocolConfig); if (!oldConfig.hasEqualServerSettings(newConfig)) { diff --git a/client/ui/models/protocols_model.cpp b/client/ui/models/protocols_model.cpp index b1bffa3f9..b2838ce3c 100644 --- a/client/ui/models/protocols_model.cpp +++ b/client/ui/models/protocols_model.cpp @@ -77,6 +77,7 @@ PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const case Proto::Cloak: return PageLoader::PageEnum::PageProtocolCloakSettings; case Proto::ShadowSocks: return PageLoader::PageEnum::PageProtocolShadowSocksSettings; case Proto::WireGuard: return PageLoader::PageEnum::PageProtocolWireGuardSettings; + case Proto::Awg: return PageLoader::PageEnum::PageProtocolAwgSettings; case Proto::Ikev2: return PageLoader::PageEnum::PageProtocolIKev2Settings; case Proto::L2tp: return PageLoader::PageEnum::PageProtocolIKev2Settings; case Proto::Xray: return PageLoader::PageEnum::PageProtocolXraySettings; diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index 8a6c5a38d..f3f45e15d 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -1,14 +1,17 @@ #include "servers_model.h" #include "core/controllers/serverController.h" +#include "core/networkUtilities.h" -ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) - : m_settings(settings), QAbstractListModel(parent) +ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent) { + m_isAmneziaDnsEnabled = m_settings->useAmneziaDns(); + connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerNameChanged); connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) { - auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString()); + auto defaultContainer = + ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString()); emit ServersModel::defaultServerDefaultContainerChanged(defaultContainer); emit ServersModel::defaultServerNameChanged(); updateDefaultServerContainersModel(); @@ -336,9 +339,9 @@ void ServersModel::updateDefaultServerContainersModel() emit defaultServerContainersUpdated(containers); } -QJsonObject ServersModel::getDefaultServerConfig() +QJsonObject ServersModel::getServerConfig(const int serverIndex) { - return m_servers.at(m_defaultServerIndex).toObject(); + return m_servers.at(serverIndex).toObject(); } void ServersModel::reloadDefaultServerContainerConfig() @@ -378,7 +381,8 @@ void ServersModel::updateContainerConfig(const int containerIndex, const QJsonOb 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)) { + if ((ContainerProps::containerFromString(defaultContainer) == DockerContainer::None + || ContainerProps::containerService(container) != ServiceType::Other)) { server.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); } @@ -396,7 +400,8 @@ void ServersModel::addContainerConfig(const int containerIndex, const QJsonObjec 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)) { + if ((ContainerProps::containerFromString(defaultContainer) == DockerContainer::None + || ContainerProps::containerService(container) != ServiceType::Other)) { server.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); } @@ -408,7 +413,7 @@ void ServersModel::setDefaultContainer(const int serverIndex, const int containe auto container = static_cast(containerIndex); QJsonObject s = m_servers.at(serverIndex).toObject(); s.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); - editServer(s, serverIndex); //check + editServer(s, serverIndex); // check } const QString ServersModel::getDefaultServerDefaultContainerName() @@ -420,8 +425,7 @@ const QString ServersModel::getDefaultServerDefaultContainerName() ErrorCode ServersModel::removeAllContainers() { ServerController serverController(m_settings); - ErrorCode errorCode = - serverController.removeAllContainers(m_settings->serverCredentials(m_processedServerIndex)); + ErrorCode errorCode = serverController.removeAllContainers(m_settings->serverCredentials(m_processedServerIndex)); if (errorCode == ErrorCode::NoError) { QJsonObject s = m_servers.at(m_processedServerIndex).toObject(); @@ -468,7 +472,8 @@ ErrorCode ServersModel::removeContainer(const int containerIndex) if (containers.empty()) { defaultContainer = DockerContainer::None; } else { - defaultContainer = ContainerProps::containerFromString(containers.begin()->toObject().value(config_key::container).toString()); + defaultContainer = + ContainerProps::containerFromString(containers.begin()->toObject().value(config_key::container).toString()); } server.insert(config_key::defaultContainer, ContainerProps::containerToString(defaultContainer)); } @@ -478,24 +483,9 @@ ErrorCode ServersModel::removeContainer(const int containerIndex) return errorCode; } -void ServersModel::clearCachedProfiles() -{ - const auto &containers = m_settings->containers(m_processedServerIndex); - for (DockerContainer container : containers.keys()) { - m_settings->clearLastConnectionConfig(m_processedServerIndex, container); - } - - m_servers.replace(m_processedServerIndex, m_settings->server(m_processedServerIndex)); - if (m_processedServerIndex == m_defaultServerIndex) { - updateDefaultServerContainersModel(); - } - updateContainersModel(); -} - void ServersModel::clearCachedProfile(const DockerContainer container) { m_settings->clearLastConnectionConfig(m_processedServerIndex, container); - m_servers.replace(m_processedServerIndex, m_settings->server(m_processedServerIndex)); if (m_processedServerIndex == m_defaultServerIndex) { updateDefaultServerContainersModel(); @@ -515,6 +505,36 @@ bool ServersModel::isAmneziaDnsContainerInstalled(const int serverIndex) const return false; } +QPair ServersModel::getDnsPair(int serverIndex) +{ + QPair dns; + + const QJsonObject &server = m_servers.at(m_processedServerIndex).toObject(); + const auto containers = server.value(config_key::containers).toArray(); + bool isDnsContainerInstalled = false; + for (const QJsonValue &container : containers) { + if (ContainerProps::containerFromString(container.toObject().value(config_key::container).toString()) == DockerContainer::Dns) { + isDnsContainerInstalled = true; + } + } + + dns.first = server.value(config_key::dns1).toString(); + dns.second = server.value(config_key::dns2).toString(); + + if (dns.first.isEmpty() || !NetworkUtilities::checkIPv4Format(dns.first)) { + if (m_isAmneziaDnsEnabled && isDnsContainerInstalled) { + dns.first = protocols::dns::amneziaDnsIp; + } else + dns.first = m_settings->primaryDns(); + } + if (dns.second.isEmpty() || !NetworkUtilities::checkIPv4Format(dns.second)) { + dns.second = m_settings->secondaryDns(); + } + + qDebug() << "VpnConfigurator::getDnsForConfig" << dns.first << dns.second; + return dns; +} + QStringList ServersModel::getAllInstalledServicesName(const int serverIndex) { QStringList servicesName; @@ -598,7 +618,8 @@ bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling() if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::WireGuard) { return !(protocolConfig.value(config_key::last_config).toString().contains("AllowedIPs = 0.0.0.0/0, ::/0")); - } else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn || defaultContainer == DockerContainer::ShadowSocks) { + } else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn + || defaultContainer == DockerContainer::ShadowSocks) { return !(protocolConfig.value(config_key::last_config).toString().contains("redirect-gateway")); } diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h index 00d8d06c1..7f4e3f6b8 100644 --- a/client/ui/models/servers_model.h +++ b/client/ui/models/servers_model.h @@ -80,13 +80,12 @@ public slots: void editServer(const QJsonObject &server, const int serverIndex); void removeServer(); - QJsonObject getDefaultServerConfig(); + QJsonObject getServerConfig(const int serverIndex); void reloadDefaultServerContainerConfig(); void updateContainerConfig(const int containerIndex, const QJsonObject config); void addContainerConfig(const int containerIndex, const QJsonObject config); - void clearCachedProfiles(); void clearCachedProfile(const DockerContainer container); ErrorCode removeContainer(const int containerIndex); @@ -98,6 +97,7 @@ public slots: QStringList getAllInstalledServicesName(const int serverIndex); void toggleAmneziaDns(bool enabled); + QPair getDnsPair(const int serverIndex); bool isServerFromApiAlreadyExists(const quint16 crc); diff --git a/client/ui/qml/Components/ConnectButton.qml b/client/ui/qml/Components/ConnectButton.qml index a915eb21f..14e398a44 100644 --- a/client/ui/qml/Components/ConnectButton.qml +++ b/client/ui/qml/Components/ConnectButton.qml @@ -17,16 +17,16 @@ Button { implicitWidth: 190 implicitHeight: 190 + text: ConnectionController.connectionStateText + Connections { target: ConnectionController - function onConnectionErrorOccurred(errorMessage) { - PageController.showErrorMessage(errorMessage) + function onPreparingConfig() { + PageController.showNotificationMessage(qsTr("Unable to disconnect during configuration preparation")) } } - text: ConnectionController.connectionStateText - // enabled: !ConnectionController.isConnectionInProgress background: Item { @@ -139,6 +139,6 @@ Button { onClicked: { ServersModel.setProcessedServerIndex(ServersModel.defaultIndex) - ApiController.updateServerConfigFromApi() + ConnectionController.connectButtonClicked() } } diff --git a/client/ui/qml/Components/HomeContainersListView.qml b/client/ui/qml/Components/HomeContainersListView.qml index c785af8b5..f2a7ae88d 100644 --- a/client/ui/qml/Components/HomeContainersListView.qml +++ b/client/ui/qml/Components/HomeContainersListView.qml @@ -69,7 +69,7 @@ ListView { return } - ContainersModel.setCurrentlyProcessedContainerIndex(proxyDefaultServerContainersModel.mapToSource(index)) + ContainersModel.setProcessedContainerIndex(proxyDefaultServerContainersModel.mapToSource(index)) InstallController.setShouldCreateServer(false) PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings) containersDropDown.close() diff --git a/client/ui/qml/Components/SettingsContainersListView.qml b/client/ui/qml/Components/SettingsContainersListView.qml index 3a33e5cc0..5102f3e6b 100644 --- a/client/ui/qml/Components/SettingsContainersListView.qml +++ b/client/ui/qml/Components/SettingsContainersListView.qml @@ -41,7 +41,7 @@ ListView { clickedFunction: function() { if (isInstalled) { var containerIndex = root.model.mapToSource(index) - ContainersModel.setCurrentlyProcessedContainerIndex(containerIndex) + ContainersModel.setProcessedContainerIndex(containerIndex) if (serviceType !== ProtocolEnum.Other) { if (config[ContainerProps.containerTypeToString(containerIndex)]["isThirdPartyConfig"]) { @@ -52,27 +52,6 @@ ListView { } switch (containerIndex) { - case ContainerEnum.OpenVpn: { - OpenVpnConfigModel.updateModel(config) - PageController.goToPage(PageEnum.PageProtocolOpenVpnSettings) - break - } - case ContainerEnum.Xray: { - XrayConfigModel.updateModel(config) - PageController.goToPage(PageEnum.PageProtocolXraySettings) - break - } - - case ContainerEnum.WireGuard: { - WireGuardConfigModel.updateModel(config) - PageController.goToPage(PageEnum.PageProtocolWireGuardSettings) - break - } - case ContainerEnum.Awg: { - AwgConfigModel.updateModel(config) - PageController.goToPage(PageEnum.PageProtocolAwgSettings) - break - } case ContainerEnum.Ipsec: { ProtocolsModel.updateModel(config) PageController.goToPage(PageEnum.PageProtocolRaw) @@ -98,7 +77,7 @@ ListView { } } else { - ContainersModel.setCurrentlyProcessedContainerIndex(root.model.mapToSource(index)) + ContainersModel.setProcessedContainerIndex(root.model.mapToSource(index)) InstallController.setShouldCreateServer(false) PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings) } diff --git a/client/ui/qml/Pages2/PageProtocolAwgSettings.qml b/client/ui/qml/Pages2/PageProtocolAwgSettings.qml index 774217eea..29a7afdaf 100644 --- a/client/ui/qml/Pages2/PageProtocolAwgSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolAwgSettings.qml @@ -311,34 +311,6 @@ PageType { KeyNavigation.tab: saveRestartButton } - BasicButtonType { - Layout.topMargin: 24 - Layout.leftMargin: -8 - implicitHeight: 32 - - defaultColor: "transparent" - hoveredColor: Qt.rgba(1, 1, 1, 0.08) - pressedColor: Qt.rgba(1, 1, 1, 0.12) - textColor: "#EB5757" - - text: qsTr("Remove AmneziaWG") - - onClicked: { - var headerText = qsTr("Remove AmneziaWG from server?") - var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.") - var yesButtonText = qsTr("Continue") - var noButtonText = qsTr("Cancel") - - var yesButtonFunction = function() { - PageController.goToPage(PageEnum.PageDeinstalling) - InstallController.removeCurrentlyProcessedContainer() - } - var noButtonFunction = function() { - } - showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) - } - } - BasicButtonType { id: saveRestartButton diff --git a/client/ui/qml/Pages2/PageProtocolOpenVpnSettings.qml b/client/ui/qml/Pages2/PageProtocolOpenVpnSettings.qml index 6f8be12c0..dd3b5a0d7 100644 --- a/client/ui/qml/Pages2/PageProtocolOpenVpnSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolOpenVpnSettings.qml @@ -129,7 +129,6 @@ PageType { TextFieldWithHeaderType { id: portTextField - Layout.fillWidth: true Layout.topMargin: 40 @@ -366,37 +365,6 @@ PageType { } } - BasicButtonType { - Layout.topMargin: 24 - Layout.leftMargin: -8 - implicitHeight: 32 - - visible: ContainersModel.getCurrentlyProcessedContainerIndex() === ContainerEnum.OpenVpn - - defaultColor: "transparent" - hoveredColor: Qt.rgba(1, 1, 1, 0.08) - pressedColor: Qt.rgba(1, 1, 1, 0.12) - textColor: "#EB5757" - - text: qsTr("Remove OpenVPN") - - clickedFunc: function() { - var headerText = qsTr("Remove OpenVpn from server?") - var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.") - var yesButtonText = qsTr("Continue") - var noButtonText = qsTr("Cancel") - - var yesButtonFunction = function() { - PageController.goToPage(PageEnum.PageDeinstalling) - InstallController.removeCurrentlyProcessedContainer() - } - var noButtonFunction = function() { - } - - showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) - } - } - BasicButtonType { id: saveRestartButton diff --git a/client/ui/qml/Pages2/PageProtocolRaw.qml b/client/ui/qml/Pages2/PageProtocolRaw.qml index 4de3ffe85..0d8da97d6 100644 --- a/client/ui/qml/Pages2/PageProtocolRaw.qml +++ b/client/ui/qml/Pages2/PageProtocolRaw.qml @@ -35,7 +35,7 @@ PageType { Layout.leftMargin: 16 Layout.rightMargin: 16 - headerText: ContainersModel.getCurrentlyProcessedContainerName() + qsTr(" settings") + headerText: ContainersModel.getProcessedContainerName() + qsTr(" settings") } } @@ -177,18 +177,18 @@ PageType { visible: ServersModel.isProcessedServerHasWriteAccess() - text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName() + text: qsTr("Remove ") + ContainersModel.getProcessedContainerName() textColor: "#EB5757" clickedFunction: function() { - var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName()) + var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getProcessedContainerName()) var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.") var yesButtonText = qsTr("Continue") var noButtonText = qsTr("Cancel") var yesButtonFunction = function() { PageController.goToPage(PageEnum.PageDeinstalling) - InstallController.removeCurrentlyProcessedContainer() + InstallController.removeProcessedContainer() } var noButtonFunction = function() { } diff --git a/client/ui/qml/Pages2/PageProtocolShadowSocksSettings.qml b/client/ui/qml/Pages2/PageProtocolShadowSocksSettings.qml index f9447c780..4847036db 100644 --- a/client/ui/qml/Pages2/PageProtocolShadowSocksSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolShadowSocksSettings.qml @@ -86,6 +86,8 @@ PageType { Layout.fillWidth: true Layout.topMargin: 40 + enabled: isPortEditable + headerText: qsTr("Port") textFieldText: port textField.maximumLength: 5 @@ -105,6 +107,8 @@ PageType { Layout.fillWidth: true Layout.topMargin: 20 + enabled: isCipherEditable + descriptionText: qsTr("Cipher") headerText: qsTr("Cipher") @@ -148,6 +152,8 @@ PageType { Layout.topMargin: 24 Layout.bottomMargin: 24 + enabled: isPortEditable | isCipherEditable + text: qsTr("Save") clickedFunc: function() { diff --git a/client/ui/qml/Pages2/PageProtocolWireGuardSettings.qml b/client/ui/qml/Pages2/PageProtocolWireGuardSettings.qml index 40d8803a6..fda339407 100644 --- a/client/ui/qml/Pages2/PageProtocolWireGuardSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolWireGuardSettings.qml @@ -114,35 +114,6 @@ PageType { checkEmptyText: true } - BasicButtonType { - Layout.topMargin: 24 - Layout.leftMargin: -8 - implicitHeight: 32 - - defaultColor: "transparent" - hoveredColor: Qt.rgba(1, 1, 1, 0.08) - pressedColor: Qt.rgba(1, 1, 1, 0.12) - textColor: "#EB5757" - - text: qsTr("Remove WG") - - clickedFunc: function() { - var headerText = qsTr("Remove WG from server?") - var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.") - var yesButtonText = qsTr("Continue") - var noButtonText = qsTr("Cancel") - - var yesButtonFunction = function() { - PageController.goToPage(PageEnum.PageDeinstalling) - InstallController.removeCurrentlyProcessedContainer() - } - var noButtonFunction = function() { - } - - showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) - } - } - BasicButtonType { Layout.fillWidth: true Layout.topMargin: 24 @@ -163,9 +134,5 @@ PageType { } } } - - QuestionDrawer { - id: questionDrawer - } } } diff --git a/client/ui/qml/Pages2/PageProtocolXraySettings.qml b/client/ui/qml/Pages2/PageProtocolXraySettings.qml index 588a7f8b6..c47ff3104 100644 --- a/client/ui/qml/Pages2/PageProtocolXraySettings.qml +++ b/client/ui/qml/Pages2/PageProtocolXraySettings.qml @@ -98,43 +98,12 @@ PageType { } } - BasicButtonType { - Layout.topMargin: 24 - Layout.leftMargin: -8 - implicitHeight: 32 - - visible: ContainersModel.getCurrentlyProcessedContainerIndex() === ContainerEnum.Xray - - defaultColor: "transparent" - hoveredColor: Qt.rgba(1, 1, 1, 0.08) - pressedColor: Qt.rgba(1, 1, 1, 0.12) - textColor: "#EB5757" - - text: qsTr("Remove XRay") - - clickedFunc: function() { - var headerText = qsTr("Remove XRay from server?") - var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.") - var yesButtonText = qsTr("Continue") - var noButtonText = qsTr("Cancel") - - var yesButtonFunction = function() { - PageController.goToPage(PageEnum.PageDeinstalling) - InstallController.removeCurrentlyProcessedContainer() - } - var noButtonFunction = function() { - } - - showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) - } - } - BasicButtonType { Layout.fillWidth: true Layout.topMargin: 24 Layout.bottomMargin: 24 - text: qsTr("Save and Restart Amnezia") + text: qsTr("Save") onClicked: { forceActiveFocus() @@ -146,10 +115,6 @@ PageType { } } } - - QuestionDrawer { - id: questionDrawer - } } } diff --git a/client/ui/qml/Pages2/PageServiceDnsSettings.qml b/client/ui/qml/Pages2/PageServiceDnsSettings.qml index c24bdd422..eb3fb1f82 100644 --- a/client/ui/qml/Pages2/PageServiceDnsSettings.qml +++ b/client/ui/qml/Pages2/PageServiceDnsSettings.qml @@ -59,17 +59,17 @@ PageType { Layout.topMargin: 24 width: parent.width - text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName() + text: qsTr("Remove ") + ContainersModel.getProcessedContainerName() textColor: "#EB5757" clickedFunction: function() { - var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName()) + var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getProcessedContainerName()) var yesButtonText = qsTr("Continue") var noButtonText = qsTr("Cancel") var yesButtonFunction = function() { PageController.goToPage(PageEnum.PageDeinstalling) - InstallController.removeCurrentlyProcessedContainer() + InstallController.removeProcessedContainer() } var noButtonFunction = function() { } diff --git a/client/ui/qml/Pages2/PageServiceSftpSettings.qml b/client/ui/qml/Pages2/PageServiceSftpSettings.qml index 91ca35309..7b8feb3c9 100644 --- a/client/ui/qml/Pages2/PageServiceSftpSettings.qml +++ b/client/ui/qml/Pages2/PageServiceSftpSettings.qml @@ -254,7 +254,7 @@ PageType { var yesButtonFunction = function() { PageController.goToPage(PageEnum.PageDeinstalling) - InstallController.removeCurrentlyProcessedContainer() + InstallController.removeProcessedContainer() } var noButtonFunction = function() { } diff --git a/client/ui/qml/Pages2/PageServiceTorWebsiteSettings.qml b/client/ui/qml/Pages2/PageServiceTorWebsiteSettings.qml index 002e03109..9a4871fd3 100644 --- a/client/ui/qml/Pages2/PageServiceTorWebsiteSettings.qml +++ b/client/ui/qml/Pages2/PageServiceTorWebsiteSettings.qml @@ -66,7 +66,7 @@ PageType { text: qsTr("Website address") descriptionText: { - var containerIndex = ContainersModel.getCurrentlyProcessedContainerIndex() + var containerIndex = ContainersModel.getProcessedContainerIndex() var config = ContainersModel.getContainerConfig(containerIndex) return config[ContainerProps.containerTypeToString(containerIndex)]["site"] } @@ -132,7 +132,7 @@ PageType { var yesButtonFunction = function() { PageController.goToPage(PageEnum.PageDeinstalling) - InstallController.removeCurrentlyProcessedContainer() + InstallController.removeProcessedContainer() } var noButtonFunction = function() { } diff --git a/client/ui/qml/Pages2/PageSettingsServerData.qml b/client/ui/qml/Pages2/PageSettingsServerData.qml index b54cd7e72..96bda96ab 100644 --- a/client/ui/qml/Pages2/PageSettingsServerData.qml +++ b/client/ui/qml/Pages2/PageSettingsServerData.qml @@ -47,7 +47,7 @@ PageType { PageController.showNotificationMessage(finishedMessage) } - function onRemoveCurrentlyProcessedContainerFinished(finishedMessage) { + function onRemoveProcessedContainerFinished(finishedMessage) { PageController.closePage() // close deInstalling page PageController.closePage() // close page with remove button PageController.showNotificationMessage(finishedMessage) @@ -84,35 +84,6 @@ PageType { property bool isServerWithWriteAccess: ServersModel.isProcessedServerHasWriteAccess() - LabelWithButtonType { - visible: content.isServerWithWriteAccess - Layout.fillWidth: true - - text: qsTr("Clear Amnezia cache") - descriptionText: qsTr("May be needed when changing other settings") - - clickedFunction: function() { - var headerText = qsTr("Clear cached profiles?") - var descriptionText = qsTr("") - var yesButtonText = qsTr("Continue") - var noButtonText = qsTr("Cancel") - - var yesButtonFunction = function() { - PageController.showBusyIndicator(true) - SettingsController.clearCachedProfiles() - PageController.showBusyIndicator(false) - } - var noButtonFunction = function() { - } - - showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) - } - } - - DividerType { - visible: content.isServerWithWriteAccess - } - LabelWithButtonType { visible: content.isServerWithWriteAccess Layout.fillWidth: true @@ -238,7 +209,7 @@ PageType { var yesButtonFunction = function() { PageController.showBusyIndicator(true) - ApiController.clearApiConfig() + InstallController.removeApiConfig() PageController.showBusyIndicator(false) } var noButtonFunction = function() { diff --git a/client/ui/qml/Pages2/PageSettingsServerProtocol.qml b/client/ui/qml/Pages2/PageSettingsServerProtocol.qml index 4d2000049..aee89cd5f 100644 --- a/client/ui/qml/Pages2/PageSettingsServerProtocol.qml +++ b/client/ui/qml/Pages2/PageSettingsServerProtocol.qml @@ -34,113 +34,141 @@ PageType { Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 + Layout.bottomMargin: 32 - headerText: ContainersModel.getCurrentlyProcessedContainerName() + qsTr(" settings") + headerText: ContainersModel.getProcessedContainerName() + qsTr(" settings") } - } - FlickableType { - id: fl - anchors.top: header.bottom - anchors.left: parent.left - anchors.right: parent.right - contentHeight: content.height - - Column { - id: content - - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.topMargin: 32 - - ListView { - id: protocols - width: parent.width - height: protocols.contentItem.height - clip: true - interactive: false - model: ProtocolsModel - - delegate: Item { - implicitWidth: protocols.width - implicitHeight: delegateContent.implicitHeight - - ColumnLayout { - id: delegateContent - - anchors.fill: parent - - LabelWithButtonType { - id: button - - Layout.fillWidth: true - - text: protocolName - rightImageSource: "qrc:/images/controls/chevron-right.svg" - - clickedFunction: function() { - switch (protocolIndex) { - case ProtocolEnum.OpenVpn: OpenVpnConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.ShadowSocks: ShadowSocksConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.Cloak: CloakConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.Xray: XrayConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.WireGuard: WireGuardConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.Ipsec: Ikev2ConfigModel.updateModel(ProtocolsModel.getConfig()); break; - } - PageController.goToPage(protocolPage); - } + ListView { + id: protocols + Layout.fillWidth: true + height: protocols.contentItem.height + clip: true + interactive: true + model: ProtocolsModel + + delegate: Item { + implicitWidth: protocols.width + implicitHeight: delegateContent.implicitHeight - MouseArea { - anchors.fill: button - cursorShape: Qt.PointingHandCursor - enabled: false + ColumnLayout { + id: delegateContent + + anchors.fill: parent + + LabelWithButtonType { + id: button + + Layout.fillWidth: true + + text: protocolName + rightImageSource: "qrc:/images/controls/chevron-right.svg" + + clickedFunction: function() { + switch (protocolIndex) { + case ProtocolEnum.OpenVpn: OpenVpnConfigModel.updateModel(ProtocolsModel.getConfig()); break; + case ProtocolEnum.ShadowSocks: ShadowSocksConfigModel.updateModel(ProtocolsModel.getConfig()); break; + case ProtocolEnum.Cloak: CloakConfigModel.updateModel(ProtocolsModel.getConfig()); break; + case ProtocolEnum.WireGuard: WireGuardConfigModel.updateModel(ProtocolsModel.getConfig()); break; + case ProtocolEnum.Awg: AwgConfigModel.updateModel(ProtocolsModel.getConfig()); break; + case ProtocolEnum.Xray: XrayConfigModel.updateModel(ProtocolsModel.getConfig()); break; + case ProtocolEnum.Ipsec: Ikev2ConfigModel.updateModel(ProtocolsModel.getConfig()); break; } + PageController.goToPage(protocolPage); } - DividerType {} + MouseArea { + anchors.fill: button + cursorShape: Qt.PointingHandCursor + enabled: false + } } + + DividerType {} } } + } - LabelWithButtonType { - id: removeButton - - width: parent.width + LabelWithButtonType { + id: clearCacheButton - visible: ServersModel.isProcessedServerHasWriteAccess() + Layout.fillWidth: true - text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName() - textColor: "#EB5757" + visible: ServersModel.isProcessedServerHasWriteAccess() - clickedFunction: function() { - var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName()) - var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.") - var yesButtonText = qsTr("Continue") - var noButtonText = qsTr("Cancel") + text: qsTr("Clear %1 profile").arg(ContainersModel.getProcessedContainerName()) - var yesButtonFunction = function() { - PageController.goToPage(PageEnum.PageDeinstalling) - InstallController.removeCurrentlyProcessedContainer() - } - var noButtonFunction = function() { - } + clickedFunction: function() { + var headerText = qsTr("Clear %1 profile?").arg(ContainersModel.getProcessedContainerName()) + var descriptionText = qsTr("") + var yesButtonText = qsTr("Continue") + var noButtonText = qsTr("Cancel") - showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) + var yesButtonFunction = function() { + PageController.showBusyIndicator(true) + InstallController.clearCachedProfile() + PageController.showBusyIndicator(false) } + var noButtonFunction = function() { + } + + showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) + } - MouseArea { - anchors.fill: removeButton - cursorShape: Qt.PointingHandCursor - enabled: false + MouseArea { + anchors.fill: clearCacheButton + cursorShape: Qt.PointingHandCursor + enabled: false + } + } + + DividerType { + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + + visible: ServersModel.isProcessedServerHasWriteAccess() + } + + LabelWithButtonType { + id: removeButton + + Layout.fillWidth: true + + visible: ServersModel.isProcessedServerHasWriteAccess() + + text: qsTr("Remove ") + ContainersModel.getProcessedContainerName() + textColor: "#EB5757" + + clickedFunction: function() { + var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getProcessedContainerName()) + var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.") + var yesButtonText = qsTr("Continue") + var noButtonText = qsTr("Cancel") + + var yesButtonFunction = function() { + PageController.goToPage(PageEnum.PageDeinstalling) + InstallController.removeProcessedContainer() + } + var noButtonFunction = function() { } + + showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) } - DividerType {} + MouseArea { + anchors.fill: removeButton + cursorShape: Qt.PointingHandCursor + enabled: false + } } - } - QuestionDrawer { - id: questionDrawer + DividerType { + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + + visible: ServersModel.isProcessedServerHasWriteAccess() + } } } diff --git a/client/ui/qml/Pages2/PageSetupWizardCredentials.qml b/client/ui/qml/Pages2/PageSetupWizardCredentials.qml index d1ba348e0..6e112c469 100644 --- a/client/ui/qml/Pages2/PageSetupWizardCredentials.qml +++ b/client/ui/qml/Pages2/PageSetupWizardCredentials.qml @@ -114,7 +114,7 @@ PageType { } InstallController.setShouldCreateServer(true) - InstallController.setCurrentlyInstalledServerCredentials(hostname.textField.text, username.textField.text, secretData.textField.text) + InstallController.setProcessedServerCredentials(hostname.textField.text, username.textField.text, secretData.textField.text) PageController.showBusyIndicator(true) var isConnectionOpened = InstallController.checkSshConnection() diff --git a/client/ui/qml/Pages2/PageSetupWizardEasy.qml b/client/ui/qml/Pages2/PageSetupWizardEasy.qml index 10fdadf9e..aba71560b 100644 --- a/client/ui/qml/Pages2/PageSetupWizardEasy.qml +++ b/client/ui/qml/Pages2/PageSetupWizardEasy.qml @@ -159,7 +159,7 @@ PageType { clickedFunc: function() { if (root.isEasySetup) { - ContainersModel.setCurrentlyProcessedContainerIndex(containers.dockerContainer) + ContainersModel.setProcessedContainerIndex(containers.dockerContainer) PageController.goToPage(PageEnum.PageSetupWizardInstalling) InstallController.install(containers.dockerContainer, containers.containerDefaultPort, diff --git a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml index 6b6e79c6c..87b0a4331 100644 --- a/client/ui/qml/Pages2/PageSetupWizardInstalling.qml +++ b/client/ui/qml/Pages2/PageSetupWizardInstalling.qml @@ -26,7 +26,7 @@ PageType { function onInstallContainerFinished(finishedMessage, isServiceInstall) { if (!ConnectionController.isConnected && !isServiceInstall) { - ServersModel.setDefaultContainer(ServersModel.processedIndex, ContainersModel.getCurrentlyProcessedContainerIndex()) + ServersModel.setDefaultContainer(ServersModel.processedIndex, ContainersModel.getProcessedContainerIndex()) } PageController.closePage() // close installing page diff --git a/client/ui/qml/Pages2/PageSetupWizardProtocols.qml b/client/ui/qml/Pages2/PageSetupWizardProtocols.qml index 71b33eb0a..c684db21b 100644 --- a/client/ui/qml/Pages2/PageSetupWizardProtocols.qml +++ b/client/ui/qml/Pages2/PageSetupWizardProtocols.qml @@ -104,7 +104,7 @@ PageType { rightImageSource: "qrc:/images/controls/chevron-right.svg" clickedFunction: function() { - ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(index)) + ContainersModel.setProcessedContainerIndex(proxyContainersModel.mapToSource(index)) PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings) } } diff --git a/client/ui/qml/Pages2/PageShare.qml b/client/ui/qml/Pages2/PageShare.qml index 79b48d44e..9907aa559 100644 --- a/client/ui/qml/Pages2/PageShare.qml +++ b/client/ui/qml/Pages2/PageShare.qml @@ -12,6 +12,7 @@ import "./" import "../Controls2" import "../Controls2/TextTypes" import "../Components" +import "../Config" PageType { id: root @@ -32,7 +33,7 @@ PageType { onRevokeConfig: function(index) { PageController.showBusyIndicator(true) ExportController.revokeConfig(index, - ContainersModel.getCurrentlyProcessedContainerIndex(), + ContainersModel.getProcessedContainerIndex(), ServersModel.getProcessedServerCredentials()) PageController.showBusyIndicator(false) PageController.showNotificationMessage(qsTr("Config revoked")) @@ -258,7 +259,7 @@ PageType { onClicked: { accessTypeSelector.currentIndex = 1 PageController.showBusyIndicator(true) - ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(), + ExportController.updateClientManagementModel(ContainersModel.getProcessedContainerIndex(), ServersModel.getProcessedServerCredentials()) PageController.showBusyIndicator(false) } @@ -418,13 +419,13 @@ PageType { protocolSelector.text = selectedText - ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(currentIndex)) + ContainersModel.setProcessedContainerIndex(proxyContainersModel.mapToSource(currentIndex)) fillConnectionTypeModel() if (accessTypeSelector.currentIndex === 1) { PageController.showBusyIndicator(true) - ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(), + ExportController.updateClientManagementModel(ContainersModel.getProcessedContainerIndex(), ServersModel.getProcessedServerCredentials()) PageController.showBusyIndicator(false) } @@ -696,7 +697,7 @@ PageType { PageController.showBusyIndicator(true) ExportController.renameClient(index, clientNameEditor.textFieldText, - ContainersModel.getCurrentlyProcessedContainerIndex(), + ContainersModel.getProcessedContainerIndex(), ServersModel.getProcessedServerCredentials()) PageController.showBusyIndicator(false) clientNameEditDrawer.close() diff --git a/client/ui/qml/Pages2/PageStart.qml b/client/ui/qml/Pages2/PageStart.qml index 8621f3def..0ad7b1127 100644 --- a/client/ui/qml/Pages2/PageStart.qml +++ b/client/ui/qml/Pages2/PageStart.qml @@ -108,6 +108,10 @@ PageType { PageController.showNotificationMessage(message) PageController.closePage() } + + function onCachedProfileCleared(message) { + PageController.showNotificationMessage(message) + } } Connections { diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index b81840534..a416eaccb 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include "core/controllers/serverController.h" @@ -30,9 +29,8 @@ #include "core/networkUtilities.h" #include "vpnconnection.h" -VpnConnection::VpnConnection(std::shared_ptr settings, std::shared_ptr configurator, - QObject *parent) - : QObject(parent), m_settings(settings), m_configurator(configurator), m_checkTimer(new QTimer(this)) +VpnConnection::VpnConnection(std::shared_ptr settings, QObject *parent) + : QObject(parent), m_settings(settings), m_checkTimer(new QTimer(this)) { m_checkTimer.setInterval(1000); #ifdef Q_OS_IOS @@ -212,109 +210,8 @@ ErrorCode VpnConnection::lastError() const return m_vpnProtocol.data()->lastError(); } -QMap VpnConnection::getLastVpnConfig(const QJsonObject &containerConfig) -{ - QMap configs; - for (Proto proto : ProtocolProps::allProtocols()) { - - QString cfg = containerConfig.value(ProtocolProps::protoToString(proto)) - .toObject() - .value(config_key::last_config) - .toString(); - - if (!cfg.isEmpty()) - configs.insert(proto, cfg); - } - return configs; -} - -QString VpnConnection::createVpnConfigurationForProto(int serverIndex, const ServerCredentials &credentials, - DockerContainer container, const QJsonObject &containerConfig, - Proto proto, ErrorCode *errorCode) -{ - QMap lastVpnConfig = getLastVpnConfig(containerConfig); - - QString configData; - if (lastVpnConfig.contains(proto)) { - configData = lastVpnConfig.value(proto); - configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData); - } else { - QString clientId; - configData = m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, proto, clientId, errorCode); - - if (errorCode && *errorCode) { - return ""; - } - - QString configDataBeforeLocalProcessing = configData; - - configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData); - - if (serverIndex >= 0) { - qDebug() << "VpnConnection::createVpnConfiguration: saving config for server #" << serverIndex << container; - QJsonObject protoObject = m_settings->protocolConfig(serverIndex, container, proto); - protoObject.insert(config_key::last_config, configDataBeforeLocalProcessing); - m_settings->setProtocolConfig(serverIndex, container, proto, protoObject); - } - - if ((container != DockerContainer::Cloak && container != DockerContainer::ShadowSocks) || - ((container == DockerContainer::Cloak || container == DockerContainer::ShadowSocks) && proto == Proto::OpenVpn)) { - QEventLoop wait; - emit m_configurator->newVpnConfigCreated(clientId, QString("Admin [%1]").arg(QSysInfo::prettyProductName()), container, credentials); - QObject::connect(m_configurator.get(), &VpnConfigurator::clientModelUpdated, &wait, &QEventLoop::quit); - wait.exec(); - } - } - - return configData; -} - -QJsonObject VpnConnection::createVpnConfiguration(int serverIndex, const ServerCredentials &credentials, - DockerContainer container, const QJsonObject &containerConfig, - ErrorCode *errorCode) -{ - QJsonObject vpnConfiguration; - vpnConfiguration[config_key::serverIndex] = serverIndex; - - for (ProtocolEnumNS::Proto proto : ContainerProps::protocolsForContainer(container)) { - auto s = m_settings->server(serverIndex); - if (m_settings->server(serverIndex).value(config_key::configVersion).toInt() && - container == DockerContainer::Cloak && proto == ProtocolEnumNS::Proto::ShadowSocks) { - continue; - } - - QJsonObject vpnConfigData = - QJsonDocument::fromJson(createVpnConfigurationForProto(serverIndex, credentials, container, - containerConfig, proto, errorCode).toUtf8()).object(); - - if (errorCode && *errorCode) { - return {}; - } - - vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData); - } - - Proto proto = ContainerProps::defaultProtocol(container); - vpnConfiguration[config_key::vpnproto] = ProtocolProps::protoToString(proto); - - auto dns = m_configurator->getDnsForConfig(serverIndex); - - vpnConfiguration[config_key::dns1] = dns.first; - vpnConfiguration[config_key::dns2] = dns.second; - - const QJsonObject &server = m_settings->server(serverIndex); - vpnConfiguration[config_key::hostName] = server.value(config_key::hostName).toString(); - vpnConfiguration[config_key::description] = server.value(config_key::description).toString(); - - vpnConfiguration[config_key::configVersion] = server.value(config_key::configVersion).toInt(); - // TODO: try to get hostName, port, description for 3rd party configs - // vpnConfiguration[config_key::port] = ...; - - return vpnConfiguration; -} - void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig) + const QJsonObject &vpnConfiguration) { qDebug() << QString("ConnectToVpn, Server index is %1, container is %2, route mode is") .arg(serverIndex) @@ -346,15 +243,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede } #endif - ErrorCode e = ErrorCode::NoError; - - m_vpnConfiguration = createVpnConfiguration(serverIndex, credentials, container, containerConfig, &e); - - if (e) { - emit connectionStateChanged(Vpn::ConnectionState::Error); - return; - } - + m_vpnConfiguration = vpnConfiguration; appendSplitTunnelingConfig(); #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) @@ -378,8 +267,8 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede createProtocolConnections(); - e = m_vpnProtocol.data()->start(); - if (e) + ErrorCode errorCode = m_vpnProtocol.data()->start(); + if (errorCode != ErrorCode::NoError) emit connectionStateChanged(Vpn::ConnectionState::Error); } diff --git a/client/vpnconnection.h b/client/vpnconnection.h index 3cc670d56..33c1b67a9 100644 --- a/client/vpnconnection.h +++ b/client/vpnconnection.h @@ -11,7 +11,6 @@ #include "core/defs.h" #include "settings.h" - #ifdef AMNEZIA_DESKTOP #include "core/ipcclient.h" #endif @@ -20,9 +19,6 @@ #include "protocols/android_vpnprotocol.h" #endif -class VpnConfigurator; -class ServerController; - using namespace amnezia; class VpnConnection : public QObject @@ -30,24 +26,13 @@ class VpnConnection : public QObject Q_OBJECT public: - explicit VpnConnection(std::shared_ptr settings, - std::shared_ptr configurator, QObject* parent = nullptr); + explicit VpnConnection(std::shared_ptr settings, QObject* parent = nullptr); ~VpnConnection() override; static QString bytesPerSecToText(quint64 bytes); ErrorCode lastError() const; - static QMap getLastVpnConfig(const QJsonObject &containerConfig); - QString createVpnConfigurationForProto(int serverIndex, - const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, Proto proto, - ErrorCode *errorCode = nullptr); - - QJsonObject createVpnConfiguration(int serverIndex, - const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); - - bool isConnected() const; bool isDisconnected() const; @@ -63,7 +48,7 @@ class VpnConnection : public QObject public slots: void connectToVpn(int serverIndex, - const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig); + const ServerCredentials &credentials, DockerContainer container, const QJsonObject &vpnConfiguration); void disconnectFromVpn(); @@ -88,8 +73,6 @@ protected slots: private: std::shared_ptr m_settings; - std::shared_ptr m_configurator; - QJsonObject m_vpnConfiguration; QJsonObject m_routeMode; QString m_remoteAddress;