diff --git a/.gitmodules b/.gitmodules index decab9b7..3ceaa56e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ +[submodule "client/3rd/OpenVPNAdapter"] + path = client/3rd/OpenVPNAdapter + url = https://github.com/amnezia-vpn/OpenVPNAdapter.git [submodule "client/3rd/qtkeychain"] path = client/3rd/qtkeychain url = https://github.com/frankosterfeld/qtkeychain.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c602249..434b195f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR) set(PROJECT AmneziaVPN) -project(${PROJECT} VERSION 4.8.4.2 +project(${PROJECT} VERSION 4.8.3.1 DESCRIPTION "AmneziaVPN" HOMEPAGE_URL "https://amnezia.org/" ) @@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d") set(RELEASE_DATE "${CURRENT_DATE}") set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}) -set(APP_ANDROID_VERSION_CODE 2079) +set(APP_ANDROID_VERSION_CODE 2074) if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(MZ_PLATFORM_NAME "linux") diff --git a/README.md b/README.md index 992c3ad0..368bcfff 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ [![Image](https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/uipic4.png)](https://amnezia.org) -### [Website](https://amnezia.org) | [Alt website link](https://storage.googleapis.com/amnezia/amnezia.org) | [Documentation](https://docs.amnezia.org) | [Troubleshooting](https://docs.amnezia.org/troubleshooting) +### [Website](https://amnezia.org) | [Alt website link](https://storage.googleapis.com/kldscp/amnezia.org) | [Documentation](https://docs.amnezia.org) | [Troubleshooting](https://docs.amnezia.org/troubleshooting) > [!TIP] -> If the [Amnezia website](https://amnezia.org) is blocked in your region, you can use an [Alternative website link](https://storage.googleapis.com/amnezia/amnezia.org ). +> If the [Amnezia website](https://amnezia.org) is blocked in your region, you can use an [Alternative website link](https://storage.googleapis.com/kldscp/amnezia.org). - + [All releases](https://github.com/amnezia-vpn/amnezia-client/releases) diff --git a/README_RU.md b/README_RU.md index f9ca7d12..45b506f2 100644 --- a/README_RU.md +++ b/README_RU.md @@ -10,12 +10,12 @@ [![Image](https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/uipic4.png)](https://amnezia.org) -### [Сайт](https://amnezia.org) | [Зеркало на сайт](https://storage.googleapis.com/amnezia/amnezia.org) | [Документация](https://docs.amnezia.org) | [Решение проблем](https://docs.amnezia.org/troubleshooting) +### [Сайт](https://amnezia.org) | [Зеркало на сайт](https://storage.googleapis.com/kldscp/amnezia.org) | [Документация](https://docs.amnezia.org) | [Решение проблем](https://docs.amnezia.org/troubleshooting) > [!TIP] -> Если [сайт Amnezia](https://amnezia.org) заблокирован в вашем регионе, вы можете воспользоваться [ссылкой на зеркало](https://storage.googleapis.com/amnezia/amnezia.org). +> Если [сайт Amnezia](https://amnezia.org) заблокирован в вашем регионе, вы можете воспользоваться [ссылкой на зеркало](https://storage.googleapis.com/kldscp/amnezia.org). - + [Все релизы](https://github.com/amnezia-vpn/amnezia-client/releases) diff --git a/client/3rd-prebuilt b/client/3rd-prebuilt index e555c78b..ba580dc5 160000 --- a/client/3rd-prebuilt +++ b/client/3rd-prebuilt @@ -1 +1 @@ -Subproject commit e555c78bcf44070d5c88bcca54480732c9164f18 +Subproject commit ba580dc5bd7784f7b1e110ff0365f3286e549a61 diff --git a/client/cmake/sources.cmake b/client/cmake/sources.cmake deleted file mode 100644 index c3af531a..00000000 --- a/client/cmake/sources.cmake +++ /dev/null @@ -1,191 +0,0 @@ -set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/..) - -set(HEADERS ${HEADERS} - ${CLIENT_ROOT_DIR}/migrations.h - ${CLIENT_ROOT_DIR}/../ipc/ipc.h - ${CLIENT_ROOT_DIR}/amnezia_application.h - ${CLIENT_ROOT_DIR}/containers/containers_defs.h - ${CLIENT_ROOT_DIR}/core/defs.h - ${CLIENT_ROOT_DIR}/core/errorstrings.h - ${CLIENT_ROOT_DIR}/core/scripts_registry.h - ${CLIENT_ROOT_DIR}/core/server_defs.h - ${CLIENT_ROOT_DIR}/core/api/apiDefs.h - ${CLIENT_ROOT_DIR}/core/qrCodeUtils.h - ${CLIENT_ROOT_DIR}/core/controllers/coreController.h - ${CLIENT_ROOT_DIR}/core/controllers/gatewayController.h - ${CLIENT_ROOT_DIR}/core/controllers/serverController.h - ${CLIENT_ROOT_DIR}/core/controllers/vpnConfigurationController.h - ${CLIENT_ROOT_DIR}/protocols/protocols_defs.h - ${CLIENT_ROOT_DIR}/protocols/qml_register_protocols.h - ${CLIENT_ROOT_DIR}/ui/pages.h - ${CLIENT_ROOT_DIR}/ui/qautostart.h - ${CLIENT_ROOT_DIR}/protocols/vpnprotocol.h - ${CMAKE_CURRENT_BINARY_DIR}/version.h - ${CLIENT_ROOT_DIR}/core/sshclient.h - ${CLIENT_ROOT_DIR}/core/networkUtilities.h - ${CLIENT_ROOT_DIR}/core/serialization/serialization.h - ${CLIENT_ROOT_DIR}/core/serialization/transfer.h - ${CLIENT_ROOT_DIR}/../common/logger/logger.h - ${CLIENT_ROOT_DIR}/utils/qmlUtils.h - ${CLIENT_ROOT_DIR}/core/api/apiUtils.h -) - -# Mozilla headres -set(HEADERS ${HEADERS} - ${CLIENT_ROOT_DIR}/mozilla/models/server.h - ${CLIENT_ROOT_DIR}/mozilla/shared/ipaddress.h - ${CLIENT_ROOT_DIR}/mozilla/shared/leakdetector.h - ${CLIENT_ROOT_DIR}/mozilla/controllerimpl.h - ${CLIENT_ROOT_DIR}/mozilla/localsocketcontroller.h -) - -if(NOT IOS) - set(HEADERS ${HEADERS} - ${CLIENT_ROOT_DIR}/platforms/ios/QRCodeReaderBase.h - ) -endif() - -if(NOT ANDROID) - set(HEADERS ${HEADERS} - ${CLIENT_ROOT_DIR}/ui/notificationhandler.h - ) -endif() - -set(SOURCES ${SOURCES} - ${CLIENT_ROOT_DIR}/migrations.cpp - ${CLIENT_ROOT_DIR}/amnezia_application.cpp - ${CLIENT_ROOT_DIR}/containers/containers_defs.cpp - ${CLIENT_ROOT_DIR}/core/errorstrings.cpp - ${CLIENT_ROOT_DIR}/core/scripts_registry.cpp - ${CLIENT_ROOT_DIR}/core/server_defs.cpp - ${CLIENT_ROOT_DIR}/core/qrCodeUtils.cpp - ${CLIENT_ROOT_DIR}/core/controllers/coreController.cpp - ${CLIENT_ROOT_DIR}/core/controllers/gatewayController.cpp - ${CLIENT_ROOT_DIR}/core/controllers/serverController.cpp - ${CLIENT_ROOT_DIR}/core/controllers/vpnConfigurationController.cpp - ${CLIENT_ROOT_DIR}/protocols/protocols_defs.cpp - ${CLIENT_ROOT_DIR}/ui/qautostart.cpp - ${CLIENT_ROOT_DIR}/protocols/vpnprotocol.cpp - ${CLIENT_ROOT_DIR}/core/sshclient.cpp - ${CLIENT_ROOT_DIR}/core/networkUtilities.cpp - ${CLIENT_ROOT_DIR}/core/serialization/outbound.cpp - ${CLIENT_ROOT_DIR}/core/serialization/inbound.cpp - ${CLIENT_ROOT_DIR}/core/serialization/ss.cpp - ${CLIENT_ROOT_DIR}/core/serialization/ssd.cpp - ${CLIENT_ROOT_DIR}/core/serialization/vless.cpp - ${CLIENT_ROOT_DIR}/core/serialization/trojan.cpp - ${CLIENT_ROOT_DIR}/core/serialization/vmess.cpp - ${CLIENT_ROOT_DIR}/core/serialization/vmess_new.cpp - ${CLIENT_ROOT_DIR}/../common/logger/logger.cpp - ${CLIENT_ROOT_DIR}/utils/qmlUtils.cpp - ${CLIENT_ROOT_DIR}/core/api/apiUtils.cpp -) - -# Mozilla sources -set(SOURCES ${SOURCES} - ${CLIENT_ROOT_DIR}/mozilla/models/server.cpp - ${CLIENT_ROOT_DIR}/mozilla/shared/ipaddress.cpp - ${CLIENT_ROOT_DIR}/mozilla/shared/leakdetector.cpp - ${CLIENT_ROOT_DIR}/mozilla/localsocketcontroller.cpp -) - -if(NOT IOS) - set(SOURCES ${SOURCES} - ${CLIENT_ROOT_DIR}/platforms/ios/QRCodeReaderBase.cpp - ) -endif() - -if(NOT ANDROID) - set(SOURCES ${SOURCES} - ${CLIENT_ROOT_DIR}/ui/notificationhandler.cpp - ) -endif() - -file(GLOB COMMON_FILES_H CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/*.h) -file(GLOB COMMON_FILES_CPP CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/*.cpp) - -file(GLOB_RECURSE PAGE_LOGIC_H CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/ui/pages_logic/*.h) -file(GLOB_RECURSE PAGE_LOGIC_CPP CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/ui/pages_logic/*.cpp) - -file(GLOB CONFIGURATORS_H CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/configurators/*.h) -file(GLOB CONFIGURATORS_CPP CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/configurators/*.cpp) - -file(GLOB UI_MODELS_H CONFIGURE_DEPENDS - ${CLIENT_ROOT_DIR}/ui/models/*.h - ${CLIENT_ROOT_DIR}/ui/models/protocols/*.h - ${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 - ${CLIENT_ROOT_DIR}/ui/models/services/*.cpp - ${CLIENT_ROOT_DIR}/ui/models/api/*.cpp -) - -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 -) - -set(HEADERS ${HEADERS} - ${COMMON_FILES_H} - ${PAGE_LOGIC_H} - ${CONFIGURATORS_H} - ${UI_MODELS_H} - ${UI_CONTROLLERS_H} -) -set(SOURCES ${SOURCES} - ${COMMON_FILES_CPP} - ${PAGE_LOGIC_CPP} - ${CONFIGURATORS_CPP} - ${UI_MODELS_CPP} - ${UI_CONTROLLERS_CPP} -) - -if(WIN32) - set(HEADERS ${HEADERS} - ${CLIENT_ROOT_DIR}/protocols/ikev2_vpn_protocol_windows.h - ) - - set(SOURCES ${SOURCES} - ${CLIENT_ROOT_DIR}/protocols/ikev2_vpn_protocol_windows.cpp - ) - - set(RESOURCES ${RESOURCES} - ${CMAKE_CURRENT_BINARY_DIR}/amneziavpn.rc - ) -endif() - -if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID)) - message("Client desktop build") - add_compile_definitions(AMNEZIA_DESKTOP) - - set(HEADERS ${HEADERS} - ${CLIENT_ROOT_DIR}/core/ipcclient.h - ${CLIENT_ROOT_DIR}/core/privileged_process.h - ${CLIENT_ROOT_DIR}/ui/systemtray_notificationhandler.h - ${CLIENT_ROOT_DIR}/protocols/openvpnprotocol.h - ${CLIENT_ROOT_DIR}/protocols/openvpnovercloakprotocol.h - ${CLIENT_ROOT_DIR}/protocols/shadowsocksvpnprotocol.h - ${CLIENT_ROOT_DIR}/protocols/wireguardprotocol.h - ${CLIENT_ROOT_DIR}/protocols/xrayprotocol.h - ${CLIENT_ROOT_DIR}/protocols/awgprotocol.h - ) - - set(SOURCES ${SOURCES} - ${CLIENT_ROOT_DIR}/core/ipcclient.cpp - ${CLIENT_ROOT_DIR}/core/privileged_process.cpp - ${CLIENT_ROOT_DIR}/ui/systemtray_notificationhandler.cpp - ${CLIENT_ROOT_DIR}/protocols/openvpnprotocol.cpp - ${CLIENT_ROOT_DIR}/protocols/openvpnovercloakprotocol.cpp - ${CLIENT_ROOT_DIR}/protocols/shadowsocksvpnprotocol.cpp - ${CLIENT_ROOT_DIR}/protocols/wireguardprotocol.cpp - ${CLIENT_ROOT_DIR}/protocols/xrayprotocol.cpp - ${CLIENT_ROOT_DIR}/protocols/awgprotocol.cpp - ) -endif() diff --git a/client/core/api/apiDefs.h b/client/core/api/apiDefs.h deleted file mode 100644 index 41dd80ba..00000000 --- a/client/core/api/apiDefs.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef APIDEFS_H -#define APIDEFS_H - -#include - -namespace apiDefs -{ - enum ConfigType { - AmneziaFreeV2 = 0, - AmneziaFreeV3, - AmneziaPremiumV1, - AmneziaPremiumV2, - SelfHosted - }; - - enum ConfigSource { - Telegram = 1, - AmneziaGateway - }; - - namespace key - { - constexpr QLatin1String configVersion("config_version"); - - constexpr QLatin1String apiConfig("api_config"); - constexpr QLatin1String stackType("stack_type"); - constexpr QLatin1String serviceType("service_type"); - - constexpr QLatin1String vpnKey("vpn_key"); - - constexpr QLatin1String installationUuid("installation_uuid"); - constexpr QLatin1String workerLastUpdated("worker_last_updated"); - constexpr QLatin1String lastDownloaded("last_downloaded"); - constexpr QLatin1String sourceType("source_type"); - - constexpr QLatin1String serverCountryCode("server_country_code"); - constexpr QLatin1String serverCountryName("server_country_name"); - - constexpr QLatin1String osVersion("os_version"); - - constexpr QLatin1String availableCountries("available_countries"); - constexpr QLatin1String activeDeviceCount("active_device_count"); - constexpr QLatin1String maxDeviceCount("max_device_count"); - constexpr QLatin1String subscriptionEndDate("subscription_end_date"); - constexpr QLatin1String issuedConfigs("issued_configs"); - } - - const int requestTimeoutMsecs = 12 * 1000; // 12 secs -} - -#endif // APIDEFS_H diff --git a/client/core/api/apiUtils.cpp b/client/core/api/apiUtils.cpp deleted file mode 100644 index 9f518b52..00000000 --- a/client/core/api/apiUtils.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "apiUtils.h" - -#include -#include - -bool apiUtils::isSubscriptionExpired(const QString &subscriptionEndDate) -{ - QDateTime now = QDateTime::currentDateTime(); - QDateTime endDate = QDateTime::fromString(subscriptionEndDate, Qt::ISODateWithMs); - return endDate < now; -} - -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; - default: return false; - } -} - -apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObject) -{ - auto configVersion = serverConfigObject.value(apiDefs::key::configVersion).toInt(); - switch (configVersion) { - case apiDefs::ConfigSource::Telegram: { - }; - case apiDefs::ConfigSource::AmneziaGateway: { - constexpr QLatin1String stackPremium("prem"); - constexpr QLatin1String stackFree("free"); - - constexpr QLatin1String servicePremium("amnezia-premium"); - constexpr QLatin1String serviceFree("amnezia-free"); - - auto apiConfigObject = serverConfigObject.value(apiDefs::key::apiConfig).toObject(); - auto stackType = apiConfigObject.value(apiDefs::key::stackType).toString(); - auto serviceType = apiConfigObject.value(apiDefs::key::serviceType).toString(); - - if (serviceType == servicePremium || stackType == stackPremium) { - return apiDefs::ConfigType::AmneziaPremiumV2; - } else if (serviceType == serviceFree || stackType == stackFree) { - return apiDefs::ConfigType::AmneziaFreeV3; - } - } - default: { - return apiDefs::ConfigType::SelfHosted; - } - }; -} - -apiDefs::ConfigSource apiUtils::getConfigSource(const QJsonObject &serverConfigObject) -{ - return static_cast(serverConfigObject.value(apiDefs::key::configVersion).toInt()); -} - -amnezia::ErrorCode apiUtils::checkNetworkReplyErrors(const QList &sslErrors, QNetworkReply *reply) -{ - const int httpStatusCodeConflict = 409; - const int httpStatusCodeNotFound = 404; - - if (!sslErrors.empty()) { - qDebug().noquote() << sslErrors; - return amnezia::ErrorCode::ApiConfigSslError; - } else if (reply->error() == QNetworkReply::NoError) { - return amnezia::ErrorCode::NoError; - } else if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError - || reply->error() == QNetworkReply::NetworkError::TimeoutError) { - return amnezia::ErrorCode::ApiConfigTimeoutError; - } else { - QString err = reply->errorString(); - int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - qDebug() << QString::fromUtf8(reply->readAll()); - qDebug() << reply->error(); - qDebug() << err; - qDebug() << httpStatusCode; - if (httpStatusCode == httpStatusCodeConflict) { - return amnezia::ErrorCode::ApiConfigLimitError; - } else if (httpStatusCode == httpStatusCodeNotFound) { - return amnezia::ErrorCode::ApiNotFoundError; - } - return amnezia::ErrorCode::ApiConfigDownloadError; - } - - qDebug() << "something went wrong"; - return amnezia::ErrorCode::InternalError; -} diff --git a/client/core/api/apiUtils.h b/client/core/api/apiUtils.h deleted file mode 100644 index 82ac315b..00000000 --- a/client/core/api/apiUtils.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef APIUTILS_H -#define APIUTILS_H - -#include -#include - -#include "apiDefs.h" -#include "core/defs.h" - -namespace apiUtils -{ - bool isServerFromApi(const QJsonObject &serverConfigObject); - - bool isSubscriptionExpired(const QString &subscriptionEndDate); - - apiDefs::ConfigType getConfigType(const QJsonObject &serverConfigObject); - apiDefs::ConfigSource getConfigSource(const QJsonObject &serverConfigObject); - - amnezia::ErrorCode checkNetworkReplyErrors(const QList &sslErrors, QNetworkReply *reply); -} - -#endif // APIUTILS_H diff --git a/client/core/controllers/coreController.cpp b/client/core/controllers/coreController.cpp deleted file mode 100644 index 82232c99..00000000 --- a/client/core/controllers/coreController.cpp +++ /dev/null @@ -1,345 +0,0 @@ -#include "coreController.h" - -#include - -#if defined(Q_OS_ANDROID) - #include "core/installedAppsImageProvider.h" - #include "platforms/android/android_controller.h" -#endif - -#if defined(Q_OS_IOS) - #include "platforms/ios/ios_controller.h" - #include -#endif - -CoreController::CoreController(const QSharedPointer &vpnConnection, const std::shared_ptr &settings, - QQmlApplicationEngine *engine, QObject *parent) - : QObject(parent), m_vpnConnection(vpnConnection), m_settings(settings), m_engine(engine) -{ - initModels(); - initControllers(); - initSignalHandlers(); - - initAndroidController(); - initAppleController(); - - initNotificationHandler(); - - auto locale = m_settings->getAppLanguage(); - m_translator.reset(new QTranslator()); - updateTranslator(locale); -} - -void CoreController::initModels() -{ - m_containersModel.reset(new ContainersModel(this)); - m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get()); - - m_defaultServerContainersModel.reset(new ContainersModel(this)); - m_engine->rootContext()->setContextProperty("DefaultServerContainersModel", m_defaultServerContainersModel.get()); - - m_serversModel.reset(new ServersModel(m_settings, this)); - m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get()); - - m_languageModel.reset(new LanguageModel(m_settings, this)); - m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get()); - - m_sitesModel.reset(new SitesModel(m_settings, this)); - m_engine->rootContext()->setContextProperty("SitesModel", m_sitesModel.get()); - - m_appSplitTunnelingModel.reset(new AppSplitTunnelingModel(m_settings, this)); - m_engine->rootContext()->setContextProperty("AppSplitTunnelingModel", m_appSplitTunnelingModel.get()); - - m_protocolsModel.reset(new ProtocolsModel(m_settings, this)); - m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get()); - - m_openVpnConfigModel.reset(new OpenVpnConfigModel(this)); - m_engine->rootContext()->setContextProperty("OpenVpnConfigModel", m_openVpnConfigModel.get()); - - m_shadowSocksConfigModel.reset(new ShadowSocksConfigModel(this)); - m_engine->rootContext()->setContextProperty("ShadowSocksConfigModel", m_shadowSocksConfigModel.get()); - - m_cloakConfigModel.reset(new CloakConfigModel(this)); - m_engine->rootContext()->setContextProperty("CloakConfigModel", m_cloakConfigModel.get()); - - m_wireGuardConfigModel.reset(new WireGuardConfigModel(this)); - m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireGuardConfigModel.get()); - - m_awgConfigModel.reset(new AwgConfigModel(this)); - m_engine->rootContext()->setContextProperty("AwgConfigModel", m_awgConfigModel.get()); - - m_xrayConfigModel.reset(new XrayConfigModel(this)); - m_engine->rootContext()->setContextProperty("XrayConfigModel", m_xrayConfigModel.get()); - -#ifdef Q_OS_WINDOWS - m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this)); - m_engine->rootContext()->setContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel.get()); -#endif - - m_sftpConfigModel.reset(new SftpConfigModel(this)); - m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get()); - - m_socks5ConfigModel.reset(new Socks5ProxyConfigModel(this)); - m_engine->rootContext()->setContextProperty("Socks5ProxyConfigModel", m_socks5ConfigModel.get()); - - m_clientManagementModel.reset(new ClientManagementModel(m_settings, this)); - m_engine->rootContext()->setContextProperty("ClientManagementModel", m_clientManagementModel.get()); - - m_apiServicesModel.reset(new ApiServicesModel(this)); - m_engine->rootContext()->setContextProperty("ApiServicesModel", m_apiServicesModel.get()); - - m_apiCountryModel.reset(new ApiCountryModel(this)); - m_engine->rootContext()->setContextProperty("ApiCountryModel", m_apiCountryModel.get()); - - m_apiAccountInfoModel.reset(new ApiAccountInfoModel(this)); - m_engine->rootContext()->setContextProperty("ApiAccountInfoModel", m_apiAccountInfoModel.get()); - - m_apiDevicesModel.reset(new ApiDevicesModel(m_settings, this)); - m_engine->rootContext()->setContextProperty("ApiDevicesModel", m_apiDevicesModel.get()); -} - -void CoreController::initControllers() -{ - m_connectionController.reset( - new ConnectionController(m_serversModel, m_containersModel, m_clientManagementModel, m_vpnConnection, m_settings)); - m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get()); - - m_pageController.reset(new PageController(m_serversModel, m_settings)); - m_engine->rootContext()->setContextProperty("PageController", m_pageController.get()); - - m_focusController.reset(new FocusController(m_engine, this)); - m_engine->rootContext()->setContextProperty("FocusController", m_focusController.get()); - - 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::currentContainerUpdated, m_connectionController.get(), - &ConnectionController::onCurrentContainerUpdated); // TODO remove this - - 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_engine->rootContext()->setContextProperty("ExportController", m_exportController.get()); - - m_settingsController.reset( - new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_sitesModel, m_appSplitTunnelingModel, m_settings)); - m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get()); - - m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel)); - m_engine->rootContext()->setContextProperty("SitesController", m_sitesController.get()); - - m_appSplitTunnelingController.reset(new AppSplitTunnelingController(m_settings, m_appSplitTunnelingModel)); - m_engine->rootContext()->setContextProperty("AppSplitTunnelingController", m_appSplitTunnelingController.get()); - - m_systemController.reset(new SystemController(m_settings)); - m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get()); - - m_apiSettingsController.reset( - new ApiSettingsController(m_serversModel, m_apiAccountInfoModel, m_apiCountryModel, m_apiDevicesModel, m_settings)); - m_engine->rootContext()->setContextProperty("ApiSettingsController", m_apiSettingsController.get()); - - m_apiConfigsController.reset(new ApiConfigsController(m_serversModel, m_apiServicesModel, m_settings)); - m_engine->rootContext()->setContextProperty("ApiConfigsController", m_apiConfigsController.get()); -} - -void CoreController::initAndroidController() -{ -#ifdef Q_OS_ANDROID - if (!AndroidController::initLogging()) { - qFatal("Android logging initialization failed"); - } - AndroidController::instance()->setSaveLogs(m_settings->isSaveLogs()); - 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::serverRemoved, AndroidController::instance(), &AndroidController::resetLastServer); - - connect(m_settings.get(), &Settings::settingsCleared, []() { AndroidController::instance()->resetLastServer(-1); }); - - connect(AndroidController::instance(), &AndroidController::initConnectionState, this, [this](Vpn::ConnectionState state) { - m_connectionController->onConnectionStateChanged(state); - if (m_vpnConnection) - m_vpnConnection->restoreConnection(); - }); - if (!AndroidController::instance()->initialize()) { - qFatal("Android controller initialization failed"); - } - - connect(AndroidController::instance(), &AndroidController::importConfigFromOutside, this, [this](QString data) { - emit m_pageController->goToPageHome(); - m_importController->extractConfigFromData(data); - data.clear(); - emit m_pageController->goToPageViewConfig(); - }); - - m_engine->addImageProvider(QLatin1String("installedAppImage"), new InstalledAppsImageProvider); -#endif -} - -void CoreController::initAppleController() -{ -#ifdef Q_OS_IOS - IosController::Instance()->initialize(); - connect(IosController::Instance(), &IosController::importConfigFromOutside, this, [this](QString data) { - emit m_pageController->goToPageHome(); - m_importController->extractConfigFromData(data); - emit m_pageController->goToPageViewConfig(); - }); - - connect(IosController::Instance(), &IosController::importBackupFromOutside, this, [this](QString filePath) { - emit m_pageController->goToPageHome(); - m_pageController->goToPageSettingsBackup(); - emit m_settingsController->importBackupFromOutside(filePath); - }); - - QTimer::singleShot(0, this, [this]() { AmneziaVPN::toggleScreenshots(m_settings->isScreenshotsEnabled()); }); - - connect(m_settings.get(), &Settings::screenshotsEnabledChanged, [](bool enabled) { AmneziaVPN::toggleScreenshots(enabled); }); -#endif -} - -void CoreController::initSignalHandlers() -{ - initErrorMessagesHandler(); - - initApiCountryModelUpdateHandler(); - initContainerModelUpdateHandler(); - initAdminConfigRevokedHandler(); - initPassphraseRequestHandler(); - initTranslationsUpdatedHandler(); - initAutoConnectHandler(); - initAmneziaDnsToggledHandler(); - initPrepareConfigHandler(); -} - -void CoreController::initNotificationHandler() -{ -#ifndef Q_OS_ANDROID - m_notificationHandler.reset(NotificationHandler::create(nullptr)); - - connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, m_notificationHandler.get(), - &NotificationHandler::setConnectionState); - - connect(m_notificationHandler.get(), &NotificationHandler::raiseRequested, m_pageController.get(), &PageController::raiseMainWindow); - connect(m_notificationHandler.get(), &NotificationHandler::connectRequested, m_connectionController.get(), - static_cast(&ConnectionController::openConnection)); - connect(m_notificationHandler.get(), &NotificationHandler::disconnectRequested, m_connectionController.get(), - &ConnectionController::closeConnection); - connect(this, &CoreController::translationsUpdated, m_notificationHandler.get(), &NotificationHandler::onTranslationsUpdated); -#endif -} - -void CoreController::updateTranslator(const QLocale &locale) -{ - if (!m_translator->isEmpty()) { - QCoreApplication::removeTranslator(m_translator.get()); - } - - QString strFileName = QString(":/translations/amneziavpn") + QLatin1String("_") + locale.name() + ".qm"; - if (m_translator->load(strFileName)) { - if (QCoreApplication::installTranslator(m_translator.get())) { - m_settings->setAppLanguage(locale); - } - } else { - m_settings->setAppLanguage(QLocale::English); - } - - m_engine->retranslate(); - - emit translationsUpdated(); -} - -void CoreController::initErrorMessagesHandler() -{ - connect(m_connectionController.get(), &ConnectionController::connectionErrorOccurred, this, [this](ErrorCode errorCode) { - emit m_pageController->showErrorMessage(errorCode); - emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); - }); - - connect(m_apiConfigsController.get(), &ApiConfigsController::errorOccurred, m_pageController.get(), - qOverload(&PageController::showErrorMessage)); -} - -void CoreController::setQmlRoot() -{ - m_systemController->setQmlRoot(m_engine->rootObjects().value(0)); -} - -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() -{ - connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(), &ContainersModel::updateModel); - connect(m_serversModel.get(), &ServersModel::defaultServerContainersUpdated, m_defaultServerContainersModel.get(), - &ContainersModel::updateModel); - m_serversModel->resetModel(); -} - -void CoreController::initAdminConfigRevokedHandler() -{ - connect(m_clientManagementModel.get(), &ClientManagementModel::adminConfigRevoked, m_serversModel.get(), - &ServersModel::clearCachedProfile); -} - -void CoreController::initPassphraseRequestHandler() -{ - connect(m_installController.get(), &InstallController::passphraseRequestStarted, m_pageController.get(), - &PageController::showPassphraseRequestDrawer); - connect(m_pageController.get(), &PageController::passphraseRequestDrawerClosed, m_installController.get(), - &InstallController::setEncryptedPassphrase); -} - -void CoreController::initTranslationsUpdatedHandler() -{ - connect(m_languageModel.get(), &LanguageModel::updateTranslations, this, &CoreController::updateTranslator); - connect(this, &CoreController::translationsUpdated, m_languageModel.get(), &LanguageModel::translationsUpdated); - connect(this, &CoreController::translationsUpdated, m_connectionController.get(), &ConnectionController::onTranslationsUpdated); -} - -void CoreController::initAutoConnectHandler() -{ - if (m_settingsController->isAutoConnectEnabled() && m_serversModel->getDefaultServerIndex() >= 0) { - QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); }); - } -} - -void CoreController::initAmneziaDnsToggledHandler() -{ - connect(m_settingsController.get(), &SettingsController::amneziaDnsToggled, m_serversModel.get(), &ServersModel::toggleAmneziaDns); -} - -void CoreController::initPrepareConfigHandler() -{ - connect(m_connectionController.get(), &ConnectionController::prepareConfig, this, [this]() { - emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Preparing); - - if (!m_apiConfigsController->isConfigValid()) { - emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); - return; - } - - if (!m_installController->isConfigValid()) { - emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); - return; - } - - m_connectionController->openConnection(); - }); -} - -QSharedPointer CoreController::pageController() const -{ - return m_pageController; -} diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h deleted file mode 100644 index 700504af..00000000 --- a/client/core/controllers/coreController.h +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef CORECONTROLLER_H -#define CORECONTROLLER_H - -#include -#include -#include - -#include "ui/controllers/api/apiConfigsController.h" -#include "ui/controllers/api/apiSettingsController.h" -#include "ui/controllers/appSplitTunnelingController.h" -#include "ui/controllers/connectionController.h" -#include "ui/controllers/exportController.h" -#include "ui/controllers/focusController.h" -#include "ui/controllers/importController.h" -#include "ui/controllers/installController.h" -#include "ui/controllers/pageController.h" -#include "ui/controllers/settingsController.h" -#include "ui/controllers/sitesController.h" -#include "ui/controllers/systemController.h" - -#include "ui/models/containers_model.h" -#include "ui/models/languageModel.h" -#include "ui/models/protocols/cloakConfigModel.h" -#ifdef Q_OS_WINDOWS - #include "ui/models/protocols/ikev2ConfigModel.h" -#endif -#include "ui/models/api/apiAccountInfoModel.h" -#include "ui/models/api/apiCountryModel.h" -#include "ui/models/api/apiDevicesModel.h" -#include "ui/models/api/apiServicesModel.h" -#include "ui/models/appSplitTunnelingModel.h" -#include "ui/models/clientManagementModel.h" -#include "ui/models/protocols/awgConfigModel.h" -#include "ui/models/protocols/openvpnConfigModel.h" -#include "ui/models/protocols/shadowsocksConfigModel.h" -#include "ui/models/protocols/wireguardConfigModel.h" -#include "ui/models/protocols/xrayConfigModel.h" -#include "ui/models/protocols_model.h" -#include "ui/models/servers_model.h" -#include "ui/models/services/sftpConfigModel.h" -#include "ui/models/services/socks5ProxyConfigModel.h" -#include "ui/models/sites_model.h" - -#ifndef Q_OS_ANDROID - #include "ui/notificationhandler.h" -#endif - -class CoreController : public QObject -{ - Q_OBJECT - -public: - explicit CoreController(const QSharedPointer &vpnConnection, const std::shared_ptr &settings, - QQmlApplicationEngine *engine, QObject *parent = nullptr); - - QSharedPointer pageController() const; - void setQmlRoot(); - -signals: - void translationsUpdated(); - -private: - void initModels(); - void initControllers(); - void initAndroidController(); - void initAppleController(); - void initSignalHandlers(); - - void initNotificationHandler(); - - void updateTranslator(const QLocale &locale); - - void initErrorMessagesHandler(); - - void initApiCountryModelUpdateHandler(); - void initContainerModelUpdateHandler(); - void initAdminConfigRevokedHandler(); - void initPassphraseRequestHandler(); - void initTranslationsUpdatedHandler(); - void initAutoConnectHandler(); - void initAmneziaDnsToggledHandler(); - void initPrepareConfigHandler(); - - QQmlApplicationEngine *m_engine {}; // TODO use parent child system here? - std::shared_ptr m_settings; - QSharedPointer m_vpnConnection; - QSharedPointer m_translator; - -#ifndef Q_OS_ANDROID - QScopedPointer m_notificationHandler; -#endif - - QMetaObject::Connection m_reloadConfigErrorOccurredConnection; - - QScopedPointer m_connectionController; - QScopedPointer m_focusController; - QSharedPointer m_pageController; // TODO - QScopedPointer m_installController; - QScopedPointer m_importController; - QScopedPointer m_exportController; - QScopedPointer m_settingsController; - QScopedPointer m_sitesController; - QScopedPointer m_systemController; - QScopedPointer m_appSplitTunnelingController; - - QScopedPointer m_apiSettingsController; - QScopedPointer m_apiConfigsController; - - QSharedPointer m_containersModel; - QSharedPointer m_defaultServerContainersModel; - QSharedPointer m_serversModel; - QSharedPointer m_languageModel; - QSharedPointer m_protocolsModel; - QSharedPointer m_sitesModel; - QSharedPointer m_appSplitTunnelingModel; - QSharedPointer m_clientManagementModel; - - QSharedPointer m_apiServicesModel; - QSharedPointer m_apiCountryModel; - QSharedPointer m_apiAccountInfoModel; - QSharedPointer m_apiDevicesModel; - - QScopedPointer m_openVpnConfigModel; - QScopedPointer m_shadowSocksConfigModel; - QScopedPointer m_cloakConfigModel; - QScopedPointer m_xrayConfigModel; - QScopedPointer m_wireGuardConfigModel; - QScopedPointer m_awgConfigModel; -#ifdef Q_OS_WINDOWS - QScopedPointer m_ikev2ConfigModel; -#endif - QScopedPointer m_sftpConfigModel; - QScopedPointer m_socks5ConfigModel; -}; - -#endif // CORECONTROLLER_H diff --git a/client/core/controllers/gatewayController.cpp b/client/core/controllers/gatewayController.cpp deleted file mode 100644 index 15776328..00000000 --- a/client/core/controllers/gatewayController.cpp +++ /dev/null @@ -1,303 +0,0 @@ -#include "gatewayController.h" - -#include -#include - -#include -#include -#include -#include - -#include "QBlockCipher.h" -#include "QRsa.h" - -#include "amnezia_application.h" -#include "core/api/apiUtils.h" -#include "utilities.h" - -namespace -{ - namespace configKey - { - constexpr char aesKey[] = "aes_key"; - constexpr char aesIv[] = "aes_iv"; - constexpr char aesSalt[] = "aes_salt"; - - constexpr char apiPayload[] = "api_payload"; - constexpr char keyPayload[] = "key_payload"; - } -} - -GatewayController::GatewayController(const QString &gatewayEndpoint, bool isDevEnvironment, int requestTimeoutMsecs, QObject *parent) - : QObject(parent), m_gatewayEndpoint(gatewayEndpoint), m_isDevEnvironment(isDevEnvironment), m_requestTimeoutMsecs(requestTimeoutMsecs) -{ -} - -ErrorCode GatewayController::get(const QString &endpoint, QByteArray &responseBody) -{ -#ifdef Q_OS_IOS - IosController::Instance()->requestInetAccess(); - QThread::msleep(10); -#endif - - QNetworkRequest request; - request.setTransferTimeout(m_requestTimeoutMsecs); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - request.setUrl(QString(endpoint).arg(m_gatewayEndpoint)); - - QNetworkReply *reply; - reply = amnApp->networkManager()->get(request); - - QEventLoop wait; - QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit); - - QList sslErrors; - connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList &errors) { sslErrors = errors; }); - wait.exec(); - - responseBody = reply->readAll(); - - if (sslErrors.isEmpty() && shouldBypassProxy(reply, responseBody, false)) { - auto requestFunction = [&request, &responseBody](const QString &url) { - request.setUrl(url); - return amnApp->networkManager()->get(request); - }; - - auto replyProcessingFunction = [&responseBody, &reply, &sslErrors, this](QNetworkReply *nestedReply, - const QList &nestedSslErrors) { - responseBody = nestedReply->readAll(); - if (!sslErrors.isEmpty() || !shouldBypassProxy(nestedReply, responseBody, false)) { - sslErrors = nestedSslErrors; - reply = nestedReply; - return true; - } - return false; - }; - - bypassProxy(endpoint, reply, requestFunction, replyProcessingFunction); - } - - auto errorCode = apiUtils::checkNetworkReplyErrors(sslErrors, reply); - reply->deleteLater(); - - return errorCode; -} - -ErrorCode GatewayController::post(const QString &endpoint, const QJsonObject apiPayload, QByteArray &responseBody) -{ -#ifdef Q_OS_IOS - IosController::Instance()->requestInetAccess(); - QThread::msleep(10); -#endif - - QNetworkRequest request; - request.setTransferTimeout(m_requestTimeoutMsecs); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - request.setUrl(endpoint.arg(m_gatewayEndpoint)); - - QSimpleCrypto::QBlockCipher blockCipher; - QByteArray key = blockCipher.generatePrivateSalt(32); - QByteArray iv = blockCipher.generatePrivateSalt(32); - QByteArray salt = blockCipher.generatePrivateSalt(8); - - QJsonObject keyPayload; - keyPayload[configKey::aesKey] = QString(key.toBase64()); - keyPayload[configKey::aesIv] = QString(iv.toBase64()); - keyPayload[configKey::aesSalt] = QString(salt.toBase64()); - - QByteArray encryptedKeyPayload; - QByteArray encryptedApiPayload; - try { - QSimpleCrypto::QRsa rsa; - - EVP_PKEY *publicKey = nullptr; - try { - QByteArray rsaKey = m_isDevEnvironment ? DEV_AGW_PUBLIC_KEY : PROD_AGW_PUBLIC_KEY; - QSimpleCrypto::QRsa rsa; - publicKey = rsa.getPublicKeyFromByteArray(rsaKey); - } catch (...) { - Utils::logException(); - qCritical() << "error loading public key from environment variables"; - return ErrorCode::ApiMissingAgwPublicKey; - } - - encryptedKeyPayload = rsa.encrypt(QJsonDocument(keyPayload).toJson(), publicKey, RSA_PKCS1_PADDING); - EVP_PKEY_free(publicKey); - - encryptedApiPayload = blockCipher.encryptAesBlockCipher(QJsonDocument(apiPayload).toJson(), key, iv, "", salt); - } catch (...) { // todo change error handling in QSimpleCrypto? - Utils::logException(); - qCritical() << "error when encrypting the request body"; - return ErrorCode::ApiConfigDecryptionError; - } - - QJsonObject requestBody; - requestBody[configKey::keyPayload] = QString(encryptedKeyPayload.toBase64()); - requestBody[configKey::apiPayload] = QString(encryptedApiPayload.toBase64()); - - QNetworkReply *reply = amnApp->networkManager()->post(request, QJsonDocument(requestBody).toJson()); - - QEventLoop wait; - connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit); - - QList sslErrors; - connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList &errors) { sslErrors = errors; }); - wait.exec(); - - QByteArray encryptedResponseBody = reply->readAll(); - - if (sslErrors.isEmpty() && shouldBypassProxy(reply, encryptedResponseBody, true, key, iv, salt)) { - auto requestFunction = [&request, &encryptedResponseBody, &requestBody](const QString &url) { - request.setUrl(url); - return amnApp->networkManager()->post(request, QJsonDocument(requestBody).toJson()); - }; - - auto replyProcessingFunction = [&encryptedResponseBody, &reply, &sslErrors, &key, &iv, &salt, - this](QNetworkReply *nestedReply, const QList &nestedSslErrors) { - encryptedResponseBody = nestedReply->readAll(); - if (!sslErrors.isEmpty() || !shouldBypassProxy(nestedReply, encryptedResponseBody, true, key, iv, salt)) { - sslErrors = nestedSslErrors; - reply = nestedReply; - return true; - } - return false; - }; - - bypassProxy(endpoint, reply, requestFunction, replyProcessingFunction); - } - - auto errorCode = apiUtils::checkNetworkReplyErrors(sslErrors, reply); - reply->deleteLater(); - if (errorCode) { - return errorCode; - } - - try { - responseBody = blockCipher.decryptAesBlockCipher(encryptedResponseBody, key, iv, "", salt); - return ErrorCode::NoError; - } catch (...) { // todo change error handling in QSimpleCrypto? - Utils::logException(); - qCritical() << "error when decrypting the request body"; - return ErrorCode::ApiConfigDecryptionError; - } -} - -QStringList GatewayController::getProxyUrls() -{ - QNetworkRequest request; - request.setTransferTimeout(m_requestTimeoutMsecs); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QEventLoop wait; - QList sslErrors; - QNetworkReply *reply; - - QStringList proxyStorageUrl; - if (m_isDevEnvironment) { - proxyStorageUrl = QStringList { DEV_S3_ENDPOINT }; - } else { - proxyStorageUrl = QStringList { PROD_S3_ENDPOINT }; - } - - QByteArray key = m_isDevEnvironment ? DEV_AGW_PUBLIC_KEY : PROD_AGW_PUBLIC_KEY; - - for (const auto &proxyStorageUrl : proxyStorageUrl) { - request.setUrl(proxyStorageUrl); - reply = amnApp->networkManager()->get(request); - - connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit); - connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList &errors) { sslErrors = errors; }); - wait.exec(); - - if (reply->error() == QNetworkReply::NetworkError::NoError) { - break; - } - reply->deleteLater(); - } - - auto encryptedResponseBody = reply->readAll(); - reply->deleteLater(); - - EVP_PKEY *privateKey = nullptr; - QByteArray responseBody; - try { - if (!m_isDevEnvironment) { - QCryptographicHash hash(QCryptographicHash::Sha512); - hash.addData(key); - QByteArray hashResult = hash.result().toHex(); - - QByteArray key = QByteArray::fromHex(hashResult.left(64)); - QByteArray iv = QByteArray::fromHex(hashResult.mid(64, 32)); - - QByteArray ba = QByteArray::fromBase64(encryptedResponseBody); - - QSimpleCrypto::QBlockCipher blockCipher; - responseBody = blockCipher.decryptAesBlockCipher(ba, key, iv); - } else { - responseBody = encryptedResponseBody; - } - } catch (...) { - Utils::logException(); - qCritical() << "error loading private key from environment variables or decrypting payload" << encryptedResponseBody; - return {}; - } - - auto endpointsArray = QJsonDocument::fromJson(responseBody).array(); - - QStringList endpoints; - for (const auto &endpoint : endpointsArray) { - endpoints.push_back(endpoint.toString()); - } - return endpoints; -} - -bool GatewayController::shouldBypassProxy(QNetworkReply *reply, const QByteArray &responseBody, bool checkEncryption, const QByteArray &key, - const QByteArray &iv, const QByteArray &salt) -{ - if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError || reply->error() == QNetworkReply::NetworkError::TimeoutError) { - qDebug() << "Timeout occurred"; - return true; - } else if (responseBody.contains("html")) { - qDebug() << "The response contains an html tag"; - return true; - } else if (checkEncryption) { - try { - QSimpleCrypto::QBlockCipher blockCipher; - static_cast(blockCipher.decryptAesBlockCipher(responseBody, key, iv, "", salt)); - } catch (...) { - qDebug() << "Failed to decrypt the data"; - return true; - } - } - return false; -} - -void GatewayController::bypassProxy(const QString &endpoint, QNetworkReply *reply, - std::function requestFunction, - std::function &sslErrors)> replyProcessingFunction) -{ - QStringList proxyUrls = getProxyUrls(); - std::random_device randomDevice; - std::mt19937 generator(randomDevice()); - std::shuffle(proxyUrls.begin(), proxyUrls.end(), generator); - - QEventLoop wait; - QList sslErrors; - QByteArray responseBody; - - for (const QString &proxyUrl : proxyUrls) { - qDebug() << "Go to the next endpoint"; - reply->deleteLater(); // delete the previous reply - reply = requestFunction(endpoint.arg(proxyUrl)); - - QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit); - connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList &errors) { sslErrors = errors; }); - wait.exec(); - - if (!replyProcessingFunction(reply, sslErrors)) { - break; - } - } -} diff --git a/client/core/controllers/gatewayController.h b/client/core/controllers/gatewayController.h deleted file mode 100644 index 45d989f0..00000000 --- a/client/core/controllers/gatewayController.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef GATEWAYCONTROLLER_H -#define GATEWAYCONTROLLER_H - -#include -#include - -#include "core/defs.h" - -#ifdef Q_OS_IOS - #include "platforms/ios/ios_controller.h" -#endif - -class GatewayController : public QObject -{ - Q_OBJECT - -public: - explicit GatewayController(const QString &gatewayEndpoint, bool isDevEnvironment, int requestTimeoutMsecs, QObject *parent = nullptr); - - amnezia::ErrorCode get(const QString &endpoint, QByteArray &responseBody); - amnezia::ErrorCode post(const QString &endpoint, const QJsonObject apiPayload, QByteArray &responseBody); - -private: - QStringList getProxyUrls(); - bool shouldBypassProxy(QNetworkReply *reply, const QByteArray &responseBody, bool checkEncryption, const QByteArray &key = "", - const QByteArray &iv = "", const QByteArray &salt = ""); - void bypassProxy(const QString &endpoint, QNetworkReply *reply, std::function requestFunction, - std::function &sslErrors)> replyProcessingFunction); - - int m_requestTimeoutMsecs; - QString m_gatewayEndpoint; - bool m_isDevEnvironment = false; -}; - -#endif // GATEWAYCONTROLLER_H diff --git a/client/core/qrCodeUtils.cpp b/client/core/qrCodeUtils.cpp deleted file mode 100644 index a18af172..00000000 --- a/client/core/qrCodeUtils.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "qrCodeUtils.h" - -#include -#include - -QList qrCodeUtils::generateQrCodeImageSeries(const QByteArray &data) -{ - double k = 850; - - quint8 chunksCount = std::ceil(data.size() / k); - QList chunks; - for (int i = 0; i < data.size(); i = i + k) { - QByteArray chunk; - QDataStream s(&chunk, QIODevice::WriteOnly); - s << qrCodeUtils::qrMagicCode << chunksCount << (quint8)std::round(i / k) << data.mid(i, k); - - QByteArray ba = chunk.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); - - qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(ba, qrcodegen::QrCode::Ecc::LOW); - QString svg = QString::fromStdString(toSvgString(qr, 1)); - chunks.append(svgToBase64(svg)); - } - - return chunks; -} - -QString qrCodeUtils::svgToBase64(const QString &image) -{ - return "data:image/svg;base64," + QString::fromLatin1(image.toUtf8().toBase64().data()); -} - -qrcodegen::QrCode qrCodeUtils::generateQrCode(const QByteArray &data) -{ - return qrcodegen::QrCode::encodeText(data, qrcodegen::QrCode::Ecc::LOW); -} diff --git a/client/core/qrCodeUtils.h b/client/core/qrCodeUtils.h deleted file mode 100644 index cda0723b..00000000 --- a/client/core/qrCodeUtils.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef QRCODEUTILS_H -#define QRCODEUTILS_H - -#include - -#include "qrcodegen.hpp" - -namespace qrCodeUtils -{ - constexpr const qint16 qrMagicCode = 1984; - - QList generateQrCodeImageSeries(const QByteArray &data); - qrcodegen::QrCode generateQrCode(const QByteArray &data); - QString svgToBase64(const QString &image); -}; - -#endif // QRCODEUTILS_H diff --git a/client/images/controls/monitor.svg b/client/images/controls/monitor.svg deleted file mode 100644 index 1cdf57c2..00000000 --- a/client/images/controls/monitor.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/server_scripts/prepare_host.sh b/client/server_scripts/prepare_host.sh index 22a50e31..d06bdafb 100644 --- a/client/server_scripts/prepare_host.sh +++ b/client/server_scripts/prepare_host.sh @@ -1,4 +1,4 @@ -CUR_USER=$(whoami 2>/dev/null || echo ~ | sed 's/.*\///');\ +CUR_USER=$(whoami 2> /dev/null || echo ~ | sed 's/.*\///');\ sudo mkdir -p $DOCKERFILE_FOLDER;\ sudo chown $CUR_USER $DOCKERFILE_FOLDER;\ if ! sudo docker network ls | grep -q amnezia-dns-net; then sudo docker network create \ diff --git a/client/ui/controllers/api/apiConfigsController.cpp b/client/ui/controllers/api/apiConfigsController.cpp deleted file mode 100644 index d3c8747d..00000000 --- a/client/ui/controllers/api/apiConfigsController.cpp +++ /dev/null @@ -1,537 +0,0 @@ -#include "apiConfigsController.h" - -#include -#include - -#include "amnezia_application.h" -#include "configurators/wireguard_configurator.h" -#include "core/api/apiDefs.h" -#include "core/api/apiUtils.h" -#include "core/controllers/gatewayController.h" -#include "core/qrCodeUtils.h" -#include "ui/controllers/systemController.h" -#include "version.h" - -namespace -{ - namespace configKey - { - constexpr char cloak[] = "cloak"; - constexpr char awg[] = "awg"; - - constexpr char apiEdnpoint[] = "api_endpoint"; - constexpr char accessToken[] = "api_key"; - constexpr char certificate[] = "certificate"; - constexpr char publicKey[] = "public_key"; - constexpr char protocol[] = "protocol"; - - constexpr char uuid[] = "installation_uuid"; - constexpr char osVersion[] = "os_version"; - constexpr char appVersion[] = "app_version"; - - constexpr char userCountryCode[] = "user_country_code"; - constexpr char serverCountryCode[] = "server_country_code"; - constexpr char serviceType[] = "service_type"; - constexpr char serviceInfo[] = "service_info"; - constexpr char serviceProtocol[] = "service_protocol"; - - constexpr char aesKey[] = "aes_key"; - constexpr char aesIv[] = "aes_iv"; - constexpr char aesSalt[] = "aes_salt"; - - constexpr char apiPayload[] = "api_payload"; - constexpr char keyPayload[] = "key_payload"; - - constexpr char apiConfig[] = "api_config"; - constexpr char authData[] = "auth_data"; - - constexpr char config[] = "config"; - } -} - -ApiConfigsController::ApiConfigsController(const QSharedPointer &serversModel, - const QSharedPointer &apiServicesModel, - const std::shared_ptr &settings, QObject *parent) - : QObject(parent), m_serversModel(serversModel), m_apiServicesModel(apiServicesModel), m_settings(settings) -{ -} - -bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode, const QString &fileName) -{ - if (fileName.isEmpty()) { - emit errorOccurred(ErrorCode::PermissionsError); - return false; - } - - GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs); - - auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex()); - auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject(); - - QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString(); - ApiPayloadData apiPayloadData = generateApiPayloadData(protocol); - - QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData); - apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode); - apiPayload[configKey::serverCountryCode] = serverCountryCode; - apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType); - apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData); - - QByteArray responseBody; - ErrorCode errorCode = gatewayController.post(QString("%1v1/native_config"), apiPayload, responseBody); - if (errorCode != ErrorCode::NoError) { - emit errorOccurred(errorCode); - return false; - } - - QJsonObject jsonConfig = QJsonDocument::fromJson(responseBody).object(); - QString nativeConfig = jsonConfig.value(configKey::config).toString(); - nativeConfig.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", apiPayloadData.wireGuardClientPrivKey); - - SystemController::saveFile(fileName, nativeConfig); - return true; -} - -bool ApiConfigsController::revokeNativeConfig(const QString &serverCountryCode) -{ - GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs); - - auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex()); - auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject(); - - QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString(); - ApiPayloadData apiPayloadData = generateApiPayloadData(protocol); - - QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData); - apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode); - apiPayload[configKey::serverCountryCode] = serverCountryCode; - apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType); - apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData); - - QByteArray responseBody; - ErrorCode errorCode = gatewayController.post(QString("%1v1/revoke_native_config"), apiPayload, responseBody); - if (errorCode != ErrorCode::NoError && errorCode != ErrorCode::ApiNotFoundError) { - emit errorOccurred(errorCode); - return false; - } - return true; -} - -void ApiConfigsController::prepareVpnKeyExport() -{ - auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex()); - auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject(); - - auto vpnKey = apiConfigObject.value(apiDefs::key::vpnKey).toString(); - m_vpnKey = vpnKey; - - vpnKey.replace("vpn://", ""); - - m_qrCodes = qrCodeUtils::generateQrCodeImageSeries(vpnKey.toUtf8()); - - emit vpnKeyExportReady(); -} - -void ApiConfigsController::copyVpnKeyToClipboard() -{ - auto clipboard = amnApp->getClipboard(); - clipboard->setText(m_vpnKey); -} - -bool ApiConfigsController::fillAvailableServices() -{ - GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs); - - QJsonObject apiPayload; - apiPayload[configKey::osVersion] = QSysInfo::productType(); - - QByteArray responseBody; - ErrorCode errorCode = gatewayController.post(QString("%1v1/services"), apiPayload, responseBody); - if (errorCode == ErrorCode::NoError) { - if (!responseBody.contains("services")) { - errorCode = ErrorCode::ApiServicesMissingError; - } - } - - if (errorCode != ErrorCode::NoError) { - emit errorOccurred(errorCode); - return false; - } - - QJsonObject data = QJsonDocument::fromJson(responseBody).object(); - m_apiServicesModel->updateModel(data); - return true; -} - -bool ApiConfigsController::importServiceFromGateway() -{ - if (m_serversModel->isServerFromApiAlreadyExists(m_apiServicesModel->getCountryCode(), m_apiServicesModel->getSelectedServiceType(), - m_apiServicesModel->getSelectedServiceProtocol())) { - emit errorOccurred(ErrorCode::ApiConfigAlreadyAdded); - return false; - } - - GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs); - - auto installationUuid = m_settings->getInstallationUuid(true); - auto userCountryCode = m_apiServicesModel->getCountryCode(); - auto serviceType = m_apiServicesModel->getSelectedServiceType(); - auto serviceProtocol = m_apiServicesModel->getSelectedServiceProtocol(); - - ApiPayloadData apiPayloadData = generateApiPayloadData(serviceProtocol); - - QJsonObject apiPayload = fillApiPayload(serviceProtocol, apiPayloadData); - apiPayload[configKey::userCountryCode] = userCountryCode; - apiPayload[configKey::serviceType] = serviceType; - apiPayload[configKey::uuid] = installationUuid; - - QByteArray responseBody; - ErrorCode errorCode = gatewayController.post(QString("%1v1/config"), apiPayload, responseBody); - - QJsonObject serverConfig; - if (errorCode == ErrorCode::NoError) { - fillServerConfig(serviceProtocol, apiPayloadData, responseBody, serverConfig); - - QJsonObject apiConfig = serverConfig.value(configKey::apiConfig).toObject(); - apiConfig.insert(configKey::userCountryCode, m_apiServicesModel->getCountryCode()); - apiConfig.insert(configKey::serviceType, m_apiServicesModel->getSelectedServiceType()); - apiConfig.insert(configKey::serviceProtocol, m_apiServicesModel->getSelectedServiceProtocol()); - - serverConfig.insert(configKey::apiConfig, apiConfig); - - m_serversModel->addServer(serverConfig); - emit installServerFromApiFinished(tr("%1 installed successfully.").arg(m_apiServicesModel->getSelectedServiceName())); - return true; - } else { - emit errorOccurred(errorCode); - return false; - } -} - -bool ApiConfigsController::updateServiceFromGateway(const int serverIndex, const QString &newCountryCode, const QString &newCountryName, - bool reloadServiceConfig) -{ - GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs); - - auto serverConfig = m_serversModel->getServerConfig(serverIndex); - auto apiConfig = serverConfig.value(configKey::apiConfig).toObject(); - auto authData = serverConfig.value(configKey::authData).toObject(); - - auto installationUuid = m_settings->getInstallationUuid(true); - auto userCountryCode = apiConfig.value(configKey::userCountryCode).toString(); - auto serviceType = apiConfig.value(configKey::serviceType).toString(); - auto serviceProtocol = apiConfig.value(configKey::serviceProtocol).toString(); - - ApiPayloadData apiPayloadData = generateApiPayloadData(serviceProtocol); - - QJsonObject apiPayload = fillApiPayload(serviceProtocol, apiPayloadData); - apiPayload[configKey::userCountryCode] = userCountryCode; - apiPayload[configKey::serviceType] = serviceType; - apiPayload[configKey::uuid] = installationUuid; - - if (!newCountryCode.isEmpty()) { - apiPayload[configKey::serverCountryCode] = newCountryCode; - } - if (!authData.isEmpty()) { - apiPayload[configKey::authData] = authData; - } - - QByteArray responseBody; - ErrorCode errorCode = gatewayController.post(QString("%1v1/config"), apiPayload, responseBody); - - QJsonObject newServerConfig; - if (errorCode == ErrorCode::NoError) { - fillServerConfig(serviceProtocol, apiPayloadData, responseBody, newServerConfig); - - QJsonObject newApiConfig = newServerConfig.value(configKey::apiConfig).toObject(); - newApiConfig.insert(configKey::userCountryCode, apiConfig.value(configKey::userCountryCode)); - newApiConfig.insert(configKey::serviceType, apiConfig.value(configKey::serviceType)); - newApiConfig.insert(configKey::serviceProtocol, apiConfig.value(configKey::serviceProtocol)); - newApiConfig.insert(apiDefs::key::vpnKey, apiConfig.value(apiDefs::key::vpnKey)); - - newServerConfig.insert(configKey::apiConfig, newApiConfig); - newServerConfig.insert(configKey::authData, authData); - // newServerConfig.insert( - - m_serversModel->editServer(newServerConfig, serverIndex); - if (reloadServiceConfig) { - emit reloadServerFromApiFinished(tr("API config reloaded")); - } else if (newCountryName.isEmpty()) { - emit updateServerFromApiFinished(); - } else { - emit changeApiCountryFinished(tr("Successfully changed the country of connection to %1").arg(newCountryName)); - } - return true; - } else { - emit errorOccurred(errorCode); - return false; - } -} - -bool ApiConfigsController::updateServiceFromTelegram(const int serverIndex) -{ - auto serverConfig = m_serversModel->getServerConfig(serverIndex); - auto installationUuid = m_settings->getInstallationUuid(true); - -#ifdef Q_OS_IOS - IosController::Instance()->requestInetAccess(); - QThread::msleep(10); -#endif - - if (serverConfig.value(config_key::configVersion).toInt()) { - QNetworkRequest request; - request.setTransferTimeout(apiDefs::requestTimeoutMsecs); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request.setRawHeader("Authorization", "Api-Key " + serverConfig.value(configKey::accessToken).toString().toUtf8()); - QString endpoint = serverConfig.value(configKey::apiEdnpoint).toString(); - request.setUrl(endpoint); - - QString protocol = serverConfig.value(configKey::protocol).toString(); - - ApiPayloadData apiPayloadData = generateApiPayloadData(protocol); - - QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData); - apiPayload[configKey::uuid] = installationUuid; - - QByteArray requestBody = QJsonDocument(apiPayload).toJson(); - - QNetworkReply *reply = amnApp->networkManager()->post(request, requestBody); - - QEventLoop wait; - connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit); - - QList sslErrors; - connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList &errors) { sslErrors = errors; }); - wait.exec(); - - auto errorCode = apiUtils::checkNetworkReplyErrors(sslErrors, reply); - if (errorCode != ErrorCode::NoError) { - reply->deleteLater(); - emit errorOccurred(errorCode); - return false; - } - - auto apiResponseBody = reply->readAll(); - reply->deleteLater(); - fillServerConfig(protocol, apiPayloadData, apiResponseBody, serverConfig); - m_serversModel->editServer(serverConfig, serverIndex); - emit updateServerFromApiFinished(); - } - return true; -} - -bool ApiConfigsController::deactivateDevice() -{ - GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs); - - auto serverIndex = m_serversModel->getProcessedServerIndex(); - auto serverConfigObject = m_serversModel->getServerConfig(serverIndex); - auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject(); - - if (apiUtils::getConfigType(serverConfigObject) != apiDefs::ConfigType::AmneziaPremiumV2) { - return true; - } - - QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString(); - ApiPayloadData apiPayloadData = generateApiPayloadData(protocol); - - QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData); - apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode); - apiPayload[configKey::serverCountryCode] = apiConfigObject.value(configKey::serverCountryCode); - apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType); - apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData); - apiPayload[configKey::uuid] = m_settings->getInstallationUuid(true); - - QByteArray responseBody; - ErrorCode errorCode = gatewayController.post(QString("%1v1/revoke_config"), apiPayload, responseBody); - if (errorCode != ErrorCode::NoError && errorCode != ErrorCode::ApiNotFoundError) { - emit errorOccurred(errorCode); - return false; - } - - serverConfigObject.remove(config_key::containers); - m_serversModel->editServer(serverConfigObject, serverIndex); - - return true; -} - -bool ApiConfigsController::deactivateExternalDevice(const QString &uuid, const QString &serverCountryCode) -{ - GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs); - - auto serverIndex = m_serversModel->getProcessedServerIndex(); - auto serverConfigObject = m_serversModel->getServerConfig(serverIndex); - auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject(); - - if (apiUtils::getConfigType(serverConfigObject) != apiDefs::ConfigType::AmneziaPremiumV2) { - return true; - } - - QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString(); - ApiPayloadData apiPayloadData = generateApiPayloadData(protocol); - - QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData); - apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode); - apiPayload[configKey::serverCountryCode] = serverCountryCode; - apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType); - apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData); - apiPayload[configKey::uuid] = uuid; - - QByteArray responseBody; - ErrorCode errorCode = gatewayController.post(QString("%1v1/revoke_config"), apiPayload, responseBody); - if (errorCode != ErrorCode::NoError && errorCode != ErrorCode::ApiNotFoundError) { - emit errorOccurred(errorCode); - return false; - } - - if (uuid == m_settings->getInstallationUuid(true)) { - serverConfigObject.remove(config_key::containers); - m_serversModel->editServer(serverConfigObject, serverIndex); - } - - return true; -} - -bool ApiConfigsController::isConfigValid() -{ - int serverIndex = m_serversModel->getDefaultServerIndex(); - QJsonObject serverConfigObject = m_serversModel->getServerConfig(serverIndex); - auto configSource = apiUtils::getConfigSource(serverConfigObject); - - if (configSource == apiDefs::ConfigSource::Telegram - && !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) { - m_serversModel->removeApiConfig(serverIndex); - return updateServiceFromTelegram(serverIndex); - } else if (configSource == apiDefs::ConfigSource::AmneziaGateway - && !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::Telegram) { - return updateServiceFromGateway(serverIndex, "", ""); - } else { - m_serversModel->removeApiConfig(serverIndex); - return updateServiceFromTelegram(serverIndex); - } - } - return true; -} - -ApiConfigsController::ApiPayloadData ApiConfigsController::generateApiPayloadData(const QString &protocol) -{ - ApiConfigsController::ApiPayloadData apiPayload; - if (protocol == configKey::cloak) { - apiPayload.certRequest = OpenVpnConfigurator::createCertRequest(); - } else if (protocol == configKey::awg) { - auto connData = WireguardConfigurator::genClientKeys(); - apiPayload.wireGuardClientPubKey = connData.clientPubKey; - apiPayload.wireGuardClientPrivKey = connData.clientPrivKey; - } - return apiPayload; -} - -QJsonObject ApiConfigsController::fillApiPayload(const QString &protocol, const ApiPayloadData &apiPayloadData) -{ - QJsonObject obj; - if (protocol == configKey::cloak) { - obj[configKey::certificate] = apiPayloadData.certRequest.request; - } else if (protocol == configKey::awg) { - obj[configKey::publicKey] = apiPayloadData.wireGuardClientPubKey; - } - - obj[configKey::osVersion] = QSysInfo::productType(); - obj[configKey::appVersion] = QString(APP_VERSION); - - return obj; -} - -void ApiConfigsController::fillServerConfig(const QString &protocol, const ApiPayloadData &apiPayloadData, - const QByteArray &apiResponseBody, QJsonObject &serverConfig) -{ - QString data = QJsonDocument::fromJson(apiResponseBody).object().value(config_key::config).toString(); - - data.replace("vpn://", ""); - QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); - - if (ba.isEmpty()) { - emit errorOccurred(ErrorCode::ApiConfigEmptyError); - return; - } - - QByteArray ba_uncompressed = qUncompress(ba); - if (!ba_uncompressed.isEmpty()) { - ba = ba_uncompressed; - } - - QString configStr = ba; - if (protocol == configKey::cloak) { - configStr.replace("", "\n"); - configStr.replace("$OPENVPN_PRIV_KEY", apiPayloadData.certRequest.privKey); - } else if (protocol == configKey::awg) { - configStr.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", apiPayloadData.wireGuardClientPrivKey); - auto newServerConfig = QJsonDocument::fromJson(configStr.toUtf8()).object(); - auto containers = newServerConfig.value(config_key::containers).toArray(); - if (containers.isEmpty()) { - return; // todo process error - } - auto container = containers.at(0).toObject(); - QString containerName = ContainerProps::containerTypeToString(DockerContainer::Awg); - auto containerConfig = container.value(containerName).toObject(); - auto protocolConfig = QJsonDocument::fromJson(containerConfig.value(config_key::last_config).toString().toUtf8()).object(); - containerConfig[config_key::junkPacketCount] = protocolConfig.value(config_key::junkPacketCount); - containerConfig[config_key::junkPacketMinSize] = protocolConfig.value(config_key::junkPacketMinSize); - containerConfig[config_key::junkPacketMaxSize] = protocolConfig.value(config_key::junkPacketMaxSize); - containerConfig[config_key::initPacketJunkSize] = protocolConfig.value(config_key::initPacketJunkSize); - containerConfig[config_key::responsePacketJunkSize] = protocolConfig.value(config_key::responsePacketJunkSize); - containerConfig[config_key::initPacketMagicHeader] = protocolConfig.value(config_key::initPacketMagicHeader); - containerConfig[config_key::responsePacketMagicHeader] = protocolConfig.value(config_key::responsePacketMagicHeader); - containerConfig[config_key::underloadPacketMagicHeader] = protocolConfig.value(config_key::underloadPacketMagicHeader); - containerConfig[config_key::transportPacketMagicHeader] = protocolConfig.value(config_key::transportPacketMagicHeader); - container[containerName] = containerConfig; - containers.replace(0, container); - newServerConfig[config_key::containers] = containers; - configStr = QString(QJsonDocument(newServerConfig).toJson()); - } - - QJsonObject newServerConfig = QJsonDocument::fromJson(configStr.toUtf8()).object(); - serverConfig[config_key::dns1] = newServerConfig.value(config_key::dns1); - serverConfig[config_key::dns2] = newServerConfig.value(config_key::dns2); - 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) { - 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); - } - - auto defaultContainer = newServerConfig.value(config_key::defaultContainer).toString(); - serverConfig[config_key::defaultContainer] = defaultContainer; - - QVariantMap map = serverConfig.value(configKey::apiConfig).toObject().toVariantMap(); - map.insert(newServerConfig.value(configKey::apiConfig).toObject().toVariantMap()); - auto apiConfig = QJsonObject::fromVariantMap(map); - - if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) { - apiConfig.insert(configKey::serviceInfo, QJsonDocument::fromJson(apiResponseBody).object().value(configKey::serviceInfo).toObject()); - } - - serverConfig[configKey::apiConfig] = apiConfig; - - return; -} - -QList ApiConfigsController::getQrCodes() -{ - return m_qrCodes; -} - -int ApiConfigsController::getQrCodesCount() -{ - return m_qrCodes.size(); -} - -QString ApiConfigsController::getVpnKey() -{ - return m_vpnKey; -} diff --git a/client/ui/controllers/api/apiConfigsController.h b/client/ui/controllers/api/apiConfigsController.h deleted file mode 100644 index 2fe981e4..00000000 --- a/client/ui/controllers/api/apiConfigsController.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef APICONFIGSCONTROLLER_H -#define APICONFIGSCONTROLLER_H - -#include - -#include "configurators/openvpn_configurator.h" -#include "ui/models/api/apiServicesModel.h" -#include "ui/models/servers_model.h" - -class ApiConfigsController : public QObject -{ - Q_OBJECT -public: - ApiConfigsController(const QSharedPointer &serversModel, const QSharedPointer &apiServicesModel, - const std::shared_ptr &settings, QObject *parent = nullptr); - - Q_PROPERTY(QList qrCodes READ getQrCodes NOTIFY vpnKeyExportReady) - Q_PROPERTY(int qrCodesCount READ getQrCodesCount NOTIFY vpnKeyExportReady) - Q_PROPERTY(QString vpnKey READ getVpnKey NOTIFY vpnKeyExportReady) - -public slots: - bool exportNativeConfig(const QString &serverCountryCode, const QString &fileName); - bool revokeNativeConfig(const QString &serverCountryCode); - // bool exportVpnKey(const QString &fileName); - void prepareVpnKeyExport(); - void copyVpnKeyToClipboard(); - - bool fillAvailableServices(); - bool importServiceFromGateway(); - bool updateServiceFromGateway(const int serverIndex, const QString &newCountryCode, const QString &newCountryName, - bool reloadServiceConfig = false); - bool updateServiceFromTelegram(const int serverIndex); - bool deactivateDevice(); - bool deactivateExternalDevice(const QString &uuid, const QString &serverCountryCode); - - bool isConfigValid(); - -signals: - void errorOccurred(ErrorCode errorCode); - - void installServerFromApiFinished(const QString &message); - void changeApiCountryFinished(const QString &message); - void reloadServerFromApiFinished(const QString &message); - void updateServerFromApiFinished(); - - void vpnKeyExportReady(); - -private: - struct ApiPayloadData - { - OpenVpnConfigurator::ConnectionData certRequest; - - QString wireGuardClientPrivKey; - QString wireGuardClientPubKey; - }; - - ApiPayloadData generateApiPayloadData(const QString &protocol); - QJsonObject fillApiPayload(const QString &protocol, const ApiPayloadData &apiPayloadData); - void fillServerConfig(const QString &protocol, const ApiPayloadData &apiPayloadData, const QByteArray &apiResponseBody, - QJsonObject &serverConfig); - - QList getQrCodes(); - int getQrCodesCount(); - QString getVpnKey(); - - QList m_qrCodes; - QString m_vpnKey; - - QSharedPointer m_serversModel; - QSharedPointer m_apiServicesModel; - std::shared_ptr m_settings; -}; - -#endif // APICONFIGSCONTROLLER_H diff --git a/client/ui/controllers/api/apiSettingsController.cpp b/client/ui/controllers/api/apiSettingsController.cpp deleted file mode 100644 index 737bfd1a..00000000 --- a/client/ui/controllers/api/apiSettingsController.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "apiSettingsController.h" - -#include -#include - -#include "core/api/apiUtils.h" -#include "core/controllers/gatewayController.h" - -namespace -{ - namespace configKey - { - constexpr char userCountryCode[] = "user_country_code"; - constexpr char serverCountryCode[] = "server_country_code"; - constexpr char serviceType[] = "service_type"; - constexpr char serviceInfo[] = "service_info"; - - constexpr char apiConfig[] = "api_config"; - constexpr char authData[] = "auth_data"; - } - - const int requestTimeoutMsecs = 12 * 1000; // 12 secs -} - -ApiSettingsController::ApiSettingsController(const QSharedPointer &serversModel, - const QSharedPointer &apiAccountInfoModel, - const QSharedPointer &apiCountryModel, - const QSharedPointer &apiDevicesModel, - const std::shared_ptr &settings, QObject *parent) - : QObject(parent), - m_serversModel(serversModel), - m_apiAccountInfoModel(apiAccountInfoModel), - m_apiCountryModel(apiCountryModel), - m_apiDevicesModel(apiDevicesModel), - m_settings(settings) -{ -} - -ApiSettingsController::~ApiSettingsController() -{ -} - -bool ApiSettingsController::getAccountInfo(bool reload) -{ - if (reload) { - QEventLoop wait; - QTimer::singleShot(1000, &wait, &QEventLoop::quit); - wait.exec(); - } - - GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), requestTimeoutMsecs); - - auto processedIndex = m_serversModel->getProcessedServerIndex(); - auto serverConfig = m_serversModel->getServerConfig(processedIndex); - auto apiConfig = serverConfig.value(configKey::apiConfig).toObject(); - auto authData = serverConfig.value(configKey::authData).toObject(); - - QJsonObject apiPayload; - apiPayload[configKey::userCountryCode] = apiConfig.value(configKey::userCountryCode).toString(); - apiPayload[configKey::serviceType] = apiConfig.value(configKey::serviceType).toString(); - apiPayload[configKey::authData] = authData; - - QByteArray responseBody; - - if (apiUtils::getConfigType(serverConfig) == apiDefs::ConfigType::AmneziaPremiumV2) { - ErrorCode errorCode = gatewayController.post(QString("%1v1/account_info"), apiPayload, responseBody); - if (errorCode != ErrorCode::NoError) { - emit errorOccurred(errorCode); - return false; - } - } - - QJsonObject accountInfo = QJsonDocument::fromJson(responseBody).object(); - m_apiAccountInfoModel->updateModel(accountInfo, serverConfig); - - if (reload) { - updateApiCountryModel(); - updateApiDevicesModel(); - } - - return true; -} - -void ApiSettingsController::updateApiCountryModel() -{ - m_apiCountryModel->updateModel(m_apiAccountInfoModel->getAvailableCountries(), ""); - m_apiCountryModel->updateIssuedConfigsInfo(m_apiAccountInfoModel->getIssuedConfigsInfo()); -} - -void ApiSettingsController::updateApiDevicesModel() -{ - m_apiDevicesModel->updateModel(m_apiAccountInfoModel->getIssuedConfigsInfo()); -} diff --git a/client/ui/controllers/api/apiSettingsController.h b/client/ui/controllers/api/apiSettingsController.h deleted file mode 100644 index afe9a570..00000000 --- a/client/ui/controllers/api/apiSettingsController.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef APISETTINGSCONTROLLER_H -#define APISETTINGSCONTROLLER_H - -#include - -#include "ui/models/api/apiAccountInfoModel.h" -#include "ui/models/api/apiCountryModel.h" -#include "ui/models/api/apiDevicesModel.h" -#include "ui/models/servers_model.h" - -class ApiSettingsController : public QObject -{ - Q_OBJECT -public: - ApiSettingsController(const QSharedPointer &serversModel, const QSharedPointer &apiAccountInfoModel, - const QSharedPointer &apiCountryModel, const QSharedPointer &apiDevicesModel, - const std::shared_ptr &settings, QObject *parent = nullptr); - ~ApiSettingsController(); - -public slots: - bool getAccountInfo(bool reload); - void updateApiCountryModel(); - void updateApiDevicesModel(); - -signals: - void errorOccurred(ErrorCode errorCode); - -private: - QSharedPointer m_serversModel; - QSharedPointer m_apiAccountInfoModel; - QSharedPointer m_apiCountryModel; - QSharedPointer m_apiDevicesModel; - - std::shared_ptr m_settings; -}; - -#endif // APISETTINGSCONTROLLER_H diff --git a/client/ui/models/api/apiAccountInfoModel.cpp b/client/ui/models/api/apiAccountInfoModel.cpp deleted file mode 100644 index cdb9dfe8..00000000 --- a/client/ui/models/api/apiAccountInfoModel.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "apiAccountInfoModel.h" - -#include - -#include "core/api/apiUtils.h" -#include "logger.h" - -namespace -{ - Logger logger("AccountInfoModel"); -} - -ApiAccountInfoModel::ApiAccountInfoModel(QObject *parent) : QAbstractListModel(parent) -{ -} - -int ApiAccountInfoModel::rowCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - return 1; -} - -QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(rowCount())) - return QVariant(); - - switch (role) { - case SubscriptionStatusRole: { - if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { - return tr("Active"); - } - - return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate) ? tr("Inactive") : tr("Active"); - } - case EndDateRole: { - if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { - return ""; - } - - return QDateTime::fromString(m_accountInfoData.subscriptionEndDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy"); - } - case ConnectedDevicesRole: { - if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { - return ""; - } - return tr("%1 out of %2").arg(m_accountInfoData.activeDeviceCount).arg(m_accountInfoData.maxDeviceCount); - } - case ServiceDescriptionRole: { - if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2) { - return tr("Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to 200 " - "Mb/s"); - } else if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { - return tr("Free unlimited access to a basic set of websites such as Facebook, Instagram, Twitter (X), Discord, Telegram and " - "more. YouTube is not included in the free plan."); - } - } - case IsComponentVisibleRole: { - return m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2; - } - case HasExpiredWorkerRole: { - for (int i = 0; i < m_issuedConfigsInfo.size(); i++) { - QJsonObject issuedConfigObject = m_issuedConfigsInfo.at(i).toObject(); - - auto lastDownloaded = QDateTime::fromString(issuedConfigObject.value(apiDefs::key::lastDownloaded).toString()); - auto workerLastUpdated = QDateTime::fromString(issuedConfigObject.value(apiDefs::key::workerLastUpdated).toString()); - - if (lastDownloaded < workerLastUpdated) { - return true; - } - } - return false; - } - } - - return QVariant(); -} - -void ApiAccountInfoModel::updateModel(const QJsonObject &accountInfoObject, const QJsonObject &serverConfig) -{ - beginResetModel(); - - AccountInfoData accountInfoData; - - m_availableCountries = accountInfoObject.value(apiDefs::key::availableCountries).toArray(); - m_issuedConfigsInfo = accountInfoObject.value(apiDefs::key::issuedConfigs).toArray(); - - accountInfoData.activeDeviceCount = accountInfoObject.value(apiDefs::key::activeDeviceCount).toInt(); - accountInfoData.maxDeviceCount = accountInfoObject.value(apiDefs::key::maxDeviceCount).toInt(); - accountInfoData.subscriptionEndDate = accountInfoObject.value(apiDefs::key::subscriptionEndDate).toString(); - - accountInfoData.configType = apiUtils::getConfigType(serverConfig); - - m_accountInfoData = accountInfoData; - - endResetModel(); -} - -QVariant ApiAccountInfoModel::data(const QString &roleString) -{ - QModelIndex modelIndex = index(0); - auto roles = roleNames(); - for (auto it = roles.begin(); it != roles.end(); it++) { - if (QString(it.value()) == roleString) { - return data(modelIndex, it.key()); - } - } - - return {}; -} - -QJsonArray ApiAccountInfoModel::getAvailableCountries() -{ - return m_availableCountries; -} - -QJsonArray ApiAccountInfoModel::getIssuedConfigsInfo() -{ - return m_issuedConfigsInfo; -} - -QString ApiAccountInfoModel::getTelegramBotLink() -{ - if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { - return tr("amnezia_free_support_bot"); - } else if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2) { - return tr("amnezia_premium_support_bot"); - } - return ""; -} - -QHash ApiAccountInfoModel::roleNames() const -{ - QHash roles; - roles[SubscriptionStatusRole] = "subscriptionStatus"; - roles[EndDateRole] = "endDate"; - roles[ConnectedDevicesRole] = "connectedDevices"; - roles[ServiceDescriptionRole] = "serviceDescription"; - roles[IsComponentVisibleRole] = "isComponentVisible"; - roles[HasExpiredWorkerRole] = "hasExpiredWorker"; - - return roles; -} diff --git a/client/ui/models/api/apiAccountInfoModel.h b/client/ui/models/api/apiAccountInfoModel.h deleted file mode 100644 index 44eb7ee6..00000000 --- a/client/ui/models/api/apiAccountInfoModel.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef APIACCOUNTINFOMODEL_H -#define APIACCOUNTINFOMODEL_H - -#include -#include -#include - -#include "core/api/apiDefs.h" - -class ApiAccountInfoModel : public QAbstractListModel -{ - Q_OBJECT - -public: - enum Roles { - SubscriptionStatusRole = Qt::UserRole + 1, - ConnectedDevicesRole, - ServiceDescriptionRole, - EndDateRole, - IsComponentVisibleRole, - HasExpiredWorkerRole - }; - - explicit ApiAccountInfoModel(QObject *parent = nullptr); - - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - -public slots: - void updateModel(const QJsonObject &accountInfoObject, const QJsonObject &serverConfig); - QVariant data(const QString &roleString); - - QJsonArray getAvailableCountries(); - QJsonArray getIssuedConfigsInfo(); - QString getTelegramBotLink(); - -protected: - QHash roleNames() const override; - -private: - struct AccountInfoData - { - QString subscriptionEndDate; - int activeDeviceCount; - int maxDeviceCount; - - apiDefs::ConfigType configType; - }; - - AccountInfoData m_accountInfoData; - QJsonArray m_availableCountries; - QJsonArray m_issuedConfigsInfo; -}; - -#endif // APIACCOUNTINFOMODEL_H diff --git a/client/ui/models/api/apiCountryModel.cpp b/client/ui/models/api/apiCountryModel.cpp deleted file mode 100644 index 12f4658e..00000000 --- a/client/ui/models/api/apiCountryModel.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "apiCountryModel.h" - -#include - -#include "core/api/apiDefs.h" -#include "logger.h" - -namespace -{ - Logger logger("ApiCountryModel"); - - constexpr QLatin1String countryConfig("country_config"); -} - -ApiCountryModel::ApiCountryModel(QObject *parent) : QAbstractListModel(parent) -{ -} - -int ApiCountryModel::rowCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - return m_countries.size(); -} - -QVariant ApiCountryModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(rowCount())) - return QVariant(); - - CountryInfo countryInfo = m_countries.at(index.row()); - IssuedConfigInfo issuedConfigInfo = m_issuedConfigs.value(countryInfo.countryCode); - bool isIssued = issuedConfigInfo.sourceType == countryConfig; - - switch (role) { - case CountryCodeRole: { - return countryInfo.countryCode; - } - case CountryNameRole: { - return countryInfo.countryName; - } - case CountryImageCodeRole: { - return countryInfo.countryCode.toUpper(); - } - case IsIssuedRole: { - return isIssued; - } - case IsWorkerExpiredRole: { - return issuedConfigInfo.lastDownloaded < issuedConfigInfo.workerLastUpdated; - } - } - - return QVariant(); -} - -void ApiCountryModel::updateModel(const QJsonArray &countries, const QString ¤tCountryCode) -{ - beginResetModel(); - - m_countries.clear(); - for (int i = 0; i < countries.size(); i++) { - CountryInfo countryInfo; - QJsonObject countryObject = countries.at(i).toObject(); - - countryInfo.countryName = countryObject.value(apiDefs::key::serverCountryName).toString(); - countryInfo.countryCode = countryObject.value(apiDefs::key::serverCountryCode).toString(); - - if (countryInfo.countryCode == currentCountryCode) { - m_currentIndex = i; - emit currentIndexChanged(m_currentIndex); - } - m_countries.push_back(countryInfo); - } - - endResetModel(); -} - -void ApiCountryModel::updateIssuedConfigsInfo(const QJsonArray &issuedConfigs) -{ - beginResetModel(); - - m_issuedConfigs.clear(); - for (int i = 0; i < issuedConfigs.size(); i++) { - IssuedConfigInfo issuedConfigInfo; - QJsonObject issuedConfigObject = issuedConfigs.at(i).toObject(); - - if (issuedConfigObject.value(apiDefs::key::sourceType).toString() != countryConfig) { - continue; - } - - issuedConfigInfo.installationUuid = issuedConfigObject.value(apiDefs::key::installationUuid).toString(); - issuedConfigInfo.workerLastUpdated = issuedConfigObject.value(apiDefs::key::workerLastUpdated).toString(); - issuedConfigInfo.lastDownloaded = issuedConfigObject.value(apiDefs::key::lastDownloaded).toString(); - issuedConfigInfo.sourceType = issuedConfigObject.value(apiDefs::key::sourceType).toString(); - issuedConfigInfo.osVersion = issuedConfigObject.value(apiDefs::key::osVersion).toString(); - - m_issuedConfigs.insert(issuedConfigObject.value(apiDefs::key::serverCountryCode).toString(), issuedConfigInfo); - } - - endResetModel(); -} - -int ApiCountryModel::getCurrentIndex() -{ - return m_currentIndex; -} - -void ApiCountryModel::setCurrentIndex(const int i) -{ - m_currentIndex = i; - emit currentIndexChanged(m_currentIndex); -} - -QHash ApiCountryModel::roleNames() const -{ - QHash roles; - roles[CountryNameRole] = "countryName"; - roles[CountryCodeRole] = "countryCode"; - roles[CountryImageCodeRole] = "countryImageCode"; - roles[IsIssuedRole] = "isIssued"; - roles[IsWorkerExpiredRole] = "isWorkerExpired"; - return roles; -} diff --git a/client/ui/models/api/apiCountryModel.h b/client/ui/models/api/apiCountryModel.h deleted file mode 100644 index 08ac3685..00000000 --- a/client/ui/models/api/apiCountryModel.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef APICOUNTRYMODEL_H -#define APICOUNTRYMODEL_H - -#include -#include -#include - -class ApiCountryModel : public QAbstractListModel -{ - Q_OBJECT - -public: - enum Roles { - CountryNameRole = Qt::UserRole + 1, - CountryCodeRole, - CountryImageCodeRole, - IsIssuedRole, - IsWorkerExpiredRole - }; - - explicit ApiCountryModel(QObject *parent = nullptr); - - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - - Q_PROPERTY(int currentIndex READ getCurrentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) - -public slots: - void updateModel(const QJsonArray &countries, const QString ¤tCountryCode); - void updateIssuedConfigsInfo(const QJsonArray &issuedConfigs); - - int getCurrentIndex(); - void setCurrentIndex(const int i); - -signals: - void currentIndexChanged(const int index); - -protected: - QHash roleNames() const override; - -private: - struct IssuedConfigInfo - { - QString installationUuid; - QString workerLastUpdated; - QString lastDownloaded; - QString sourceType; - QString osVersion; - }; - - struct CountryInfo - { - QString countryName; - QString countryCode; - }; - - QVector m_countries; - QHash m_issuedConfigs; - int m_currentIndex; -}; - -#endif // APICOUNTRYMODEL_H diff --git a/client/ui/models/api/apiDevicesModel.cpp b/client/ui/models/api/apiDevicesModel.cpp deleted file mode 100644 index 6c0d60d0..00000000 --- a/client/ui/models/api/apiDevicesModel.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "apiDevicesModel.h" - -#include - -#include "core/api/apiDefs.h" -#include "logger.h" - -namespace -{ - Logger logger("ApiDevicesModel"); - - constexpr QLatin1String gatewayAccount("gateway_account"); -} - -ApiDevicesModel::ApiDevicesModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent) -{ -} - -int ApiDevicesModel::rowCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - return m_issuedConfigs.size(); -} - -QVariant ApiDevicesModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(rowCount())) - return QVariant(); - - IssuedConfigInfo issuedConfigInfo = m_issuedConfigs.at(index.row()); - - switch (role) { - case OsVersionRole: { - return issuedConfigInfo.osVersion; - } - case SupportTagRole: { - return issuedConfigInfo.installationUuid; - } - case CountryCodeRole: { - return issuedConfigInfo.countryCode; - } - case LastUpdateRole: { - return QDateTime::fromString(issuedConfigInfo.lastDownloaded, Qt::ISODate).toLocalTime().toString("d MMM yyyy"); - } - case IsCurrentDeviceRole: { - return issuedConfigInfo.installationUuid == m_settings->getInstallationUuid(false); - } - } - - return QVariant(); -} - -void ApiDevicesModel::updateModel(const QJsonArray &issuedConfigs) -{ - beginResetModel(); - - m_issuedConfigs.clear(); - for (int i = 0; i < issuedConfigs.size(); i++) { - IssuedConfigInfo issuedConfigInfo; - QJsonObject issuedConfigObject = issuedConfigs.at(i).toObject(); - - if (issuedConfigObject.value(apiDefs::key::sourceType).toString() != gatewayAccount) { - continue; - } - - issuedConfigInfo.installationUuid = issuedConfigObject.value(apiDefs::key::installationUuid).toString(); - issuedConfigInfo.workerLastUpdated = issuedConfigObject.value(apiDefs::key::workerLastUpdated).toString(); - issuedConfigInfo.lastDownloaded = issuedConfigObject.value(apiDefs::key::lastDownloaded).toString(); - issuedConfigInfo.sourceType = issuedConfigObject.value(apiDefs::key::sourceType).toString(); - issuedConfigInfo.osVersion = issuedConfigObject.value(apiDefs::key::osVersion).toString(); - - issuedConfigInfo.countryName = issuedConfigObject.value(apiDefs::key::serverCountryName).toString(); - issuedConfigInfo.countryCode = issuedConfigObject.value(apiDefs::key::serverCountryCode).toString(); - - m_issuedConfigs.push_back(issuedConfigInfo); - } - - endResetModel(); -} - -QHash ApiDevicesModel::roleNames() const -{ - QHash roles; - roles[OsVersionRole] = "osVersion"; - roles[SupportTagRole] = "supportTag"; - roles[CountryCodeRole] = "countryCode"; - roles[LastUpdateRole] = "lastUpdate"; - roles[IsCurrentDeviceRole] = "isCurrentDevice"; - return roles; -} diff --git a/client/ui/models/api/apiDevicesModel.h b/client/ui/models/api/apiDevicesModel.h deleted file mode 100644 index e6a59dba..00000000 --- a/client/ui/models/api/apiDevicesModel.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef APIDEVICESMODEL_H -#define APIDEVICESMODEL_H - -#include -#include -#include - -#include "settings.h" - -class ApiDevicesModel : public QAbstractListModel -{ - Q_OBJECT - -public: - enum Roles { - OsVersionRole = Qt::UserRole + 1, - SupportTagRole, - CountryCodeRole, - LastUpdateRole, - IsCurrentDeviceRole - }; - - explicit ApiDevicesModel(std::shared_ptr settings, QObject *parent = nullptr); - - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - -public slots: - void updateModel(const QJsonArray &issuedConfigs); - -protected: - QHash roleNames() const override; - -private: - struct IssuedConfigInfo - { - QString installationUuid; - QString workerLastUpdated; - QString lastDownloaded; - QString sourceType; - QString osVersion; - - QString countryName; - QString countryCode; - }; - - QVector m_issuedConfigs; - - std::shared_ptr m_settings; -}; -#endif // APIDEVICESMODEL_H diff --git a/client/ui/models/api/apiServicesModel.cpp b/client/ui/models/api/apiServicesModel.cpp deleted file mode 100644 index f1880e4d..00000000 --- a/client/ui/models/api/apiServicesModel.cpp +++ /dev/null @@ -1,264 +0,0 @@ -#include "apiServicesModel.h" - -#include - -#include "logger.h" - -namespace -{ - Logger logger("ApiServicesModel"); - - namespace configKey - { - constexpr char userCountryCode[] = "user_country_code"; - constexpr char services[] = "services"; - constexpr char serviceInfo[] = "service_info"; - constexpr char serviceType[] = "service_type"; - constexpr char serviceProtocol[] = "service_protocol"; - - constexpr char name[] = "name"; - constexpr char price[] = "price"; - constexpr char speed[] = "speed"; - constexpr char timelimit[] = "timelimit"; - constexpr char region[] = "region"; - - constexpr char availableCountries[] = "available_countries"; - - constexpr char storeEndpoint[] = "store_endpoint"; - - constexpr char isAvailable[] = "is_available"; - - constexpr char subscription[] = "subscription"; - constexpr char endDate[] = "end_date"; - } - - namespace serviceType - { - constexpr char amneziaFree[] = "amnezia-free"; - constexpr char amneziaPremium[] = "amnezia-premium"; - } -} - -ApiServicesModel::ApiServicesModel(QObject *parent) : QAbstractListModel(parent) -{ -} - -int ApiServicesModel::rowCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - return m_services.size(); -} - -QVariant ApiServicesModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(rowCount())) - return QVariant(); - - auto apiServiceData = m_services.at(index.row()); - auto serviceType = apiServiceData.type; - auto isServiceAvailable = apiServiceData.isServiceAvailable; - - switch (role) { - case NameRole: { - return apiServiceData.serviceInfo.name; - } - case CardDescriptionRole: { - auto speed = apiServiceData.serviceInfo.speed; - if (serviceType == serviceType::amneziaPremium) { - return tr("Amnezia Premium is VPN for comfortable work, downloading large files and watching videos in 8K resolution. " - "Works for any sites with no restrictions. Speed up to %1 MBit/s. Unlimited traffic.") - .arg(speed); - } else if (serviceType == serviceType::amneziaFree) { - QString description = tr("AmneziaFree provides free unlimited access to a basic set of web sites, such as Facebook, Instagram, Twitter (X), Discord, Telegram, and others. YouTube is not included in the free plan."); - if (!isServiceAvailable) { - description += tr("

Not available in your region. If you have VPN enabled, disable it, " - "return to the previous screen, and try again."); - } - return description; - } - } - case ServiceDescriptionRole: { - if (serviceType == serviceType::amneziaPremium) { - return tr("Amnezia Premium is VPN for comfortable work, downloading large files and watching videos in 8K resolution. " - "Works for any sites with no restrictions."); - } else { - return tr("AmneziaFree provides free unlimited access to a basic set of web sites, such as Facebook, Instagram, Twitter (X), Discord, Telegram, and others. YouTube is not included in the free plan."); - } - } - case IsServiceAvailableRole: { - if (serviceType == serviceType::amneziaFree) { - if (!isServiceAvailable) { - return false; - } - } - return true; - } - case SpeedRole: { - return tr("%1 MBit/s").arg(apiServiceData.serviceInfo.speed); - } - case TimeLimitRole: { - auto timeLimit = apiServiceData.serviceInfo.timeLimit; - if (timeLimit == "0") { - return ""; - } - return tr("%1 days").arg(timeLimit); - } - case RegionRole: { - return apiServiceData.serviceInfo.region; - } - case FeaturesRole: { - if (serviceType == serviceType::amneziaPremium) { - return tr(""); - } else { - return tr("VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. " - "Other sites will be opened from your real IP address, " - "more details on the website."); - } - } - case PriceRole: { - auto price = apiServiceData.serviceInfo.price; - if (price == "free") { - return tr("Free"); - } - return tr("%1 $/month").arg(price); - } - case EndDateRole: { - return QDateTime::fromString(apiServiceData.subscription.endDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy"); - } - } - - return QVariant(); -} - -void ApiServicesModel::updateModel(const QJsonObject &data) -{ - beginResetModel(); - - m_services.clear(); - - m_countryCode = data.value(configKey::userCountryCode).toString(); - auto services = data.value(configKey::services).toArray(); - - if (services.isEmpty()) { - m_services.push_back(getApiServicesData(data)); - m_selectedServiceIndex = 0; - } else { - for (const auto &service : services) { - auto serviceObject = service.toObject(); - m_services.push_back(getApiServicesData(serviceObject)); - } - } - - endResetModel(); -} - -void ApiServicesModel::setServiceIndex(const int index) -{ - m_selectedServiceIndex = index; -} - -QJsonObject ApiServicesModel::getSelectedServiceInfo() -{ - auto service = m_services.at(m_selectedServiceIndex); - return service.serviceInfo.object; -} - -QString ApiServicesModel::getSelectedServiceType() -{ - auto service = m_services.at(m_selectedServiceIndex); - return service.type; -} - -QString ApiServicesModel::getSelectedServiceProtocol() -{ - auto service = m_services.at(m_selectedServiceIndex); - return service.protocol; -} - -QString ApiServicesModel::getSelectedServiceName() -{ - auto service = m_services.at(m_selectedServiceIndex); - return service.serviceInfo.name; -} - -QJsonArray ApiServicesModel::getSelectedServiceCountries() -{ - auto service = m_services.at(m_selectedServiceIndex); - return service.availableCountries; -} - -QString ApiServicesModel::getCountryCode() -{ - return m_countryCode; -} - -QString ApiServicesModel::getStoreEndpoint() -{ - auto service = m_services.at(m_selectedServiceIndex); - return service.storeEndpoint; -} - -QVariant ApiServicesModel::getSelectedServiceData(const QString roleString) -{ - QModelIndex modelIndex = index(m_selectedServiceIndex); - auto roles = roleNames(); - for (auto it = roles.begin(); it != roles.end(); it++) { - if (QString(it.value()) == roleString) { - return data(modelIndex, it.key()); - } - } - - return {}; -} - -QHash ApiServicesModel::roleNames() const -{ - QHash roles; - roles[NameRole] = "name"; - roles[CardDescriptionRole] = "cardDescription"; - roles[ServiceDescriptionRole] = "serviceDescription"; - roles[IsServiceAvailableRole] = "isServiceAvailable"; - roles[SpeedRole] = "speed"; - roles[TimeLimitRole] = "timeLimit"; - roles[RegionRole] = "region"; - roles[FeaturesRole] = "features"; - roles[PriceRole] = "price"; - roles[EndDateRole] = "endDate"; - - return roles; -} - -ApiServicesModel::ApiServicesData ApiServicesModel::getApiServicesData(const QJsonObject &data) -{ - auto serviceInfo = data.value(configKey::serviceInfo).toObject(); - auto serviceType = data.value(configKey::serviceType).toString(); - auto serviceProtocol = data.value(configKey::serviceProtocol).toString(); - auto availableCountries = data.value(configKey::availableCountries).toArray(); - - auto subscriptionObject = data.value(configKey::subscription).toObject(); - - ApiServicesData serviceData; - serviceData.serviceInfo.name = serviceInfo.value(configKey::name).toString(); - serviceData.serviceInfo.price = serviceInfo.value(configKey::price).toString(); - serviceData.serviceInfo.region = serviceInfo.value(configKey::region).toString(); - serviceData.serviceInfo.speed = serviceInfo.value(configKey::speed).toString(); - serviceData.serviceInfo.timeLimit = serviceInfo.value(configKey::timelimit).toString(); - - serviceData.type = serviceType; - serviceData.protocol = serviceProtocol; - - serviceData.storeEndpoint = data.value(configKey::storeEndpoint).toString(); - - if (data.value(configKey::isAvailable).isBool()) { - serviceData.isServiceAvailable = data.value(configKey::isAvailable).toBool(); - } else { - serviceData.isServiceAvailable = true; - } - - serviceData.serviceInfo.object = serviceInfo; - serviceData.availableCountries = availableCountries; - - serviceData.subscription.endDate = subscriptionObject.value(configKey::endDate).toString(); - - return serviceData; -} diff --git a/client/ui/models/api/apiServicesModel.h b/client/ui/models/api/apiServicesModel.h deleted file mode 100644 index c96a49ab..00000000 --- a/client/ui/models/api/apiServicesModel.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef APISERVICESMODEL_H -#define APISERVICESMODEL_H - -#include -#include -#include - -class ApiServicesModel : public QAbstractListModel -{ - Q_OBJECT - -public: - enum Roles { - NameRole = Qt::UserRole + 1, - CardDescriptionRole, - ServiceDescriptionRole, - IsServiceAvailableRole, - SpeedRole, - TimeLimitRole, - RegionRole, - FeaturesRole, - PriceRole, - EndDateRole - }; - - explicit ApiServicesModel(QObject *parent = nullptr); - - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - -public slots: - void updateModel(const QJsonObject &data); - - void setServiceIndex(const int index); - - QJsonObject getSelectedServiceInfo(); - QString getSelectedServiceType(); - QString getSelectedServiceProtocol(); - QString getSelectedServiceName(); - QJsonArray getSelectedServiceCountries(); - - QString getCountryCode(); - - QString getStoreEndpoint(); - - QVariant getSelectedServiceData(const QString roleString); - -protected: - QHash roleNames() const override; - -private: - struct ServiceInfo - { - QString name; - QString speed; - QString timeLimit; - QString region; - QString price; - - QJsonObject object; - }; - - struct Subscription - { - QString endDate; - }; - - struct ApiServicesData - { - bool isServiceAvailable; - - QString type; - QString protocol; - QString storeEndpoint; - - ServiceInfo serviceInfo; - Subscription subscription; - - QJsonArray availableCountries; - }; - - ApiServicesData getApiServicesData(const QJsonObject &data); - - QString m_countryCode; - QVector m_services; - - int m_selectedServiceIndex; -}; - -#endif // APISERVICESMODEL_H diff --git a/client/ui/qml/Components/RenameServerDrawer.qml b/client/ui/qml/Components/RenameServerDrawer.qml deleted file mode 100644 index d65b9bba..00000000 --- a/client/ui/qml/Components/RenameServerDrawer.qml +++ /dev/null @@ -1,55 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts - -import Style 1.0 - -import "../Controls2" -import "../Controls2/TextTypes" - -import "../Config" - -DrawerType2 { - property string serverNameText - - id: root - objectName: "serverNameEditDrawer" - - expandedStateContent: ColumnLayout { - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.topMargin: 32 - anchors.leftMargin: 16 - anchors.rightMargin: 16 - - TextFieldWithHeaderType { - id: serverName - - Layout.fillWidth: true - headerText: qsTr("Server name") - textField.text: root.serverNameText - textField.maximumLength: 30 - checkEmptyText: true - } - - BasicButtonType { - id: saveButton - - Layout.fillWidth: true - - text: qsTr("Save") - - clickedFunc: function() { - if (serverName.textField.text === "") { - return - } - - if (serverName.textField.text !== root.serverNameText) { - ServersModel.setProcessedServerData("name", serverName.textField.text); - } - root.closeTriggered() - } - } - } -} diff --git a/client/ui/qml/Controls2/ListViewType.qml b/client/ui/qml/Controls2/ListViewType.qml deleted file mode 100644 index 0de43d77..00000000 --- a/client/ui/qml/Controls2/ListViewType.qml +++ /dev/null @@ -1,38 +0,0 @@ -import QtQuick -import QtQuick.Controls - -ListView { - id: root - - property bool isFocusable: true - - Keys.onTabPressed: { - FocusController.nextKeyTabItem() - } - - Keys.onBacktabPressed: { - FocusController.previousKeyTabItem() - } - - Keys.onUpPressed: { - FocusController.nextKeyUpItem() - } - - Keys.onDownPressed: { - FocusController.nextKeyDownItem() - } - - Keys.onLeftPressed: { - FocusController.nextKeyLeftItem() - } - - Keys.onRightPressed: { - FocusController.nextKeyRightItem() - } - - ScrollBar.vertical: ScrollBarType {} - - clip: true - reuseItems: true - snapMode: ListView.SnapToItem -} diff --git a/client/ui/qml/Pages2/PageSettingsApiAvailableCountries.qml b/client/ui/qml/Pages2/PageSettingsApiAvailableCountries.qml deleted file mode 100644 index 43fbb160..00000000 --- a/client/ui/qml/Pages2/PageSettingsApiAvailableCountries.qml +++ /dev/null @@ -1,171 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Dialogs - -import SortFilterProxyModel 0.2 - -import PageEnum 1.0 -import Style 1.0 - -import "./" -import "../Controls2" -import "../Controls2/TextTypes" -import "../Config" -import "../Components" - -PageType { - id: root - - property var processedServer - - Connections { - target: ServersModel - - function onProcessedServerChanged() { - root.processedServer = proxyServersModel.get(0) - } - } - - SortFilterProxyModel { - id: proxyServersModel - objectName: "proxyServersModel" - - sourceModel: ServersModel - filters: [ - ValueFilter { - roleName: "isCurrentlyProcessed" - value: true - } - ] - - Component.onCompleted: { - root.processedServer = proxyServersModel.get(0) - } - } - - ListViewType { - id: menuContent - - anchors.fill: parent - - model: ApiCountryModel - - currentIndex: 0 - - ButtonGroup { - id: containersRadioButtonGroup - } - - header: ColumnLayout { - width: menuContent.width - - spacing: 4 - - BackButtonType { - id: backButton - objectName: "backButton" - - Layout.topMargin: 20 - } - - HeaderType { - id: headerContent - objectName: "headerContent" - - Layout.fillWidth: true - Layout.leftMargin: 16 - Layout.rightMargin: 16 - Layout.bottomMargin: 10 - - actionButtonImage: "qrc:/images/controls/settings.svg" - - headerText: root.processedServer.name - descriptionText: qsTr("Locations for connection") - - actionButtonFunction: function() { - PageController.showBusyIndicator(true) - let result = ApiSettingsController.getAccountInfo(false) - PageController.showBusyIndicator(false) - if (!result) { - return - } - - PageController.goToPage(PageEnum.PageSettingsApiServerInfo) - } - } - } - - delegate: ColumnLayout { - id: content - - width: menuContent.width - height: content.implicitHeight - - RowLayout { - VerticalRadioButton { - id: containerRadioButton - - Layout.fillWidth: true - Layout.leftMargin: 16 - - text: countryName - - ButtonGroup.group: containersRadioButtonGroup - - imageSource: "qrc:/images/controls/download.svg" - - checked: index === ApiCountryModel.currentIndex - checkable: !ConnectionController.isConnected - - onClicked: { - if (ConnectionController.isConnected) { - PageController.showNotificationMessage(qsTr("Unable change server location while there is an active connection")) - return - } - - if (index !== ApiCountryModel.currentIndex) { - PageController.showBusyIndicator(true) - var prevIndex = ApiCountryModel.currentIndex - ApiCountryModel.currentIndex = index - if (!ApiConfigsController.updateServiceFromGateway(ServersModel.defaultIndex, countryCode, countryName)) { - ApiCountryModel.currentIndex = prevIndex - } - PageController.showBusyIndicator(false) - } - } - - MouseArea { - anchors.fill: containerRadioButton - cursorShape: Qt.PointingHandCursor - enabled: false - } - - Keys.onEnterPressed: { - if (checkable) { - checked = true - } - containerRadioButton.clicked() - } - Keys.onReturnPressed: { - if (checkable) { - checked = true - } - containerRadioButton.clicked() - } - } - - Image { - Layout.rightMargin: 32 - Layout.alignment: Qt.AlignRight - - source: "qrc:/countriesFlags/images/flagKit/" + countryImageCode + ".svg" - } - } - - DividerType { - Layout.fillWidth: true - } - } - } -} diff --git a/client/ui/qml/Pages2/PageSettingsApiDevices.qml b/client/ui/qml/Pages2/PageSettingsApiDevices.qml deleted file mode 100644 index 5cc21d07..00000000 --- a/client/ui/qml/Pages2/PageSettingsApiDevices.qml +++ /dev/null @@ -1,100 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Dialogs - -import QtCore - -import SortFilterProxyModel 0.2 - -import PageEnum 1.0 -import Style 1.0 - -import "./" -import "../Controls2" -import "../Controls2/TextTypes" -import "../Config" -import "../Components" - -PageType { - id: root - - ListViewType { - id: listView - - anchors.fill: parent - anchors.topMargin: 20 - anchors.bottomMargin: 24 - - model: ApiDevicesModel - - header: ColumnLayout { - width: listView.width - - BackButtonType { - id: backButton - } - - HeaderType { - id: header - - Layout.fillWidth: true - Layout.rightMargin: 16 - Layout.leftMargin: 16 - - headerText: qsTr("Connected devices") - descriptionText: qsTr("To manage connected devices") - } - - WarningType { - Layout.topMargin: 16 - Layout.rightMargin: 16 - Layout.leftMargin: 16 - Layout.fillWidth: true - - textString: qsTr("You can find the identifier on the Support tab or, for older versions of the app, " - + "by tapping '+' and then the three dots at the top of the page.") - - iconPath: "qrc:/images/controls/alert-circle.svg" - } - } - - delegate: ColumnLayout { - width: listView.width - - LabelWithButtonType { - Layout.fillWidth: true - Layout.topMargin: 6 - - text: osVersion + (isCurrentDevice ? qsTr(" (current device)") : "") - descriptionText: qsTr("Support tag: ") + "\n" + supportTag + "\n" + qsTr("Last updated: ") + lastUpdate - rightImageSource: "qrc:/images/controls/trash.svg" - - clickedFunction: function() { - var headerText = qsTr("Deactivate the subscription on selected device") - var descriptionText = qsTr("The next time the “Connect” button is pressed, the device will be activated again") - var yesButtonText = qsTr("Continue") - var noButtonText = qsTr("Cancel") - - var yesButtonFunction = function() { - Qt.callLater(deactivateExternalDevice, supportTag, countryCode) - } - var noButtonFunction = function() { - } - - showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) - } - } - - DividerType {} - } - } - - function deactivateExternalDevice(supportTag, countryCode) { - PageController.showBusyIndicator(true) - if (ApiConfigsController.deactivateExternalDevice(supportTag, countryCode)) { - ApiSettingsController.getAccountInfo(true) - } - PageController.showBusyIndicator(false) - } -} diff --git a/client/ui/qml/Pages2/PageSettingsApiInstructions.qml b/client/ui/qml/Pages2/PageSettingsApiInstructions.qml deleted file mode 100644 index 3651407b..00000000 --- a/client/ui/qml/Pages2/PageSettingsApiInstructions.qml +++ /dev/null @@ -1,124 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts - -import SortFilterProxyModel 0.2 - -import PageEnum 1.0 -import Style 1.0 - -import "./" -import "../Controls2" -import "../Controls2/TextTypes" -import "../Config" -import "../Components" - -PageType { - id: root - - QtObject { - id: windows - - readonly property string title: qsTr("Windows") - readonly property string link: qsTr("https://docs.amnezia.org/documentation/instructions/connect-amnezia-premium#windows") - } - - QtObject { - id: macos - - readonly property string title: qsTr("macOS") - readonly property string link: qsTr("https://docs.amnezia.org/documentation/instructions/connect-amnezia-premium#macos") - } - - QtObject { - id: android - - readonly property string title: qsTr("Android") - readonly property string link: qsTr("https://docs.amnezia.org/documentation/instructions/connect-amnezia-premium#android") - } - - QtObject { - id: androidTv - - readonly property string title: qsTr("AndroidTV") - readonly property string link: qsTr("https://docs.amnezia.org/ru/documentation/instructions/android_tv_connect/") - } - - QtObject { - id: ios - - readonly property string title: qsTr("iOS") - readonly property string link: qsTr("https://docs.amnezia.org/documentation/instructions/connect-amnezia-premium#ios") - } - - QtObject { - id: linux - - readonly property string title: qsTr("Linux") - readonly property string link: qsTr("https://docs.amnezia.org/documentation/instructions/connect-amnezia-premium#linux") - } - - QtObject { - id: routers - - readonly property string title: qsTr("Routers") - readonly property string link: qsTr("https://docs.amnezia.org/documentation/instructions/connect-amnezia-premium#routers") - } - - property list instructionsModel: [ - windows, - macos, - android, - androidTv, - ios, - linux, - routers - ] - - ListViewType { - id: listView - - anchors.fill: parent - anchors.topMargin: 20 - anchors.bottomMargin: 24 - - model: instructionsModel - - header: ColumnLayout { - width: listView.width - - BackButtonType { - id: backButton - } - - HeaderType { - id: header - - Layout.fillWidth: true - Layout.rightMargin: 16 - Layout.leftMargin: 16 - - headerText: qsTr("How to connect on another device") - descriptionText: qsTr("Instructions on the Amnezia website") - } - } - - delegate: ColumnLayout { - width: listView.width - - LabelWithButtonType { - Layout.fillWidth: true - Layout.topMargin: 6 - - text: title - rightImageSource: "qrc:/images/controls/external-link.svg" - - clickedFunction: function() { - Qt.openUrlExternally(link) - } - } - - DividerType {} - } - } -} diff --git a/client/ui/qml/Pages2/PageSettingsApiNativeConfigs.qml b/client/ui/qml/Pages2/PageSettingsApiNativeConfigs.qml deleted file mode 100644 index a1cc1fb8..00000000 --- a/client/ui/qml/Pages2/PageSettingsApiNativeConfigs.qml +++ /dev/null @@ -1,214 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Dialogs - -import QtCore - -import SortFilterProxyModel 0.2 - -import PageEnum 1.0 -import Style 1.0 - -import "./" -import "../Controls2" -import "../Controls2/TextTypes" -import "../Config" -import "../Components" - -PageType { - id: root - - property string configExtension: ".conf" - property string configCaption: qsTr("Save AmneziaVPN config") - - ListViewType { - id: listView - - anchors.fill: parent - anchors.topMargin: 20 - anchors.bottomMargin: 24 - - model: ApiCountryModel - - header: ColumnLayout { - width: listView.width - - BackButtonType { - id: backButton - } - - HeaderType { - id: header - - Layout.fillWidth: true - Layout.rightMargin: 16 - Layout.leftMargin: 16 - - headerText: qsTr("Configuration files") - descriptionText: qsTr("To connect a router or AmneziaWG application") - } - } - - delegate: ColumnLayout { - width: listView.width - - LabelWithButtonType { - Layout.fillWidth: true - Layout.topMargin: 6 - - text: countryName - descriptionText: isWorkerExpired ? qsTr("The configuration needs to be reissued") : "" - descriptionColor: AmneziaStyle.color.vibrantRed - - leftImageSource: "qrc:/countriesFlags/images/flagKit/" + countryImageCode + ".svg" - rightImageSource: isIssued ? "qrc:/images/controls/more-vertical.svg" : "qrc:/images/controls/download.svg" - - clickedFunction: function() { - if (isIssued) { - moreOptionsDrawer.countryName = countryName - moreOptionsDrawer.countryCode = countryCode - moreOptionsDrawer.openTriggered() - } else { - issueConfig(countryCode) - } - } - } - - DividerType {} - } - } - - DrawerType2 { - id: moreOptionsDrawer - - property string countryName - property string countryCode - - anchors.fill: parent - expandedHeight: parent.height * 0.4375 - - expandedStateContent: Item { - implicitHeight: moreOptionsDrawer.expandedHeight - - BackButtonType { - id: moreOptionsDrawerBackButton - - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.topMargin: 16 - - backButtonFunction: function() { - moreOptionsDrawer.closeTriggered() - } - } - - FlickableType { - anchors.top: moreOptionsDrawerBackButton.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - - contentHeight: moreOptionsDrawerContent.height - - ColumnLayout { - id: moreOptionsDrawerContent - - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - - Header2Type { - Layout.fillWidth: true - Layout.margins: 16 - - headerText: qsTr("Configuration file ") + moreOptionsDrawer.countryName - } - - LabelWithButtonType { - Layout.fillWidth: true - - text: qsTr("Create a new") - descriptionText: qsTr("The previously created one will stop working") - - clickedFunction: function() { - showQuestion(true, moreOptionsDrawer.countryCode, moreOptionsDrawer.countryName) - } - } - - DividerType {} - - LabelWithButtonType { - Layout.fillWidth: true - text: qsTr("Revoke the current configuration file") - - clickedFunction: function() { - showQuestion(false, moreOptionsDrawer.countryCode, moreOptionsDrawer.countryName) - } - } - - DividerType {} - } - } - } - } - - function issueConfig(countryCode) { - var fileName = "" - if (GC.isMobile()) { - fileName = countryCode + configExtension - } else { - fileName = SystemController.getFileName(configCaption, - qsTr("Config files (*" + configExtension + ")"), - StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/" + countryCode, - true, - configExtension) - } - if (fileName !== "") { - PageController.showBusyIndicator(true) - let result = ApiConfigsController.exportNativeConfig(countryCode, fileName) - if (result) { - ApiSettingsController.getAccountInfo(true) - } - - PageController.showBusyIndicator(false) - if (result) { - PageController.showNotificationMessage(qsTr("Config file saved")) - } - } - } - - function revokeConfig(countryCode) { - PageController.showBusyIndicator(true) - let result = ApiConfigsController.revokeNativeConfig(countryCode) - if (result) { - ApiSettingsController.getAccountInfo(true) - } - PageController.showBusyIndicator(false) - - if (result) { - PageController.showNotificationMessage(qsTr("The config has been revoked")) - } - } - - function showQuestion(isConfigIssue, countryCode, countryName) { - var headerText = qsTr("Revoke the actual %1 configuration file?").arg(countryName) - var descriptionText = qsTr("The previously created file will no longer be valid. It will not be possible to connect using it.") - var yesButtonText = qsTr("Continue") - var noButtonText = qsTr("Cancel") - - var yesButtonFunction = function() { - if (isConfigIssue) { - issueConfig(countryCode) - } else { - revokeConfig(countryCode) - } - moreOptionsDrawer.closeTriggered() - } - var noButtonFunction = function() { - } - - showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) - } -} diff --git a/client/ui/qml/Pages2/PageSettingsApiSupport.qml b/client/ui/qml/Pages2/PageSettingsApiSupport.qml deleted file mode 100644 index 424e10c5..00000000 --- a/client/ui/qml/Pages2/PageSettingsApiSupport.qml +++ /dev/null @@ -1,127 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts - -import SortFilterProxyModel 0.2 - -import PageEnum 1.0 -import Style 1.0 - -import "./" -import "../Controls2" -import "../Controls2/TextTypes" -import "../Config" -import "../Components" - -PageType { - id: root - - QtObject { - id: telegram - - readonly property string title: qsTr("Telegram") - readonly property string description: "@" + ApiAccountInfoModel.getTelegramBotLink() - readonly property string link: "https://t.me/" + ApiAccountInfoModel.getTelegramBotLink() - } - - QtObject { - id: techSupport - - readonly property string title: qsTr("For technical support") - readonly property string description: qsTr("support@amnezia.org") - readonly property string link: "mailto:support@amnezia.org" - } - - QtObject { - id: paymentSupport - - readonly property string title: qsTr("For payment issues") - readonly property string description: qsTr("help@vpnpay.io") - readonly property string link: "mailto:help@vpnpay.io" - } - - QtObject { - id: site - - readonly property string title: qsTr("Site") - readonly property string description: qsTr("amnezia.org") - readonly property string link: LanguageModel.getCurrentSiteUrl() - } - - property list supportModel: [ - telegram, - techSupport, - paymentSupport, - site - ] - - ListViewType { - id: listView - - anchors.fill: parent - anchors.topMargin: 20 - anchors.bottomMargin: 24 - - model: supportModel - - header: ColumnLayout { - width: listView.width - - BackButtonType { - id: backButton - } - - HeaderType { - id: header - - Layout.fillWidth: true - Layout.rightMargin: 16 - Layout.leftMargin: 16 - - headerText: qsTr("Support") - descriptionText: qsTr("Our technical support specialists are ready to help you at any time") - } - } - - delegate: ColumnLayout { - width: listView.width - - LabelWithButtonType { - Layout.fillWidth: true - text: title - descriptionText: description - rightImageSource: "qrc:/images/controls/external-link.svg" - clickedFunction: function() { - Qt.openUrlExternally(link) - } - } - DividerType {} - } - - - footer: ColumnLayout { - width: listView.width - - LabelWithButtonType { - id: supportUuid - Layout.fillWidth: true - - text: qsTr("Support tag") - descriptionText: SettingsController.getInstallationUuid() - - descriptionOnTop: true - - rightImageSource: "qrc:/images/controls/copy.svg" - rightImageColor: AmneziaStyle.color.paleGray - - clickedFunction: function() { - GC.copyToClipBoard(descriptionText) - PageController.showNotificationMessage(qsTr("Copied")) - if (!GC.isMobile()) { - this.rightButton.forceActiveFocus() - } - } - } - } - } -}