From 2d22a74b229f322f2489efd097e8793bf47e7300 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Fri, 20 Jun 2025 22:18:47 +0800 Subject: [PATCH] refactoring: added classes for working with server configs --- CMakeLists.txt | 2 +- client/cmake/sources.cmake | 18 ++ client/core/api/apiDefs.h | 5 - client/core/api/apiUtils.cpp | 12 +- client/core/api/apiUtils.h | 2 +- client/core/controllers/coreController.cpp | 3 - client/core/defs.h | 7 + .../models/containers/containerConfig.cpp | 5 + .../core/models/containers/containerConfig.h | 19 ++ .../models/protocols/awgProtocolConfig.cpp | 198 ++++++++++++++++++ .../core/models/protocols/awgProtocolConfig.h | 65 ++++++ .../models/protocols/cloakProtocolConfig.cpp | 43 ++++ .../models/protocols/cloakProtocolConfig.h | 35 ++++ .../protocols/openvpnProtocolConfig.cpp | 83 ++++++++ .../models/protocols/openvpnProtocolConfig.h | 46 ++++ .../core/models/protocols/protocolConfig.cpp | 12 ++ client/core/models/protocols/protocolConfig.h | 16 ++ .../protocols/shadowsocksProtocolConfig.cpp | 39 ++++ .../protocols/shadowsocksProtocolConfig.h | 34 +++ .../protocols/wireguardProtocolConfig.cpp | 120 +++++++++++ .../protocols/wireguardProtocolConfig.h | 58 +++++ .../models/protocols/xrayProtocolConfig.cpp | 43 ++++ .../models/protocols/xrayProtocolConfig.h | 35 ++++ .../core/models/servers/apiV1ServerConfig.cpp | 30 +++ .../core/models/servers/apiV1ServerConfig.h | 17 ++ .../core/models/servers/apiV2ServerConfig.cpp | 125 +++++++++++ .../core/models/servers/apiV2ServerConfig.h | 54 +++++ .../models/servers/selfHostedServerConfig.cpp | 48 +++++ .../models/servers/selfHostedServerConfig.h | 19 ++ client/core/models/servers/serverConfig.cpp | 145 +++++++++++++ client/core/models/servers/serverConfig.h | 32 +++ .../controllers/api/apiConfigsController.cpp | 10 +- client/ui/models/servers_model.cpp | 144 +++++++------ client/ui/models/servers_model.h | 8 +- 34 files changed, 1441 insertions(+), 91 deletions(-) create mode 100644 client/core/models/containers/containerConfig.cpp create mode 100644 client/core/models/containers/containerConfig.h create mode 100644 client/core/models/protocols/awgProtocolConfig.cpp create mode 100644 client/core/models/protocols/awgProtocolConfig.h create mode 100644 client/core/models/protocols/cloakProtocolConfig.cpp create mode 100644 client/core/models/protocols/cloakProtocolConfig.h create mode 100644 client/core/models/protocols/openvpnProtocolConfig.cpp create mode 100644 client/core/models/protocols/openvpnProtocolConfig.h create mode 100644 client/core/models/protocols/protocolConfig.cpp create mode 100644 client/core/models/protocols/protocolConfig.h create mode 100644 client/core/models/protocols/shadowsocksProtocolConfig.cpp create mode 100644 client/core/models/protocols/shadowsocksProtocolConfig.h create mode 100644 client/core/models/protocols/wireguardProtocolConfig.cpp create mode 100644 client/core/models/protocols/wireguardProtocolConfig.h create mode 100644 client/core/models/protocols/xrayProtocolConfig.cpp create mode 100644 client/core/models/protocols/xrayProtocolConfig.h create mode 100644 client/core/models/servers/apiV1ServerConfig.cpp create mode 100644 client/core/models/servers/apiV1ServerConfig.h create mode 100644 client/core/models/servers/apiV2ServerConfig.cpp create mode 100644 client/core/models/servers/apiV2ServerConfig.h create mode 100644 client/core/models/servers/selfHostedServerConfig.cpp create mode 100644 client/core/models/servers/selfHostedServerConfig.h create mode 100644 client/core/models/servers/serverConfig.cpp create mode 100644 client/core/models/servers/serverConfig.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 424dcf3a..a759bd80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") endif() set(QT_BUILD_TOOLS_WHEN_CROSS_COMPILING ON) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(APPLE AND NOT IOS) diff --git a/client/cmake/sources.cmake b/client/cmake/sources.cmake index c3af531a..fe8e37e3 100644 --- a/client/cmake/sources.cmake +++ b/client/cmake/sources.cmake @@ -116,6 +116,7 @@ file(GLOB UI_MODELS_H CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/ui/models/services/*.h ${CLIENT_ROOT_DIR}/ui/models/api/*.h ) + file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/ui/models/*.cpp ${CLIENT_ROOT_DIR}/ui/models/protocols/*.cpp @@ -127,17 +128,33 @@ file(GLOB UI_CONTROLLERS_H CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/ui/controllers/*.h ${CLIENT_ROOT_DIR}/ui/controllers/api/*.h ) + file(GLOB UI_CONTROLLERS_CPP CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/ui/controllers/*.cpp ${CLIENT_ROOT_DIR}/ui/controllers/api/*.cpp ) +file(GLOB CORE_MODELS_H CONFIGURE_DEPENDS + ${CLIENT_ROOT_DIR}/core/models/*.h + ${CLIENT_ROOT_DIR}/core/models/containers/*.h + ${CLIENT_ROOT_DIR}/core/models/protocols/*.h + ${CLIENT_ROOT_DIR}/core/models/servers/*.h +) + +file(GLOB CORE_MODELS_CPP CONFIGURE_DEPENDS + ${CLIENT_ROOT_DIR}/core/models/*.cpp + ${CLIENT_ROOT_DIR}/core/models/containers/*.cpp + ${CLIENT_ROOT_DIR}/core/models/protocols/*.cpp + ${CLIENT_ROOT_DIR}/core/models/servers/*.cpp +) + set(HEADERS ${HEADERS} ${COMMON_FILES_H} ${PAGE_LOGIC_H} ${CONFIGURATORS_H} ${UI_MODELS_H} ${UI_CONTROLLERS_H} + ${CORE_MODELS_H} ) set(SOURCES ${SOURCES} ${COMMON_FILES_CPP} @@ -145,6 +162,7 @@ set(SOURCES ${SOURCES} ${CONFIGURATORS_CPP} ${UI_MODELS_CPP} ${UI_CONTROLLERS_CPP} + ${CORE_MODELS_CPP} ) if(WIN32) diff --git a/client/core/api/apiDefs.h b/client/core/api/apiDefs.h index 4588ef04..a7b134f0 100644 --- a/client/core/api/apiDefs.h +++ b/client/core/api/apiDefs.h @@ -14,11 +14,6 @@ namespace apiDefs ExternalPremium }; - enum ConfigSource { - Telegram = 1, - AmneziaGateway - }; - namespace key { constexpr QLatin1String configVersion("config_version"); diff --git a/client/core/api/apiUtils.cpp b/client/core/api/apiUtils.cpp index 7f3e6db3..8e5ac28c 100644 --- a/client/core/api/apiUtils.cpp +++ b/client/core/api/apiUtils.cpp @@ -32,8 +32,8 @@ bool apiUtils::isServerFromApi(const QJsonObject &serverConfigObject) { auto configVersion = serverConfigObject.value(apiDefs::key::configVersion).toInt(); switch (configVersion) { - case apiDefs::ConfigSource::Telegram: return true; - case apiDefs::ConfigSource::AmneziaGateway: return true; + case amnezia::ServerConfigType::ApiV1: return true; + case amnezia::ServerConfigType::ApiV2: return true; default: return false; } } @@ -43,7 +43,7 @@ apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObjec auto configVersion = serverConfigObject.value(apiDefs::key::configVersion).toInt(); switch (configVersion) { - case apiDefs::ConfigSource::Telegram: { + case amnezia::ServerConfigType::ApiV1: { constexpr QLatin1String freeV2Endpoint(FREE_V2_ENDPOINT); constexpr QLatin1String premiumV1Endpoint(PREM_V1_ENDPOINT); @@ -55,7 +55,7 @@ apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObjec return apiDefs::ConfigType::AmneziaFreeV2; } }; - case apiDefs::ConfigSource::AmneziaGateway: { + case amnezia::ServerConfigType::ApiV2: { constexpr QLatin1String servicePremium("amnezia-premium"); constexpr QLatin1String serviceFree("amnezia-free"); constexpr QLatin1String serviceExternalPremium("external-premium"); @@ -77,9 +77,9 @@ apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObjec }; } -apiDefs::ConfigSource apiUtils::getConfigSource(const QJsonObject &serverConfigObject) +amnezia::ServerConfigType apiUtils::getConfigSource(const QJsonObject &serverConfigObject) { - return static_cast(serverConfigObject.value(apiDefs::key::configVersion).toInt()); + return static_cast(serverConfigObject.value(apiDefs::key::configVersion).toInt()); } amnezia::ErrorCode apiUtils::checkNetworkReplyErrors(const QList &sslErrors, QNetworkReply *reply) diff --git a/client/core/api/apiUtils.h b/client/core/api/apiUtils.h index 45eaf2de..9e6fdbbe 100644 --- a/client/core/api/apiUtils.h +++ b/client/core/api/apiUtils.h @@ -16,7 +16,7 @@ namespace apiUtils bool isPremiumServer(const QJsonObject &serverConfigObject); apiDefs::ConfigType getConfigType(const QJsonObject &serverConfigObject); - apiDefs::ConfigSource getConfigSource(const QJsonObject &serverConfigObject); + amnezia::ServerConfigType getConfigSource(const QJsonObject &serverConfigObject); amnezia::ErrorCode checkNetworkReplyErrors(const QList &sslErrors, QNetworkReply *reply); diff --git a/client/core/controllers/coreController.cpp b/client/core/controllers/coreController.cpp index 0e72ef1a..a4dbc6d6 100644 --- a/client/core/controllers/coreController.cpp +++ b/client/core/controllers/coreController.cpp @@ -299,13 +299,10 @@ void CoreController::setQmlRoot() void CoreController::initApiCountryModelUpdateHandler() { - // TODO connect(m_serversModel.get(), &ServersModel::updateApiCountryModel, this, [this]() { m_apiCountryModel->updateModel(m_serversModel->getProcessedServerData("apiAvailableCountries").toJsonArray(), m_serversModel->getProcessedServerData("apiServerCountryCode").toString()); }); - connect(m_serversModel.get(), &ServersModel::updateApiServicesModel, this, - [this]() { m_apiServicesModel->updateModel(m_serversModel->getProcessedServerData("apiConfig").toJsonObject()); }); } void CoreController::initContainerModelUpdateHandler() diff --git a/client/core/defs.h b/client/core/defs.h index df6a1342..3d64932a 100644 --- a/client/core/defs.h +++ b/client/core/defs.h @@ -19,6 +19,13 @@ namespace amnezia } }; + enum ServerConfigType + { + SelfHosted, + ApiV1, + ApiV2 + }; + struct InstalledAppInfo { QString appName; QString packageName; diff --git a/client/core/models/containers/containerConfig.cpp b/client/core/models/containers/containerConfig.cpp new file mode 100644 index 00000000..119ff2b6 --- /dev/null +++ b/client/core/models/containers/containerConfig.cpp @@ -0,0 +1,5 @@ +#include "containerConfig.h" + +ContainerConfig::ContainerConfig() +{ +} diff --git a/client/core/models/containers/containerConfig.h b/client/core/models/containers/containerConfig.h new file mode 100644 index 00000000..7207d028 --- /dev/null +++ b/client/core/models/containers/containerConfig.h @@ -0,0 +1,19 @@ +#ifndef CONTAINERCONFIG_H +#define CONTAINERCONFIG_H + +#include +#include +#include + +#include "core/models/protocols/protocolConfig.h" + +class ContainerConfig +{ +public: + ContainerConfig(); + + QString containerName; + QMap> protocolConfigs; +}; + +#endif // CONTAINERCONFIG_H diff --git a/client/core/models/protocols/awgProtocolConfig.cpp b/client/core/models/protocols/awgProtocolConfig.cpp new file mode 100644 index 00000000..f77c0385 --- /dev/null +++ b/client/core/models/protocols/awgProtocolConfig.cpp @@ -0,0 +1,198 @@ +#include "awgProtocolConfig.h" + +#include +#include + +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +AwgProtocolConfig::AwgProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); + serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(); + + serverProtocolConfig.awgData.junkPacketCount = protocolConfigObject.value(config_key::junkPacketCount).toString(); + serverProtocolConfig.awgData.junkPacketMinSize = protocolConfigObject.value(config_key::junkPacketMinSize).toString(); + serverProtocolConfig.awgData.junkPacketMaxSize = protocolConfigObject.value(config_key::junkPacketMaxSize).toString(); + serverProtocolConfig.awgData.initPacketJunkSize = protocolConfigObject.value(config_key::initPacketJunkSize).toString(); + serverProtocolConfig.awgData.responsePacketJunkSize = protocolConfigObject.value(config_key::responsePacketJunkSize).toString(); + serverProtocolConfig.awgData.initPacketMagicHeader = protocolConfigObject.value(config_key::initPacketMagicHeader).toString(); + serverProtocolConfig.awgData.responsePacketMagicHeader = protocolConfigObject.value(config_key::responsePacketMagicHeader).toString(); + serverProtocolConfig.awgData.underloadPacketMagicHeader = protocolConfigObject.value(config_key::underloadPacketMagicHeader).toString(); + serverProtocolConfig.awgData.transportPacketMagicHeader = protocolConfigObject.value(config_key::transportPacketMagicHeader).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + + clientProtocolConfig.awgData.junkPacketCount = clientProtocolConfigObject.value(config_key::junkPacketCount).toString(); + clientProtocolConfig.awgData.junkPacketMinSize = clientProtocolConfigObject.value(config_key::junkPacketMinSize).toString(); + clientProtocolConfig.awgData.junkPacketMaxSize = clientProtocolConfigObject.value(config_key::junkPacketMaxSize).toString(); + clientProtocolConfig.awgData.initPacketJunkSize = clientProtocolConfigObject.value(config_key::initPacketJunkSize).toString(); + clientProtocolConfig.awgData.responsePacketJunkSize = clientProtocolConfigObject.value(config_key::responsePacketJunkSize).toString(); + clientProtocolConfig.awgData.initPacketMagicHeader = clientProtocolConfigObject.value(config_key::initPacketMagicHeader).toString(); + clientProtocolConfig.awgData.responsePacketMagicHeader = + clientProtocolConfigObject.value(config_key::responsePacketMagicHeader).toString(); + clientProtocolConfig.awgData.underloadPacketMagicHeader = + clientProtocolConfigObject.value(config_key::underloadPacketMagicHeader).toString(); + clientProtocolConfig.awgData.transportPacketMagicHeader = + clientProtocolConfigObject.value(config_key::transportPacketMagicHeader).toString(); + + clientProtocolConfig.clientId = clientProtocolConfigObject.value(config_key::clientId).toString(); + + clientProtocolConfig.wireGuardData.clientIp = clientProtocolConfigObject.value(config_key::client_ip).toString(); + clientProtocolConfig.wireGuardData.clientPrivateKey = clientProtocolConfigObject.value(config_key::client_priv_key).toString(); + clientProtocolConfig.wireGuardData.clientPublicKey = clientProtocolConfigObject.value(config_key::client_pub_key).toString(); + clientProtocolConfig.wireGuardData.persistentKeepAlive = + clientProtocolConfigObject.value(config_key::persistent_keep_alive).toString(); + clientProtocolConfig.wireGuardData.pskKey = clientProtocolConfigObject.value(config_key::psk_key).toString(); + clientProtocolConfig.wireGuardData.serverPubKey = clientProtocolConfigObject.value(config_key::server_pub_key).toString(); + clientProtocolConfig.wireGuardData.mtu = clientProtocolConfigObject.value(config_key::mtu).toString(); + + clientProtocolConfig.hostname = clientProtocolConfigObject.value(config_key::hostName).toString(); + clientProtocolConfig.port = clientProtocolConfigObject.value(config_key::port).toInt(0); + + clientProtocolConfig.nativeConfig = clientProtocolConfigObject.value(config_key::config).toString(); + + if (clientProtocolConfigObject.contains(config_key::allowed_ips) + && clientProtocolConfigObject.value(config_key::allowed_ips).isArray()) { + auto allowedIpsArray = clientProtocolConfigObject.value(config_key::allowed_ips).toArray(); + for (const auto &ip : allowedIpsArray) { + clientProtocolConfig.wireGuardData.allowedIps.append(ip.toString()); + } + } + } +} + +QJsonObject AwgProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.transportProto.isEmpty()) { + json[config_key::transport_proto] = serverProtocolConfig.transportProto; + } + if (!serverProtocolConfig.subnetAddress.isEmpty()) { + json[config_key::subnet_address] = serverProtocolConfig.subnetAddress; + } + + if (!serverProtocolConfig.awgData.junkPacketCount.isEmpty()) { + json[config_key::junkPacketCount] = serverProtocolConfig.awgData.junkPacketCount; + } + if (!serverProtocolConfig.awgData.junkPacketMinSize.isEmpty()) { + json[config_key::junkPacketMinSize] = serverProtocolConfig.awgData.junkPacketMinSize; + } + if (!serverProtocolConfig.awgData.junkPacketMaxSize.isEmpty()) { + json[config_key::junkPacketMaxSize] = serverProtocolConfig.awgData.junkPacketMaxSize; + } + if (!serverProtocolConfig.awgData.initPacketJunkSize.isEmpty()) { + json[config_key::initPacketJunkSize] = serverProtocolConfig.awgData.initPacketJunkSize; + } + if (!serverProtocolConfig.awgData.responsePacketJunkSize.isEmpty()) { + json[config_key::responsePacketJunkSize] = serverProtocolConfig.awgData.responsePacketJunkSize; + } + if (!serverProtocolConfig.awgData.initPacketMagicHeader.isEmpty()) { + json[config_key::initPacketMagicHeader] = serverProtocolConfig.awgData.initPacketMagicHeader; + } + if (!serverProtocolConfig.awgData.responsePacketMagicHeader.isEmpty()) { + json[config_key::responsePacketMagicHeader] = serverProtocolConfig.awgData.responsePacketMagicHeader; + } + if (!serverProtocolConfig.awgData.underloadPacketMagicHeader.isEmpty()) { + json[config_key::underloadPacketMagicHeader] = serverProtocolConfig.awgData.underloadPacketMagicHeader; + } + if (!serverProtocolConfig.awgData.transportPacketMagicHeader.isEmpty()) { + json[config_key::transportPacketMagicHeader] = serverProtocolConfig.awgData.transportPacketMagicHeader; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + + if (!clientProtocolConfig.clientId.isEmpty()) { + clientConfigJson[config_key::clientId] = clientProtocolConfig.clientId; + } + + if (!clientProtocolConfig.awgData.junkPacketCount.isEmpty()) { + clientConfigJson[config_key::junkPacketCount] = clientProtocolConfig.awgData.junkPacketCount; + } + if (!clientProtocolConfig.awgData.junkPacketMinSize.isEmpty()) { + clientConfigJson[config_key::junkPacketMinSize] = clientProtocolConfig.awgData.junkPacketMinSize; + } + if (!clientProtocolConfig.awgData.junkPacketMaxSize.isEmpty()) { + clientConfigJson[config_key::junkPacketMaxSize] = clientProtocolConfig.awgData.junkPacketMaxSize; + } + if (!clientProtocolConfig.awgData.initPacketJunkSize.isEmpty()) { + clientConfigJson[config_key::initPacketJunkSize] = clientProtocolConfig.awgData.initPacketJunkSize; + } + if (!clientProtocolConfig.awgData.responsePacketJunkSize.isEmpty()) { + clientConfigJson[config_key::responsePacketJunkSize] = clientProtocolConfig.awgData.responsePacketJunkSize; + } + if (!clientProtocolConfig.awgData.initPacketMagicHeader.isEmpty()) { + clientConfigJson[config_key::initPacketMagicHeader] = clientProtocolConfig.awgData.initPacketMagicHeader; + } + if (!clientProtocolConfig.awgData.responsePacketMagicHeader.isEmpty()) { + clientConfigJson[config_key::responsePacketMagicHeader] = clientProtocolConfig.awgData.responsePacketMagicHeader; + } + if (!clientProtocolConfig.awgData.underloadPacketMagicHeader.isEmpty()) { + clientConfigJson[config_key::underloadPacketMagicHeader] = clientProtocolConfig.awgData.underloadPacketMagicHeader; + } + if (!clientProtocolConfig.awgData.transportPacketMagicHeader.isEmpty()) { + clientConfigJson[config_key::transportPacketMagicHeader] = clientProtocolConfig.awgData.transportPacketMagicHeader; + } + + if (!clientProtocolConfig.wireGuardData.clientIp.isEmpty()) { + clientConfigJson[config_key::client_ip] = clientProtocolConfig.wireGuardData.clientIp; + } + if (!clientProtocolConfig.wireGuardData.clientPrivateKey.isEmpty()) { + clientConfigJson[config_key::client_priv_key] = clientProtocolConfig.wireGuardData.clientPrivateKey; + } + if (!clientProtocolConfig.wireGuardData.clientPublicKey.isEmpty()) { + clientConfigJson[config_key::client_pub_key] = clientProtocolConfig.wireGuardData.clientPublicKey; + } + if (!clientProtocolConfig.wireGuardData.persistentKeepAlive.isEmpty()) { + clientConfigJson[config_key::persistent_keep_alive] = clientProtocolConfig.wireGuardData.persistentKeepAlive; + } + if (!clientProtocolConfig.wireGuardData.pskKey.isEmpty()) { + clientConfigJson[config_key::psk_key] = clientProtocolConfig.wireGuardData.pskKey; + } + if (!clientProtocolConfig.wireGuardData.serverPubKey.isEmpty()) { + clientConfigJson[config_key::server_pub_key] = clientProtocolConfig.wireGuardData.serverPubKey; + } + if (!clientProtocolConfig.wireGuardData.mtu.isEmpty()) { + clientConfigJson[config_key::mtu] = clientProtocolConfig.wireGuardData.mtu; + } + + if (!clientProtocolConfig.wireGuardData.allowedIps.isEmpty()) { + QJsonArray allowedIpsArray; + for (const auto &ip : clientProtocolConfig.wireGuardData.allowedIps) { + if (!ip.isEmpty()) { + allowedIpsArray.append(ip); + } + } + if (!allowedIpsArray.isEmpty()) { + clientConfigJson[config_key::allowed_ips] = allowedIpsArray; + } + } + + if (!clientProtocolConfig.hostname.isEmpty()) { + clientConfigJson[config_key::hostName] = clientProtocolConfig.hostname; + } + if (clientProtocolConfig.port) { + clientConfigJson[config_key::port] = clientProtocolConfig.port; + } + if (!clientProtocolConfig.nativeConfig.isEmpty()) { + clientConfigJson[config_key::config] = clientProtocolConfig.nativeConfig; + } + + if (!clientConfigJson.isEmpty()) { + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson(QJsonDocument::Compact)); + } + } + + return json; +} diff --git a/client/core/models/protocols/awgProtocolConfig.h b/client/core/models/protocols/awgProtocolConfig.h new file mode 100644 index 00000000..7c4fcf06 --- /dev/null +++ b/client/core/models/protocols/awgProtocolConfig.h @@ -0,0 +1,65 @@ +#ifndef AWGPROTOCOLCONFIG_H +#define AWGPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" +#include "wireguardProtocolConfig.h" + +namespace awg +{ + struct AwgData + { + QString junkPacketCount; + QString junkPacketMinSize; + QString junkPacketMaxSize; + + QString initPacketJunkSize; + QString responsePacketJunkSize; + + QString initPacketMagicHeader; + QString responsePacketMagicHeader; + QString underloadPacketMagicHeader; + QString transportPacketMagicHeader; + }; + + struct ServerProtocolConfig + { + QString port; + QString transportProto; + + QString subnetAddress; + + AwgData awgData; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + + QString clientId; + + wireguard::WireGuardData wireGuardData; + + AwgData awgData; + + QString hostname; + int port; + + QString nativeConfig; + }; +} + +class AwgProtocolConfig : public ProtocolConfig +{ +public: + AwgProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + awg::ServerProtocolConfig serverProtocolConfig; + awg::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // AWGPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/cloakProtocolConfig.cpp b/client/core/models/protocols/cloakProtocolConfig.cpp new file mode 100644 index 00000000..b32e652e --- /dev/null +++ b/client/core/models/protocols/cloakProtocolConfig.cpp @@ -0,0 +1,43 @@ +#include "cloakProtocolConfig.h" + +#include +#include +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +CloakProtocolConfig::CloakProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(); + serverProtocolConfig.site = protocolConfigObject.value(config_key::site).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + } +} + +QJsonObject CloakProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.cipher.isEmpty()) { + json[config_key::cipher] = serverProtocolConfig.cipher; + } + if (!serverProtocolConfig.site.isEmpty()) { + json[config_key::site] = serverProtocolConfig.site; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson()); + } + + return json; +} diff --git a/client/core/models/protocols/cloakProtocolConfig.h b/client/core/models/protocols/cloakProtocolConfig.h new file mode 100644 index 00000000..191e3f2d --- /dev/null +++ b/client/core/models/protocols/cloakProtocolConfig.h @@ -0,0 +1,35 @@ +#ifndef CLOAKPROTOCOLCONFIG_H +#define CLOAKPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace cloak +{ + struct ServerProtocolConfig + { + QString port; + QString cipher; + QString site; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + }; +} + +class CloakProtocolConfig : public ProtocolConfig +{ +public: + CloakProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + cloak::ServerProtocolConfig serverProtocolConfig; + cloak::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // CLOAKPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/openvpnProtocolConfig.cpp b/client/core/models/protocols/openvpnProtocolConfig.cpp new file mode 100644 index 00000000..cf994566 --- /dev/null +++ b/client/core/models/protocols/openvpnProtocolConfig.cpp @@ -0,0 +1,83 @@ +#include "openvpnProtocolConfig.h" + +#include +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +OpenVpnProtocolConfig::OpenVpnProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.ncpDisable = protocolConfigObject.value(config_key::ncp_disable).toString(); + serverProtocolConfig.hash = protocolConfigObject.value(config_key::hash).toString(); + serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(); + serverProtocolConfig.tlsAuth = protocolConfigObject.value(config_key::tls_auth).toString(); + serverProtocolConfig.blockOutsideDns = protocolConfigObject.value(config_key::block_outside_dns).toString(); + serverProtocolConfig.additionalClientConfig = protocolConfigObject.value(config_key::additional_client_config).toString(); + serverProtocolConfig.additionalServerConfig = protocolConfigObject.value(config_key::additional_server_config).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + + clientProtocolConfig.clientId = clientProtocolConfigObject.value(config_key::clientId).toString(); + clientProtocolConfig.nativeConfig = clientProtocolConfigObject.value(config_key::config).toString(); + } +} + +QJsonObject OpenVpnProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.subnetAddress.isEmpty()) { + json[config_key::subnet_address] = serverProtocolConfig.subnetAddress; + } + if (!serverProtocolConfig.transportProto.isEmpty()) { + json[config_key::transport_proto] = serverProtocolConfig.transportProto; + } + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.ncpDisable.isEmpty()) { + json[config_key::ncp_disable] = serverProtocolConfig.ncpDisable; + } + if (!serverProtocolConfig.hash.isEmpty()) { + json[config_key::hash] = serverProtocolConfig.hash; + } + if (!serverProtocolConfig.cipher.isEmpty()) { + json[config_key::cipher] = serverProtocolConfig.cipher; + } + if (!serverProtocolConfig.tlsAuth.isEmpty()) { + json[config_key::tls_auth] = serverProtocolConfig.tlsAuth; + } + if (!serverProtocolConfig.blockOutsideDns.isEmpty()) { + json[config_key::block_outside_dns] = serverProtocolConfig.blockOutsideDns; + } + if (!serverProtocolConfig.additionalClientConfig.isEmpty()) { + json[config_key::additional_client_config] = serverProtocolConfig.additionalClientConfig; + } + if (!serverProtocolConfig.additionalServerConfig.isEmpty()) { + json[config_key::additional_server_config] = serverProtocolConfig.additionalServerConfig; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + + if (!clientProtocolConfig.clientId.isEmpty()) { + clientConfigJson[config_key::clientId] = clientProtocolConfig.clientId; + } + if (!clientProtocolConfig.nativeConfig.isEmpty()) { + clientConfigJson[config_key::config] = clientProtocolConfig.nativeConfig; + } + + if (!clientConfigJson.isEmpty()) { + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson()); + } + } + + return json; +} diff --git a/client/core/models/protocols/openvpnProtocolConfig.h b/client/core/models/protocols/openvpnProtocolConfig.h new file mode 100644 index 00000000..0e6d4e6a --- /dev/null +++ b/client/core/models/protocols/openvpnProtocolConfig.h @@ -0,0 +1,46 @@ +#ifndef OPENVPNPROTOCOLCONFIG_H +#define OPENVPNPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace openvpn +{ + struct ServerProtocolConfig + { + QString subnetAddress; + QString transportProto; + QString port; + QString ncpDisable; + QString hash; + QString cipher; + QString tlsAuth; + QString blockOutsideDns; + QString additionalClientConfig; + QString additionalServerConfig; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + + QString clientId; + + QString nativeConfig; + }; +} + +class OpenVpnProtocolConfig : public ProtocolConfig +{ +public: + OpenVpnProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + openvpn::ServerProtocolConfig serverProtocolConfig; + openvpn::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // OPENVPNPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/protocolConfig.cpp b/client/core/models/protocols/protocolConfig.cpp new file mode 100644 index 00000000..58b9387d --- /dev/null +++ b/client/core/models/protocols/protocolConfig.cpp @@ -0,0 +1,12 @@ +#include "protocolConfig.h" + +#include + +ProtocolConfig::ProtocolConfig(const QString &protocolName) : protocolName(protocolName) +{ +} + +QJsonObject ProtocolConfig::toJson() const +{ + return QJsonObject(); +} diff --git a/client/core/models/protocols/protocolConfig.h b/client/core/models/protocols/protocolConfig.h new file mode 100644 index 00000000..ce917002 --- /dev/null +++ b/client/core/models/protocols/protocolConfig.h @@ -0,0 +1,16 @@ +#ifndef PROTOCOLCONFIG_H +#define PROTOCOLCONFIG_H + +#include + +class ProtocolConfig +{ +public: + ProtocolConfig(const QString &protocolName); + + QString protocolName; + + virtual QJsonObject toJson() const; +}; + +#endif // PROTOCOLCONFIG_H diff --git a/client/core/models/protocols/shadowsocksProtocolConfig.cpp b/client/core/models/protocols/shadowsocksProtocolConfig.cpp new file mode 100644 index 00000000..e5f9b978 --- /dev/null +++ b/client/core/models/protocols/shadowsocksProtocolConfig.cpp @@ -0,0 +1,39 @@ +#include "shadowsocksProtocolConfig.h" + +#include +#include +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +ShadowsocksProtocolConfig::ShadowsocksProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + } +} + +QJsonObject ShadowsocksProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.cipher.isEmpty()) { + json[config_key::cipher] = serverProtocolConfig.cipher; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson()); + } + + return json; +} diff --git a/client/core/models/protocols/shadowsocksProtocolConfig.h b/client/core/models/protocols/shadowsocksProtocolConfig.h new file mode 100644 index 00000000..3c615f8a --- /dev/null +++ b/client/core/models/protocols/shadowsocksProtocolConfig.h @@ -0,0 +1,34 @@ +#ifndef SHADOWSOCKSPROTOCOLCONFIG_H +#define SHADOWSOCKSPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace shadowsocks +{ + struct ServerProtocolConfig + { + QString port; + QString cipher; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + }; +} + +class ShadowsocksProtocolConfig : public ProtocolConfig +{ +public: + ShadowsocksProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + shadowsocks::ServerProtocolConfig serverProtocolConfig; + shadowsocks::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // SHADOWSOCKSPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/wireguardProtocolConfig.cpp b/client/core/models/protocols/wireguardProtocolConfig.cpp new file mode 100644 index 00000000..602cbce5 --- /dev/null +++ b/client/core/models/protocols/wireguardProtocolConfig.cpp @@ -0,0 +1,120 @@ +#include "wireguardProtocolConfig.h" + +#include +#include + +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +WireGuardProtocolConfig::WireGuardProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) + : ProtocolConfig(protocolName) +{ + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); + serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + + clientProtocolConfig.clientId = clientProtocolConfigObject.value(config_key::clientId).toString(); + + clientProtocolConfig.wireGuardData.clientIp = clientProtocolConfigObject.value(config_key::client_ip).toString(); + clientProtocolConfig.wireGuardData.clientPrivateKey = clientProtocolConfigObject.value(config_key::client_priv_key).toString(); + clientProtocolConfig.wireGuardData.clientPublicKey = clientProtocolConfigObject.value(config_key::client_pub_key).toString(); + clientProtocolConfig.wireGuardData.persistentKeepAlive = + clientProtocolConfigObject.value(config_key::persistent_keep_alive).toString(); + clientProtocolConfig.wireGuardData.pskKey = clientProtocolConfigObject.value(config_key::psk_key).toString(); + clientProtocolConfig.wireGuardData.serverPubKey = clientProtocolConfigObject.value(config_key::server_pub_key).toString(); + clientProtocolConfig.wireGuardData.mtu = clientProtocolConfigObject.value(config_key::mtu).toString(); + + clientProtocolConfig.hostname = clientProtocolConfigObject.value(config_key::hostName).toString(); + clientProtocolConfig.port = clientProtocolConfigObject.value(config_key::port).toInt(0); + + clientProtocolConfig.nativeConfig = clientProtocolConfigObject.value(config_key::config).toString(); + + if (clientProtocolConfigObject.contains(config_key::allowed_ips) + && clientProtocolConfigObject.value(config_key::allowed_ips).isArray()) { + auto allowedIpsArray = clientProtocolConfigObject.value(config_key::allowed_ips).toArray(); + for (const auto &ip : allowedIpsArray) { + clientProtocolConfig.wireGuardData.allowedIps.append(ip.toString()); + } + } + } +} + +QJsonObject WireGuardProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.transportProto.isEmpty()) { + json[config_key::transport_proto] = serverProtocolConfig.transportProto; + } + if (!serverProtocolConfig.subnetAddress.isEmpty()) { + json[config_key::subnet_address] = serverProtocolConfig.subnetAddress; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + + if (!clientProtocolConfig.clientId.isEmpty()) { + clientConfigJson[config_key::clientId] = clientProtocolConfig.clientId; + } + + if (!clientProtocolConfig.wireGuardData.clientIp.isEmpty()) { + clientConfigJson[config_key::client_ip] = clientProtocolConfig.wireGuardData.clientIp; + } + if (!clientProtocolConfig.wireGuardData.clientPrivateKey.isEmpty()) { + clientConfigJson[config_key::client_priv_key] = clientProtocolConfig.wireGuardData.clientPrivateKey; + } + if (!clientProtocolConfig.wireGuardData.clientPublicKey.isEmpty()) { + clientConfigJson[config_key::client_pub_key] = clientProtocolConfig.wireGuardData.clientPublicKey; + } + if (!clientProtocolConfig.wireGuardData.persistentKeepAlive.isEmpty()) { + clientConfigJson[config_key::persistent_keep_alive] = clientProtocolConfig.wireGuardData.persistentKeepAlive; + } + if (!clientProtocolConfig.wireGuardData.pskKey.isEmpty()) { + clientConfigJson[config_key::psk_key] = clientProtocolConfig.wireGuardData.pskKey; + } + if (!clientProtocolConfig.wireGuardData.serverPubKey.isEmpty()) { + clientConfigJson[config_key::server_pub_key] = clientProtocolConfig.wireGuardData.serverPubKey; + } + if (!clientProtocolConfig.wireGuardData.mtu.isEmpty()) { + clientConfigJson[config_key::mtu] = clientProtocolConfig.wireGuardData.mtu; + } + + if (!clientProtocolConfig.wireGuardData.allowedIps.isEmpty()) { + QJsonArray allowedIpsArray; + for (const auto &ip : clientProtocolConfig.wireGuardData.allowedIps) { + if (!ip.isEmpty()) { + allowedIpsArray.append(ip); + } + } + if (!allowedIpsArray.isEmpty()) { + clientConfigJson[config_key::allowed_ips] = allowedIpsArray; + } + } + + if (!clientProtocolConfig.hostname.isEmpty()) { + clientConfigJson[config_key::hostName] = clientProtocolConfig.hostname; + } + if (clientProtocolConfig.port) { + clientConfigJson[config_key::port] = clientProtocolConfig.port; + } + if (!clientProtocolConfig.nativeConfig.isEmpty()) { + clientConfigJson[config_key::config] = clientProtocolConfig.nativeConfig; + } + + if (!clientConfigJson.isEmpty()) { + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson()); + } + } + + return json; +} diff --git a/client/core/models/protocols/wireguardProtocolConfig.h b/client/core/models/protocols/wireguardProtocolConfig.h new file mode 100644 index 00000000..acefafe2 --- /dev/null +++ b/client/core/models/protocols/wireguardProtocolConfig.h @@ -0,0 +1,58 @@ +#ifndef WIREGUARDPROTOCOLCONFIG_H +#define WIREGUARDPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace wireguard +{ + struct WireGuardData + { + QStringList allowedIps; + + QString clientIp; + QString clientPrivateKey; + QString clientPublicKey; + QString mtu; + QString persistentKeepAlive; + QString pskKey; + QString serverPubKey; + }; + + struct ServerProtocolConfig + { + QString port; + QString transportProto; + + QString subnetAddress; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + + QString clientId; + + WireGuardData wireGuardData; + + QString hostname; + int port; + + QString nativeConfig; + }; +} + +class WireGuardProtocolConfig : public ProtocolConfig +{ +public: + WireGuardProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + wireguard::ServerProtocolConfig serverProtocolConfig; + wireguard::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // WIREGUARDPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/xrayProtocolConfig.cpp b/client/core/models/protocols/xrayProtocolConfig.cpp new file mode 100644 index 00000000..32ad108a --- /dev/null +++ b/client/core/models/protocols/xrayProtocolConfig.cpp @@ -0,0 +1,43 @@ +#include "xrayProtocolConfig.h" + +#include +#include +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +XrayProtocolConfig::XrayProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.site = protocolConfigObject.value(config_key::site).toString(); + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + } +} + +QJsonObject XrayProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.site.isEmpty()) { + json[config_key::site] = serverProtocolConfig.site; + } + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.transportProto.isEmpty()) { + json[config_key::transport_proto] = serverProtocolConfig.transportProto; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson()); + } + + return json; +} diff --git a/client/core/models/protocols/xrayProtocolConfig.h b/client/core/models/protocols/xrayProtocolConfig.h new file mode 100644 index 00000000..87023954 --- /dev/null +++ b/client/core/models/protocols/xrayProtocolConfig.h @@ -0,0 +1,35 @@ +#ifndef XRAYPROTOCOLCONFIG_H +#define XRAYPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace xray +{ + struct ServerProtocolConfig + { + QString site; + QString port; + QString transportProto; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + }; +} + +class XrayProtocolConfig : public ProtocolConfig +{ +public: + XrayProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + xray::ServerProtocolConfig serverProtocolConfig; + xray::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // XRAYPROTOCOLCONFIG_H diff --git a/client/core/models/servers/apiV1ServerConfig.cpp b/client/core/models/servers/apiV1ServerConfig.cpp new file mode 100644 index 00000000..363c1d9e --- /dev/null +++ b/client/core/models/servers/apiV1ServerConfig.cpp @@ -0,0 +1,30 @@ +#include "apiV1ServerConfig.h" + +#include +#include + +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +ApiV1ServerConfig::ApiV1ServerConfig(const QJsonObject &serverConfigObject) : ServerConfig(serverConfigObject) +{ + name = serverConfigObject.value(config_key::name).toString(); + description = serverConfigObject.value(config_key::description).toString(); +} + +QJsonObject ApiV1ServerConfig::toJson() const +{ + // Сначала вызываем родительскую функцию для сериализации базовых полей + QJsonObject json = ServerConfig::toJson(); + + // Добавляем свои поля только если они не пустые + if (!name.isEmpty()) { + json[config_key::name] = name; + } + if (!description.isEmpty()) { + json[config_key::description] = description; + } + + return json; +} diff --git a/client/core/models/servers/apiV1ServerConfig.h b/client/core/models/servers/apiV1ServerConfig.h new file mode 100644 index 00000000..c3a9e52b --- /dev/null +++ b/client/core/models/servers/apiV1ServerConfig.h @@ -0,0 +1,17 @@ +#ifndef APIV1SERVERCONFIG_H +#define APIV1SERVERCONFIG_H + +#include "serverConfig.h" + +class ApiV1ServerConfig : public ServerConfig +{ +public: + ApiV1ServerConfig(const QJsonObject &serverConfigObject); + + QJsonObject toJson() const override; + + QString name; + QString description; +}; + +#endif // APIV1SERVERCONFIG_H diff --git a/client/core/models/servers/apiV2ServerConfig.cpp b/client/core/models/servers/apiV2ServerConfig.cpp new file mode 100644 index 00000000..97e27dcb --- /dev/null +++ b/client/core/models/servers/apiV2ServerConfig.cpp @@ -0,0 +1,125 @@ +#include "apiV2ServerConfig.h" + +#include +#include + +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +ApiV2ServerConfig::ApiV2ServerConfig(const QJsonObject &serverConfigObject) : ServerConfig(serverConfigObject) +{ + name = serverConfigObject.value(config_key::name).toString(); + description = serverConfigObject.value(config_key::description).toString(); + + auto apiConfigObject = serverConfigObject.value("api_config").toObject(); + + auto availableCountriesArray = apiConfigObject.value("available_countries").toArray(); + for (const auto &countryValue : availableCountriesArray) { + auto countryObject = countryValue.toObject(); + apiv2::Country country; + country.code = countryObject.value("server_country_code").toString(); + country.name = countryObject.value("server_country_name").toString(); + apiConfig.availableCountries.append(country); + } + + auto subscriptionObject = apiConfigObject.value("subscription").toObject(); + apiConfig.subscription.end_date = subscriptionObject.value("end_date").toString(); + + auto publicKeyObject = apiConfigObject.value("public_key").toObject(); + apiConfig.publicKey.expiresAt = publicKeyObject.value("expires_at").toString(); + + apiConfig.serverCountryCode = apiConfigObject.value("server_country_code").toString(); + apiConfig.serverCountryName = apiConfigObject.value("server_country_name").toString(); + + apiConfig.serviceProtocol = apiConfigObject.value("service_protocol").toString(); + apiConfig.serviceType = apiConfigObject.value("service_type").toString(); + + apiConfig.userCountryCode = apiConfigObject.value("user_country_code").toString(); + + apiConfig.vpnKey = apiConfigObject.value("vpn_key").toString(); +} + +QJsonObject ApiV2ServerConfig::toJson() const +{ + // Сначала вызываем родительскую функцию для сериализации базовых полей + QJsonObject json = ServerConfig::toJson(); + + // Добавляем свои поля только если они не пустые + if (!name.isEmpty()) { + json[config_key::name] = name; + } + if (!description.isEmpty()) { + json[config_key::description] = description; + } + + // Сериализация API конфигурации + QJsonObject apiConfigJson; + + // Сериализация доступных стран только если массив не пустой + if (!apiConfig.availableCountries.isEmpty()) { + QJsonArray availableCountriesArray; + for (const auto &country : apiConfig.availableCountries) { + QJsonObject countryObject; + if (!country.code.isEmpty()) { + countryObject["server_country_code"] = country.code; + } + if (!country.name.isEmpty()) { + countryObject["server_country_name"] = country.name; + } + if (!countryObject.isEmpty()) { + availableCountriesArray.append(countryObject); + } + } + if (!availableCountriesArray.isEmpty()) { + apiConfigJson["available_countries"] = availableCountriesArray; + } + } + + // Сериализация подписки только если есть данные + if (!apiConfig.subscription.end_date.isEmpty()) { + QJsonObject subscriptionObject; + subscriptionObject["end_date"] = apiConfig.subscription.end_date; + apiConfigJson["subscription"] = subscriptionObject; + } + + // Сериализация публичного ключа только если есть данные + if (!apiConfig.publicKey.expiresAt.isEmpty()) { + QJsonObject publicKeyObject; + publicKeyObject["expires_at"] = apiConfig.publicKey.expiresAt; + apiConfigJson["public_key"] = publicKeyObject; + } + + // Сериализация информации о сервере только если не пустая + if (!apiConfig.serverCountryCode.isEmpty()) { + apiConfigJson["server_country_code"] = apiConfig.serverCountryCode; + } + if (!apiConfig.serverCountryName.isEmpty()) { + apiConfigJson["server_country_name"] = apiConfig.serverCountryName; + } + + // Сериализация информации о сервисе только если не пустая + if (!apiConfig.serviceProtocol.isEmpty()) { + apiConfigJson["service_protocol"] = apiConfig.serviceProtocol; + } + if (!apiConfig.serviceType.isEmpty()) { + apiConfigJson["service_type"] = apiConfig.serviceType; + } + + // Сериализация информации о пользователе только если не пустая + if (!apiConfig.userCountryCode.isEmpty()) { + apiConfigJson["user_country_code"] = apiConfig.userCountryCode; + } + + // Сериализация VPN ключа только если не пустой + if (!apiConfig.vpnKey.isEmpty()) { + apiConfigJson["vpn_key"] = apiConfig.vpnKey; + } + + // Добавляем API конфигурацию в основной JSON только если есть данные + if (!apiConfigJson.isEmpty()) { + json["api_config"] = apiConfigJson; + } + + return json; +} diff --git a/client/core/models/servers/apiV2ServerConfig.h b/client/core/models/servers/apiV2ServerConfig.h new file mode 100644 index 00000000..782e82ef --- /dev/null +++ b/client/core/models/servers/apiV2ServerConfig.h @@ -0,0 +1,54 @@ +#ifndef APIV2SERVERCONFIG_H +#define APIV2SERVERCONFIG_H + +#include "serverConfig.h" + +namespace apiv2 +{ + struct Country { + QString code; + QString name; + }; + + struct PublicKey + { + QString expiresAt; + }; + + struct Subscription + { + QString end_date; + }; + + struct ApiConfig { + QVector availableCountries; + + Subscription subscription; + PublicKey publicKey; + + QString serverCountryCode; + QString serverCountryName; + + QString serviceProtocol; + QString serviceType; + + QString userCountryCode; + + QString vpnKey; + }; +} + +class ApiV2ServerConfig : public ServerConfig +{ +public: + ApiV2ServerConfig(const QJsonObject &serverConfigObject); + + QJsonObject toJson() const override; + + QString name; + QString description; + + apiv2::ApiConfig apiConfig; +}; + +#endif // APIV2SERVERCONFIG_H diff --git a/client/core/models/servers/selfHostedServerConfig.cpp b/client/core/models/servers/selfHostedServerConfig.cpp new file mode 100644 index 00000000..b2cf189a --- /dev/null +++ b/client/core/models/servers/selfHostedServerConfig.cpp @@ -0,0 +1,48 @@ +#include "selfHostedServerConfig.h" + +#include +#include + +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +SelfHostedServerConfig::SelfHostedServerConfig(const QJsonObject &serverConfigObject) : ServerConfig(serverConfigObject) +{ + name = serverConfigObject.value(config_key::description).toString(); + if (name.isEmpty()) { + name = serverConfigObject.value(config_key::hostName).toString(); + } + + serverCredentials.hostName = serverConfigObject.value(config_key::hostName).toString(); + serverCredentials.userName = serverConfigObject.value(config_key::userName).toString(); + serverCredentials.secretData = serverConfigObject.value(config_key::password).toString(); + serverCredentials.port = serverConfigObject.value(config_key::port).toInt(22); +} + +QJsonObject SelfHostedServerConfig::toJson() const +{ + // Сначала вызываем родительскую функцию для сериализации базовых полей + QJsonObject json = ServerConfig::toJson(); + + // Добавляем имя только если оно не пустое + if (!name.isEmpty()) { + json[config_key::description] = name; // Используем description как в конструкторе + } + + // Добавляем credentials только если они не пустые + if (!serverCredentials.hostName.isEmpty()) { + json[config_key::hostName] = serverCredentials.hostName; + } + if (!serverCredentials.userName.isEmpty()) { + json[config_key::userName] = serverCredentials.userName; + } + if (!serverCredentials.secretData.isEmpty()) { + json[config_key::password] = serverCredentials.secretData; + } + if (serverCredentials.port != 22) { // Добавляем порт только если не дефолтный + json[config_key::port] = serverCredentials.port; + } + + return json; +} diff --git a/client/core/models/servers/selfHostedServerConfig.h b/client/core/models/servers/selfHostedServerConfig.h new file mode 100644 index 00000000..c11b8aa4 --- /dev/null +++ b/client/core/models/servers/selfHostedServerConfig.h @@ -0,0 +1,19 @@ +#ifndef SELFHOSTEDSERVERCONFIG_H +#define SELFHOSTEDSERVERCONFIG_H + +#include "core/defs.h" +#include "serverConfig.h" + +class SelfHostedServerConfig : public ServerConfig +{ +public: + SelfHostedServerConfig(const QJsonObject &serverConfigObject); + + QJsonObject toJson() const override; + + QString name; + + amnezia::ServerCredentials serverCredentials; +}; + +#endif // SELFHOSTEDSERVERCONFIG_H diff --git a/client/core/models/servers/serverConfig.cpp b/client/core/models/servers/serverConfig.cpp new file mode 100644 index 00000000..977f8763 --- /dev/null +++ b/client/core/models/servers/serverConfig.cpp @@ -0,0 +1,145 @@ +#include "serverConfig.h" + +#include + +#include "apiV1ServerConfig.h" +#include "apiV2ServerConfig.h" +#include "containers/containers_defs.h" +#include "core/models/protocols/awgProtocolConfig.h" +#include "core/models/protocols/cloakProtocolConfig.h" +#include "core/models/protocols/openvpnProtocolConfig.h" +#include "core/models/protocols/protocolConfig.h" +#include "core/models/protocols/shadowsocksProtocolConfig.h" +#include "core/models/protocols/xrayProtocolConfig.h" +#include "protocols/protocols_defs.h" +#include "selfHostedServerConfig.h" + +using namespace amnezia; + +ServerConfig::ServerConfig(const QJsonObject &serverConfigObject) +{ + type = static_cast(serverConfigObject.value(config_key::configVersion).toInt(0)); + + hostName = serverConfigObject.value(config_key::hostName).toString(); + + dns1 = serverConfigObject.value(config_key::dns1).toString(); + dns2 = serverConfigObject.value(config_key::dns2).toString(); + + defaultContainer = serverConfigObject.value(config_key::defaultContainer).toString(); + + auto containers = serverConfigObject.value(config_key::containers).toArray(); + for (const auto &container : std::as_const(containers)) { + auto containerObject = container.toObject(); + + auto containerName = containerObject.value(config_key::container).toString(); + + ContainerConfig containerConfig; + containerConfig.containerName = containerName; + + auto protocols = ContainerProps::protocolsForContainer(ContainerProps::containerFromString(containerName)); + for (const auto &protocol : protocols) { + auto protocolName = ProtocolProps::protoToString(protocol); + auto protocolConfigObject = containerObject.value(protocolName).toObject(); + + switch (protocol) { + case Proto::OpenVpn: { + containerConfig.protocolConfigs.insert(protocolName, + QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::ShadowSocks: { + containerConfig.protocolConfigs.insert( + protocolName, QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::Cloak: { + containerConfig.protocolConfigs.insert(protocolName, + QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::WireGuard: { + containerConfig.protocolConfigs.insert(protocolName, + QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::Awg: { + containerConfig.protocolConfigs.insert(protocolName, + QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::Xray: { + containerConfig.protocolConfigs.insert(protocolName, + QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::Ikev2: break; + case Proto::L2tp: break; + case Proto::SSXray: break; + case Proto::TorWebSite: break; + case Proto::Dns: break; + case Proto::Sftp: break; + case Proto::Socks5Proxy: break; + default: break; + } + } + + containerConfigs.insert(containerName, containerConfig); + } +} + +QSharedPointer ServerConfig::createServerConfig(const QJsonObject &serverConfigObject) +{ + auto type = static_cast(serverConfigObject.value(config_key::configVersion).toInt(0)); + + switch (type) { + case ServerConfigType::SelfHosted: return QSharedPointer::create(serverConfigObject); + case ServerConfigType::ApiV1: return QSharedPointer::create(serverConfigObject); + case ServerConfigType::ApiV2: return QSharedPointer::create(serverConfigObject); + } +} + +QJsonObject ServerConfig::toJson() const +{ + QJsonObject json; + + if (type != ServerConfigType::SelfHosted) { + json[config_key::configVersion] = static_cast(type); + } + + if (!hostName.isEmpty()) { + json[config_key::hostName] = hostName; + } + if (!dns1.isEmpty()) { + json[config_key::dns1] = dns1; + } + if (!dns2.isEmpty()) { + json[config_key::dns2] = dns2; + } + if (!defaultContainer.isEmpty()) { + json[config_key::defaultContainer] = defaultContainer; + } + + if (!containerConfigs.isEmpty()) { + QJsonArray containersArray; + for (const auto &containerConfig : containerConfigs) { + QJsonObject containerObject; + containerObject[config_key::container] = containerConfig.containerName; + + if (!containerConfig.protocolConfigs.isEmpty()) { + for (const auto &protocolConfig : containerConfig.protocolConfigs) { + QJsonObject protocolJson = protocolConfig->toJson(); + if (!protocolJson.isEmpty()) { + containerObject[protocolConfig->protocolName] = protocolJson; + } + } + } + + containersArray.append(containerObject); + } + if (!containersArray.isEmpty()) { + json[config_key::containers] = containersArray; + } + } + + return json; +} diff --git a/client/core/models/servers/serverConfig.h b/client/core/models/servers/serverConfig.h new file mode 100644 index 00000000..5559b507 --- /dev/null +++ b/client/core/models/servers/serverConfig.h @@ -0,0 +1,32 @@ +#ifndef SERVERCONFIG_H +#define SERVERCONFIG_H + +#include +#include +#include + +#include "core/defs.h" +#include "core/models/containers/containerConfig.h" + +class ServerConfig +{ +public: + ServerConfig(const QJsonObject &serverConfigObject); + + virtual QJsonObject toJson() const; + + static QSharedPointer createServerConfig(const QJsonObject &serverConfigObject); + + amnezia::ServerConfigType type; + + QString hostName; + + QString dns1; + QString dns2; + + QString defaultContainer; + + QMap containerConfigs; +}; + +#endif // SERVERCONFIG_H diff --git a/client/ui/controllers/api/apiConfigsController.cpp b/client/ui/controllers/api/apiConfigsController.cpp index 4c58140c..a805dae2 100644 --- a/client/ui/controllers/api/apiConfigsController.cpp +++ b/client/ui/controllers/api/apiConfigsController.cpp @@ -398,16 +398,16 @@ bool ApiConfigsController::isConfigValid() QJsonObject serverConfigObject = m_serversModel->getServerConfig(serverIndex); auto configSource = apiUtils::getConfigSource(serverConfigObject); - if (configSource == apiDefs::ConfigSource::Telegram + if (configSource == amnezia::ServerConfigType::ApiV1 && !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) { m_serversModel->removeApiConfig(serverIndex); return updateServiceFromTelegram(serverIndex); - } else if (configSource == apiDefs::ConfigSource::AmneziaGateway + } else if (configSource == amnezia::ServerConfigType::ApiV2 && !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) { return updateServiceFromGateway(serverIndex, "", ""); } else if (configSource && m_serversModel->isApiKeyExpired(serverIndex)) { qDebug() << "attempt to update api config by expires_at event"; - if (configSource == apiDefs::ConfigSource::AmneziaGateway) { + if (configSource == amnezia::ServerConfigType::ApiV2) { return updateServiceFromGateway(serverIndex, "", ""); } else { m_serversModel->removeApiConfig(serverIndex); @@ -499,7 +499,7 @@ void ApiConfigsController::fillServerConfig(const QString &protocol, const ApiPa serverConfig[config_key::containers] = newServerConfig.value(config_key::containers); serverConfig[config_key::hostName] = newServerConfig.value(config_key::hostName); - if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) { + if (newServerConfig.value(config_key::configVersion).toInt() == amnezia::ServerConfigType::ApiV2) { serverConfig[config_key::configVersion] = newServerConfig.value(config_key::configVersion); serverConfig[config_key::description] = newServerConfig.value(config_key::description); serverConfig[config_key::name] = newServerConfig.value(config_key::name); @@ -512,7 +512,7 @@ void ApiConfigsController::fillServerConfig(const QString &protocol, const ApiPa map.insert(newServerConfig.value(configKey::apiConfig).toObject().toVariantMap()); auto apiConfig = QJsonObject::fromVariantMap(map); - if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) { + if (newServerConfig.value(config_key::configVersion).toInt() == amnezia::ServerConfigType::ApiV2) { apiConfig.insert(configKey::serviceInfo, QJsonDocument::fromJson(apiResponseBody).object().value(configKey::serviceInfo).toObject()); } diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index 5a70c16f..f76fea89 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -2,6 +2,9 @@ #include "core/api/apiDefs.h" #include "core/controllers/serverController.h" +#include "core/models/servers/apiV1ServerConfig.h" +#include "core/models/servers/apiV2ServerConfig.h" +#include "core/models/servers/selfHostedServerConfig.h" #include "core/networkUtilities.h" #ifdef Q_OS_IOS @@ -24,6 +27,9 @@ namespace constexpr char publicKeyInfo[] = "public_key"; constexpr char expiresAt[] = "expires_at"; } + + using ServerConfigVariant = + std::variant, QSharedPointer, QSharedPointer >; } ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent) @@ -91,29 +97,26 @@ bool ServersModel::setData(const int index, const QVariant &value, int role) QVariant ServersModel::data(const QModelIndex &index, int role) const { - if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(m_servers.size())) { + if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(m_servers1.size())) { return QVariant(); } - const QJsonObject server = m_servers.at(index.row()).toObject(); - const auto apiConfig = server.value(configKey::apiConfig).toObject(); - const auto configVersion = server.value(config_key::configVersion).toInt(); + QSharedPointer serverConfig = m_servers1.at(index.row()); + ServerConfigVariant variant; + switch (serverConfig->type) { + case amnezia::ServerConfigType::SelfHosted: variant = qSharedPointerCast(serverConfig); break; + case amnezia::ServerConfigType::ApiV1: variant = qSharedPointerCast(serverConfig); break; + case amnezia::ServerConfigType::ApiV2: variant = qSharedPointerCast(serverConfig); break; + } + switch (role) { case NameRole: { - if (configVersion) { - return server.value(config_key::name).toString(); - } - auto name = server.value(config_key::description).toString(); - if (name.isEmpty()) { - return server.value(config_key::hostName).toString(); - } - return name; + return std::visit([](const auto &ptr) -> QString { return ptr->name; }, variant); } case ServerDescriptionRole: { - auto description = getServerDescription(server, index.row()); - return configVersion ? description : description + server.value(config_key::hostName).toString(); + return getServerDescription(index.row()); } - case HostNameRole: return server.value(config_key::hostName).toString(); + case HostNameRole: return serverConfig->hostName; case CredentialsRole: return QVariant::fromValue(serverCredentials(index.row())); case CredentialsLoginRole: return serverCredentials(index.row()).userName; case IsDefaultRole: return index.row() == m_defaultServerIndex; @@ -123,36 +126,28 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty()); } case ContainsAmneziaDnsRole: { - QString primaryDns = server.value(config_key::dns1).toString(); - return primaryDns == protocols::dns::amneziaDnsIp; + return serverConfig->dns1 == protocols::dns::amneziaDnsIp; } case DefaultContainerRole: { - return ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); + return ContainerProps::containerFromString(serverConfig->defaultContainer); } case HasInstalledContainers: { return serverHasInstalledContainers(index.row()); } case IsServerFromTelegramApiRole: { - return server.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::Telegram; + return serverConfig->type == amnezia::ServerConfigType::ApiV1; } case IsServerFromGatewayApiRole: { - return server.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway; - } - case ApiConfigRole: { - return apiConfig; + return serverConfig->type == amnezia::ServerConfigType::ApiV2; } case IsCountrySelectionAvailableRole: { - return !apiConfig.value(configKey::availableCountries).toArray().isEmpty(); + return !qSharedPointerCast(serverConfig)->apiConfig.availableCountries.isEmpty(); } case ApiAvailableCountriesRole: { - return apiConfig.value(configKey::availableCountries).toArray(); + return QVariant::fromValue(qSharedPointerCast(serverConfig)->apiConfig.availableCountries); } case ApiServerCountryCodeRole: { - return apiConfig.value(configKey::serverCountryCode).toString(); - } - case HasAmneziaDns: { - QString primaryDns = server.value(config_key::dns1).toString(); - return primaryDns == protocols::dns::amneziaDnsIp; + return qSharedPointerCast(serverConfig)->apiConfig.serverCountryCode; } } @@ -171,6 +166,25 @@ void ServersModel::resetModel() m_servers = m_settings->serversArray(); m_defaultServerIndex = m_settings->defaultServerIndex(); m_processedServerIndex = m_defaultServerIndex; + + for (auto server : m_servers) { + auto serverConfig = ServerConfig::createServerConfig(server.toObject()); + m_servers1.push_back(serverConfig); + qDebug() << "333"; + qDebug() << server.toObject(); + qDebug() << "333"; + + ServerConfigVariant variant; + switch (serverConfig->type) { + case amnezia::ServerConfigType::SelfHosted: variant = qSharedPointerCast(serverConfig); break; + case amnezia::ServerConfigType::ApiV1: variant = qSharedPointerCast(serverConfig); break; + case amnezia::ServerConfigType::ApiV2: variant = qSharedPointerCast(serverConfig); break; + } + qDebug() << "123"; + qDebug() << std::visit([](const auto &ptr) -> QJsonObject { return ptr->toJson(); }, variant); + qDebug() << "123"; + } + endResetModel(); emit defaultServerIndexChanged(m_defaultServerIndex); } @@ -192,34 +206,40 @@ const QString ServersModel::getDefaultServerName() return qvariant_cast(data(m_defaultServerIndex, NameRole)); } -QString ServersModel::getServerDescription(const QJsonObject &server, const int index) const +QString ServersModel::getServerDescription(const int index) const { - const auto configVersion = server.value(config_key::configVersion).toInt(); - const auto apiConfig = server.value(configKey::apiConfig).toObject(); - - QString description; - - if (configVersion && !apiConfig.value(configKey::serverCountryCode).toString().isEmpty()) { - return apiConfig.value(configKey::serverCountryName).toString(); - } else if (configVersion) { - return server.value(config_key::description).toString(); - } else if (data(index, HasWriteAccessRole).toBool()) { - if (m_isAmneziaDnsEnabled && isAmneziaDnsContainerInstalled(index)) { - description += "Amnezia DNS | "; - } - } else { - if (data(index, HasAmneziaDns).toBool()) { - description += "Amnezia DNS | "; + auto serverConfig = m_servers1.at(index); + switch (serverConfig->type) { + case amnezia::ServerConfigType::ApiV1: return qSharedPointerCast(serverConfig)->description; + case amnezia::ServerConfigType::ApiV2: { + auto apiV2ServerConfig = qSharedPointerCast(serverConfig); + if (apiV2ServerConfig->apiConfig.serverCountryCode.isEmpty()) { + return apiV2ServerConfig->description; + } else { + return apiV2ServerConfig->apiConfig.serverCountryName; } } - return description; + case amnezia::ServerConfigType::SelfHosted: { + QString description; + if (data(index, HasWriteAccessRole).toBool()) { + if (m_isAmneziaDnsEnabled && isAmneziaDnsContainerInstalled(index)) { + description += "Amnezia DNS | " + serverConfig->hostName; + } + } else { + if (data(index, ContainsAmneziaDnsRole).toBool()) { + description += "Amnezia DNS | " + serverConfig->hostName; + } + } + return description; + } + } } const QString ServersModel::getDefaultServerDescriptionCollapsed() { const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); const auto configVersion = server.value(config_key::configVersion).toInt(); - auto description = getServerDescription(server, m_defaultServerIndex); + auto description = getServerDescription(m_defaultServerIndex); if (configVersion) { return description; } @@ -233,7 +253,7 @@ const QString ServersModel::getDefaultServerDescriptionExpanded() { const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); const auto configVersion = server.value(config_key::configVersion).toInt(); - auto description = getServerDescription(server, m_defaultServerIndex); + auto description = getServerDescription(m_defaultServerIndex); if (configVersion) { return description; } @@ -395,7 +415,6 @@ QHash ServersModel::roleNames() const roles[IsServerFromTelegramApiRole] = "isServerFromTelegramApi"; roles[IsServerFromGatewayApiRole] = "isServerFromGatewayApi"; - roles[ApiConfigRole] = "apiConfig"; roles[IsCountrySelectionAvailableRole] = "isCountrySelectionAvailable"; roles[ApiAvailableCountriesRole] = "apiAvailableCountries"; roles[ApiServerCountryCodeRole] = "apiServerCountryCode"; @@ -404,15 +423,8 @@ QHash ServersModel::roleNames() const ServerCredentials ServersModel::serverCredentials(int index) const { - const QJsonObject &s = m_servers.at(index).toObject(); - - ServerCredentials credentials; - credentials.hostName = s.value(config_key::hostName).toString(); - credentials.userName = s.value(config_key::userName).toString(); - credentials.secretData = s.value(config_key::password).toString(); - credentials.port = s.value(config_key::port).toInt(); - - return credentials; + const auto serverConfig = m_servers1.at(index); + return qSharedPointerCast(serverConfig)->serverCredentials; } void ServersModel::updateContainersModel() @@ -670,14 +682,14 @@ bool ServersModel::isServerFromApiAlreadyExists(const QString &userCountryCode, bool ServersModel::serverHasInstalledContainers(const int serverIndex) const { - QJsonObject server = m_servers.at(serverIndex).toObject(); - const auto containers = server.value(config_key::containers).toArray(); - for (auto it = containers.begin(); it != containers.end(); it++) { - auto container = ContainerProps::containerFromString(it->toObject().value(config_key::container).toString()); - if (ContainerProps::containerService(container) == ServiceType::Vpn) { + auto server = m_servers1.at(serverIndex); + const auto containers = server->containerConfigs; + for (const auto &container : containers) { + auto dockerContainer = ContainerProps::containerFromString(container.containerName); + if (ContainerProps::containerService(dockerContainer) == ServiceType::Vpn) { return true; } - if (container == DockerContainer::SSXray) { + if (dockerContainer == DockerContainer::SSXray) { return true; } } diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h index c4803708..f0649e7d 100644 --- a/client/ui/models/servers_model.h +++ b/client/ui/models/servers_model.h @@ -4,6 +4,7 @@ #include #include "core/controllers/serverController.h" +#include "core/models/servers/serverConfig.h" #include "settings.h" class ServersModel : public QAbstractListModel @@ -36,9 +37,7 @@ public: ApiConfigRole, IsCountrySelectionAvailableRole, ApiAvailableCountriesRole, - ApiServerCountryCodeRole, - - HasAmneziaDns + ApiServerCountryCodeRole }; ServersModel(std::shared_ptr settings, QObject *parent = nullptr); @@ -150,13 +149,14 @@ private: void updateContainersModel(); void updateDefaultServerContainersModel(); - QString getServerDescription(const QJsonObject &server, const int index) const; + QString getServerDescription(const int index) const; bool isAmneziaDnsContainerInstalled(const int serverIndex) const; bool serverHasInstalledContainers(const int serverIndex) const; QJsonArray m_servers; + QVector> m_servers1; std::shared_ptr m_settings;