refactor: remove serverConfig struct (#2595)

* refactor: remove serverConfig struct

* refactor: add warnings for api v1 configs

* refactor: moved the server type definition to a separate namespace

* refactor: simplified gateway stacks

* fix: fixed server description

* fix: fixed postAsync reply usage

* fix: fixed validateConfig call

* fix: fixed server name in notifications

* fix: fixed initPrepareConfigHandler for lagacy configs
This commit is contained in:
vkamn
2026-05-15 12:33:36 +08:00
committed by GitHub
parent 009ca981d5
commit 06372c8fd7
123 changed files with 3558 additions and 3026 deletions
+1 -1
View File
@@ -15,7 +15,6 @@ set(HEADERS ${HEADERS}
${CLIENT_ROOT_DIR}/core/utils/constants/protocolConstants.h ${CLIENT_ROOT_DIR}/core/utils/constants/protocolConstants.h
${CLIENT_ROOT_DIR}/core/utils/constants/apiKeys.h ${CLIENT_ROOT_DIR}/core/utils/constants/apiKeys.h
${CLIENT_ROOT_DIR}/core/utils/constants/apiConstants.h ${CLIENT_ROOT_DIR}/core/utils/constants/apiConstants.h
${CLIENT_ROOT_DIR}/core/utils/api/apiEnums.h
${CLIENT_ROOT_DIR}/core/utils/errorStrings.h ${CLIENT_ROOT_DIR}/core/utils/errorStrings.h
${CLIENT_ROOT_DIR}/core/utils/selfhosted/scriptsRegistry.h ${CLIENT_ROOT_DIR}/core/utils/selfhosted/scriptsRegistry.h
${CLIENT_ROOT_DIR}/core/utils/qrCodeUtils.h ${CLIENT_ROOT_DIR}/core/utils/qrCodeUtils.h
@@ -138,6 +137,7 @@ set(SOURCES ${SOURCES}
${CLIENT_ROOT_DIR}/../common/logger/logger.cpp ${CLIENT_ROOT_DIR}/../common/logger/logger.cpp
${CLIENT_ROOT_DIR}/ui/utils/qmlUtils.cpp ${CLIENT_ROOT_DIR}/ui/utils/qmlUtils.cpp
${CLIENT_ROOT_DIR}/core/utils/api/apiUtils.cpp ${CLIENT_ROOT_DIR}/core/utils/api/apiUtils.cpp
${CLIENT_ROOT_DIR}/core/utils/serverConfigUtils.cpp
${CLIENT_ROOT_DIR}/core/utils/osSignalHandler.cpp ${CLIENT_ROOT_DIR}/core/utils/osSignalHandler.cpp
${CLIENT_ROOT_DIR}/core/utils/utilities.cpp ${CLIENT_ROOT_DIR}/core/utils/utilities.cpp
${CLIENT_ROOT_DIR}/core/utils/managementServer.cpp ${CLIENT_ROOT_DIR}/core/utils/managementServer.cpp
+62 -21
View File
@@ -1,51 +1,93 @@
#include "newsController.h" #include "newsController.h"
#include "core/controllers/gatewayController.h" #include "core/controllers/gatewayController.h"
#include "core/utils/api/apiEnums.h" #include "core/repositories/secureServersRepository.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
#include "core/utils/constants/configKeys.h"
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
#include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QSet>
#include <QSharedPointer> #include <QSharedPointer>
using namespace amnezia; using namespace amnezia;
NewsController::NewsController(SecureAppSettingsRepository* appSettingsRepository, NewsController::NewsController(SecureAppSettingsRepository *appSettingsRepository,
ServersController* serversController) SecureServersRepository *serversRepository)
: m_appSettingsRepository(appSettingsRepository), m_serversController(serversController) : m_appSettingsRepository(appSettingsRepository),
m_serversRepository(serversRepository)
{ {
} }
QJsonObject NewsController::getServicesList() const
{
if (!m_serversRepository) {
return {};
}
QSet<QString> userCountryCodes;
QSet<QString> serviceTypes;
const QVector<QString> ids = m_serversRepository->orderedServerIds();
for (const QString &id : ids) {
const auto apiV2 = m_serversRepository->apiV2Config(id);
if (!apiV2.has_value()) {
continue;
}
if (!apiV2->apiConfig.userCountryCode.isEmpty()) {
userCountryCodes.insert(apiV2->apiConfig.userCountryCode);
}
const QString serviceType = apiV2->serviceType();
if (!serviceType.isEmpty()) {
serviceTypes.insert(serviceType);
}
}
if (userCountryCodes.isEmpty() && serviceTypes.isEmpty()) {
return {};
}
QJsonObject json;
QJsonArray userCountryCodesArray;
for (const QString &code : userCountryCodes) {
userCountryCodesArray.append(code);
}
json[apiDefs::key::userCountryCode] = userCountryCodesArray;
QJsonArray serviceTypesArray;
for (const QString &type : serviceTypes) {
serviceTypesArray.append(type);
}
json[apiDefs::key::serviceType] = serviceTypesArray;
return json;
}
QFuture<QPair<ErrorCode, QJsonArray>> NewsController::fetchNews() QFuture<QPair<ErrorCode, QJsonArray>> NewsController::fetchNews()
{ {
if (!m_serversController) { if (!m_serversRepository) {
qWarning() << "ServersController is null, skip fetchNews"; qWarning() << "SecureServersRepository is null, skip fetchNews";
return QtFuture::makeReadyFuture(qMakePair(ErrorCode::InternalError, QJsonArray())); return QtFuture::makeReadyFuture(qMakePair(ErrorCode::InternalError, QJsonArray()));
} }
const auto stacks = m_serversController->gatewayStacks(); const QJsonObject services = getServicesList();
if (stacks.isEmpty()) { if (services.isEmpty()) {
qDebug() << "No Gateway stacks, skip fetchNews"; qDebug() << "No Gateway stacks, skip fetchNews";
return QtFuture::makeReadyFuture(qMakePair(ErrorCode::NoError, QJsonArray())); return QtFuture::makeReadyFuture(qMakePair(ErrorCode::NoError, QJsonArray()));
} }
auto gatewayController = QSharedPointer<GatewayController>::create( auto gatewayController = QSharedPointer<GatewayController>::create(
m_appSettingsRepository->getGatewayEndpoint(), m_appSettingsRepository->getGatewayEndpoint(),
m_appSettingsRepository->isDevGatewayEnv(), m_appSettingsRepository->isDevGatewayEnv(),
apiDefs::requestTimeoutMsecs, apiDefs::requestTimeoutMsecs,
m_appSettingsRepository->isStrictKillSwitchEnabled()); m_appSettingsRepository->isStrictKillSwitchEnabled());
QJsonObject payload; QJsonObject payload;
payload.insert("locale", m_appSettingsRepository->getAppLanguage().name().split("_").first()); payload.insert("locale", m_appSettingsRepository->getAppLanguage().name().split("_").first());
const QJsonObject stacksJson = stacks.toJson(); if (services.contains(apiDefs::key::userCountryCode)) {
if (stacksJson.contains(apiDefs::key::userCountryCode)) { payload.insert(apiDefs::key::userCountryCode, services.value(apiDefs::key::userCountryCode));
payload.insert(apiDefs::key::userCountryCode, stacksJson.value(apiDefs::key::userCountryCode));
} }
if (stacksJson.contains(apiDefs::key::serviceType)) { if (services.contains(apiDefs::key::serviceType)) {
payload.insert(apiDefs::key::serviceType, stacksJson.value(apiDefs::key::serviceType)); payload.insert(apiDefs::key::serviceType, services.value(apiDefs::key::serviceType));
} }
auto future = gatewayController->postAsync(QString("%1v1/news"), payload); auto future = gatewayController->postAsync(QString("%1v1/news"), payload);
@@ -69,4 +111,3 @@ QFuture<QPair<ErrorCode, QJsonArray>> NewsController::fetchNews()
return qMakePair(ErrorCode::NoError, newsArray); return qMakePair(ErrorCode::NoError, newsArray);
}); });
} }
+6 -4
View File
@@ -3,26 +3,28 @@
#include <QFuture> #include <QFuture>
#include <QJsonArray> #include <QJsonArray>
#include <QJsonObject>
#include <QPair> #include <QPair>
#include "core/utils/errorCodes.h" #include "core/utils/errorCodes.h"
#include "core/utils/routeModes.h" #include "core/utils/routeModes.h"
#include "core/utils/commonStructs.h" #include "core/utils/commonStructs.h"
#include "core/repositories/secureAppSettingsRepository.h" #include "core/repositories/secureAppSettingsRepository.h"
#include "core/controllers/serversController.h" #include "core/repositories/secureServersRepository.h"
class NewsController class NewsController
{ {
public: public:
explicit NewsController(SecureAppSettingsRepository* appSettingsRepository, explicit NewsController(SecureAppSettingsRepository* appSettingsRepository,
ServersController* serversController); SecureServersRepository* serversRepository);
QFuture<QPair<ErrorCode, QJsonArray>> fetchNews(); QFuture<QPair<ErrorCode, QJsonArray>> fetchNews();
private: private:
QJsonObject getServicesList() const;
SecureAppSettingsRepository* m_appSettingsRepository; SecureAppSettingsRepository* m_appSettingsRepository;
ServersController* m_serversController; SecureServersRepository* m_serversRepository;
}; };
#endif // NEWSCONTROLLER_H #endif // NEWSCONTROLLER_H
@@ -11,7 +11,7 @@
#include <limits> #include <limits>
#include "core/controllers/gatewayController.h" #include "core/controllers/gatewayController.h"
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
#include "version.h" #include "version.h"
@@ -16,7 +16,7 @@
#include "core/utils/containerEnum.h" #include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h" #include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h" #include "core/utils/protocolEnum.h"
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
#include "core/utils/api/apiUtils.h" #include "core/utils/api/apiUtils.h"
@@ -26,7 +26,6 @@
#include "core/utils/constants/configKeys.h" #include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h" #include "core/utils/constants/protocolConstants.h"
#include "version.h" #include "version.h"
#include "core/models/serverConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/models/api/apiConfig.h" #include "core/models/api/apiConfig.h"
@@ -196,7 +195,7 @@ void SubscriptionController::updateApiConfigInJson(QJsonObject &serverConfigJson
apiConfig[apiDefs::key::serviceProtocol] = serviceProtocol; apiConfig[apiDefs::key::serviceProtocol] = serviceProtocol;
apiConfig[apiDefs::key::userCountryCode] = userCountryCode; apiConfig[apiDefs::key::userCountryCode] = userCountryCode;
if (serverConfigJson.value(configKey::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) { if (serverConfigJson.value(configKey::configVersion).toInt() == serverConfigUtils::ConfigSource::AmneziaGateway) {
QJsonObject responseObj = QJsonDocument::fromJson(apiResponseBody).object(); QJsonObject responseObj = QJsonDocument::fromJson(apiResponseBody).object();
if (responseObj.contains(apiDefs::key::supportedProtocols)) { if (responseObj.contains(apiDefs::key::supportedProtocols)) {
apiConfig.insert(apiDefs::key::supportedProtocols, responseObj.value(apiDefs::key::supportedProtocols).toArray()); apiConfig.insert(apiDefs::key::supportedProtocols, responseObj.value(apiDefs::key::supportedProtocols).toArray());
@@ -217,8 +216,7 @@ ErrorCode SubscriptionController::executeRequest(const QString &endpoint, const
} }
ErrorCode SubscriptionController::importServiceFromGateway(const QString &userCountryCode, const QString &serviceType, ErrorCode SubscriptionController::importServiceFromGateway(const QString &userCountryCode, const QString &serviceType,
const QString &serviceProtocol, const ProtocolData &protocolData, const QString &serviceProtocol, const ProtocolData &protocolData)
ServerConfig &serverConfig)
{ {
GatewayRequestData gatewayRequestData { QSysInfo::productType(), GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION), QString(APP_VERSION),
@@ -247,20 +245,18 @@ ErrorCode SubscriptionController::importServiceFromGateway(const QString &userCo
updateApiConfigInJson(serverConfigJson, serviceType, serviceProtocol, userCountryCode, responseBody); updateApiConfigInJson(serverConfigJson, serviceType, serviceProtocol, userCountryCode, responseBody);
ServerConfig serverConfigModel = ServerConfig::fromJson(serverConfigJson); if (serverConfigJson.value(configKey::configVersion).toInt() != serverConfigUtils::ConfigSource::AmneziaGateway) {
if (!serverConfigModel.isApiV2()) {
return ErrorCode::InternalError; return ErrorCode::InternalError;
} }
m_serversRepository->addServer(serverConfigModel); ApiV2ServerConfig apiV2ServerConfig = ApiV2ServerConfig::fromJson(serverConfigJson);
serverConfig = serverConfigModel; m_serversRepository->addServer(QString(), apiV2ServerConfig.toJson(),
serverConfigUtils::configTypeFromJson(apiV2ServerConfig.toJson()));
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode SubscriptionController::importTrialFromGateway(const QString &userCountryCode, const QString &serviceType, ErrorCode SubscriptionController::importTrialFromGateway(const QString &userCountryCode, const QString &serviceType,
const QString &serviceProtocol, const QString &email, const QString &serviceProtocol, const QString &email)
ServerConfig &serverConfig)
{ {
const QString trimmedEmail = email.trimmed(); const QString trimmedEmail = email.trimmed();
if (trimmedEmail.isEmpty()) { if (trimmedEmail.isEmpty()) {
@@ -306,16 +302,19 @@ ErrorCode SubscriptionController::importTrialFromGateway(const QString &userCoun
} }
QJsonObject configObject = QJsonDocument::fromJson(configBytes).object(); QJsonObject configObject = QJsonDocument::fromJson(configBytes).object();
ServerConfig serverConfigModel = ServerConfig::fromJson(configObject); if (configObject.value(configKey::configVersion).toInt() != serverConfigUtils::ConfigSource::AmneziaGateway) {
m_serversRepository->addServer(serverConfigModel); return ErrorCode::InternalError;
serverConfig = serverConfigModel; }
ApiV2ServerConfig apiV2ServerConfig = ApiV2ServerConfig::fromJson(configObject);
m_serversRepository->addServer(QString(), apiV2ServerConfig.toJson(),
serverConfigUtils::configTypeFromJson(apiV2ServerConfig.toJson()));
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode SubscriptionController::importServiceFromAppStore(const QString &userCountryCode, const QString &serviceType, ErrorCode SubscriptionController::importServiceFromAppStore(const QString &userCountryCode, const QString &serviceType,
const QString &serviceProtocol, const ProtocolData &protocolData, const QString &serviceProtocol, const ProtocolData &protocolData,
const QString &transactionId, bool isTestPurchase, const QString &transactionId, bool isTestPurchase,
ServerConfig &serverConfig,
int *duplicateServerIndex) int *duplicateServerIndex)
{ {
GatewayRequestData gatewayRequestData { QSysInfo::productType(), GatewayRequestData gatewayRequestData { QSysInfo::productType(),
@@ -351,15 +350,8 @@ ErrorCode SubscriptionController::importServiceFromAppStore(const QString &userC
// Check if server with this VPN key already exists // Check if server with this VPN key already exists
for (int i = 0; i < m_serversRepository->serversCount(); ++i) { for (int i = 0; i < m_serversRepository->serversCount(); ++i) {
ServerConfig existingServerConfig = m_serversRepository->server(i); const auto apiV2 = m_serversRepository->apiV2Config(m_serversRepository->serverIdAt(i));
QString existingVpnKey; QString existingVpnKey = apiV2.has_value() ? apiV2->vpnKey() : QString();
if (existingServerConfig.isApiV1()) {
const ApiV1ServerConfig* apiV1 = existingServerConfig.as<ApiV1ServerConfig>();
existingVpnKey = apiV1 ? apiV1->vpnKey() : QString();
} else if (existingServerConfig.isApiV2()) {
const ApiV2ServerConfig* apiV2 = existingServerConfig.as<ApiV2ServerConfig>();
existingVpnKey = apiV2 ? apiV2->vpnKey() : QString();
}
existingVpnKey.replace(QStringLiteral("vpn://"), QString()); existingVpnKey.replace(QStringLiteral("vpn://"), QString());
if (!existingVpnKey.isEmpty() && existingVpnKey == normalizedKey) { if (!existingVpnKey.isEmpty() && existingVpnKey == normalizedKey) {
if (duplicateServerIndex) { if (duplicateServerIndex) {
@@ -385,38 +377,28 @@ ErrorCode SubscriptionController::importServiceFromAppStore(const QString &userC
quint16 crc = qChecksum(QJsonDocument(configObject).toJson()); quint16 crc = qChecksum(QJsonDocument(configObject).toJson());
ServerConfig serverConfigModel = ServerConfig::fromJson(configObject); if (configObject.value(configKey::configVersion).toInt() != serverConfigUtils::ConfigSource::AmneziaGateway) {
if (!serverConfigModel.isApiV2()) {
return ErrorCode::InternalError; return ErrorCode::InternalError;
} }
ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>(); ApiV2ServerConfig apiV2ServerConfig = ApiV2ServerConfig::fromJson(configObject);
if (!apiV2) { ApiV2ServerConfig* apiV2 = &apiV2ServerConfig;
return ErrorCode::InternalError;
}
apiV2->apiConfig.vpnKey = normalizedKey; apiV2->apiConfig.vpnKey = normalizedKey;
apiV2->apiConfig.isTestPurchase = isTestPurchase; apiV2->apiConfig.isTestPurchase = isTestPurchase;
apiV2->apiConfig.isInAppPurchase = true; apiV2->apiConfig.isInAppPurchase = true;
apiV2->apiConfig.subscriptionExpiredByServer = false; apiV2->apiConfig.subscriptionExpiredByServer = false;
apiV2->crc = crc; apiV2->crc = crc;
m_serversRepository->addServer(serverConfigModel); m_serversRepository->addServer(QString(), apiV2ServerConfig.toJson(),
serverConfig = serverConfigModel; serverConfigUtils::configTypeFromJson(apiV2ServerConfig.toJson()));
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode SubscriptionController::updateServiceFromGateway(int serverIndex, const QString &newCountryCode, bool isConnectEvent) ErrorCode SubscriptionController::updateServiceFromGateway(const QString &serverId, const QString &newCountryCode, bool isConnectEvent)
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (!apiV2.has_value()) {
if (!serverConfigModel.isApiV2()) {
return ErrorCode::InternalError;
}
const ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>();
if (!apiV2) {
return ErrorCode::InternalError; return ErrorCode::InternalError;
} }
const bool isTestPurchase = apiV2->apiConfig.isTestPurchase; const bool isTestPurchase = apiV2->apiConfig.isTestPurchase;
@@ -445,12 +427,10 @@ ErrorCode SubscriptionController::updateServiceFromGateway(int serverIndex, cons
ErrorCode errorCode = executeRequest(QString("%1v1/config"), apiPayload, responseBody, isTestPurchase); ErrorCode errorCode = executeRequest(QString("%1v1/config"), apiPayload, responseBody, isTestPurchase);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
if (errorCode == ErrorCode::ApiSubscriptionExpiredError && !apiV2->apiConfig.isInAppPurchase) { if (errorCode == ErrorCode::ApiSubscriptionExpiredError && !apiV2->apiConfig.isInAppPurchase) {
ServerConfig expiredServerConfig = serverConfigModel; ApiV2ServerConfig expiredApiV2 = *apiV2;
ApiV2ServerConfig *expiredApiV2 = expiredServerConfig.as<ApiV2ServerConfig>(); expiredApiV2.apiConfig.subscriptionExpiredByServer = true;
if (expiredApiV2) { m_serversRepository->editServer(serverId, expiredApiV2.toJson(),
expiredApiV2->apiConfig.subscriptionExpiredByServer = true; serverConfigUtils::configTypeFromJson(expiredApiV2.toJson()));
m_serversRepository->editServer(serverIndex, expiredServerConfig);
}
} }
return errorCode; return errorCode;
} }
@@ -463,16 +443,12 @@ ErrorCode SubscriptionController::updateServiceFromGateway(int serverIndex, cons
updateApiConfigInJson(serverConfigJson, apiV2->apiConfig.serviceType, serviceProtocol, apiV2->apiConfig.userCountryCode, responseBody); updateApiConfigInJson(serverConfigJson, apiV2->apiConfig.serviceType, serviceProtocol, apiV2->apiConfig.userCountryCode, responseBody);
ServerConfig newServerConfigModel = ServerConfig::fromJson(serverConfigJson); if (serverConfigJson.value(configKey::configVersion).toInt() != serverConfigUtils::ConfigSource::AmneziaGateway) {
if (!newServerConfigModel.isApiV2()) {
return ErrorCode::InternalError; return ErrorCode::InternalError;
} }
ApiV2ServerConfig* newApiV2 = newServerConfigModel.as<ApiV2ServerConfig>(); ApiV2ServerConfig newApiV2Config = ApiV2ServerConfig::fromJson(serverConfigJson);
if (!newApiV2) { ApiV2ServerConfig* newApiV2 = &newApiV2Config;
return ErrorCode::InternalError;
}
newApiV2->apiConfig.vpnKey = apiV2->apiConfig.vpnKey; newApiV2->apiConfig.vpnKey = apiV2->apiConfig.vpnKey;
newApiV2->apiConfig.isTestPurchase = apiV2->apiConfig.isTestPurchase; newApiV2->apiConfig.isTestPurchase = apiV2->apiConfig.isTestPurchase;
@@ -487,20 +463,15 @@ ErrorCode SubscriptionController::updateServiceFromGateway(int serverIndex, cons
newApiV2->nameOverriddenByUser = true; newApiV2->nameOverriddenByUser = true;
} }
m_serversRepository->editServer(serverIndex, newServerConfigModel); m_serversRepository->editServer(serverId, newApiV2Config.toJson(),
serverConfigUtils::configTypeFromJson(newApiV2Config.toJson()));
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode SubscriptionController::deactivateDevice(int serverIndex) ErrorCode SubscriptionController::deactivateDevice(const QString &serverId)
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (!apiV2.has_value()) {
if (!serverConfigModel.isApiV2()) {
return ErrorCode::NoError;
}
const ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>();
if (!apiV2) {
return ErrorCode::NoError; return ErrorCode::NoError;
} }
@@ -528,23 +499,16 @@ ErrorCode SubscriptionController::deactivateDevice(int serverIndex)
return errorCode; return errorCode;
} }
serverConfigModel.visit([](auto& arg) { apiV2->containers.clear();
arg.containers.clear(); m_serversRepository->editServer(serverId, apiV2->toJson(),
}); serverConfigUtils::configTypeFromJson(apiV2->toJson()));
m_serversRepository->editServer(serverIndex, serverConfigModel);
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode SubscriptionController::deactivateExternalDevice(int serverIndex, const QString &uuid, const QString &serverCountryCode) ErrorCode SubscriptionController::deactivateExternalDevice(const QString &serverId, const QString &uuid, const QString &serverCountryCode)
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (!apiV2.has_value()) {
if (!serverConfigModel.isApiV2()) {
return ErrorCode::NoError;
}
const ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>();
if (!apiV2) {
return ErrorCode::NoError; return ErrorCode::NoError;
} }
@@ -573,25 +537,18 @@ ErrorCode SubscriptionController::deactivateExternalDevice(int serverIndex, cons
} }
if (uuid == m_appSettingsRepository->getInstallationUuid(true)) { if (uuid == m_appSettingsRepository->getInstallationUuid(true)) {
serverConfigModel.visit([](auto& arg) { apiV2->containers.clear();
arg.containers.clear(); m_serversRepository->editServer(serverId, apiV2->toJson(),
}); serverConfigUtils::configTypeFromJson(apiV2->toJson()));
m_serversRepository->editServer(serverIndex, serverConfigModel);
} }
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode SubscriptionController::exportNativeConfig(int serverIndex, const QString &serverCountryCode, QString &nativeConfig) ErrorCode SubscriptionController::exportNativeConfig(const QString &serverId, const QString &serverCountryCode, QString &nativeConfig)
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (!apiV2.has_value()) {
if (!serverConfigModel.isApiV2()) {
return ErrorCode::InternalError;
}
const ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>();
if (!apiV2) {
return ErrorCode::InternalError; return ErrorCode::InternalError;
} }
const bool isTestPurchase = apiV2->apiConfig.isTestPurchase; const bool isTestPurchase = apiV2->apiConfig.isTestPurchase;
@@ -624,16 +581,10 @@ ErrorCode SubscriptionController::exportNativeConfig(int serverIndex, const QStr
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode SubscriptionController::revokeNativeConfig(int serverIndex, const QString &serverCountryCode) ErrorCode SubscriptionController::revokeNativeConfig(const QString &serverId, const QString &serverCountryCode)
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (!apiV2.has_value()) {
if (!serverConfigModel.isApiV2()) {
return ErrorCode::InternalError;
}
const ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>();
if (!apiV2) {
return ErrorCode::InternalError; return ErrorCode::InternalError;
} }
const bool isTestPurchase = apiV2->apiConfig.isTestPurchase; const bool isTestPurchase = apiV2->apiConfig.isTestPurchase;
@@ -661,126 +612,54 @@ ErrorCode SubscriptionController::revokeNativeConfig(int serverIndex, const QStr
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode SubscriptionController::updateServiceFromTelegram(int serverIndex) ErrorCode SubscriptionController::prepareVpnKeyExport(const QString &serverId, QString &vpnKey)
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (!apiV2.has_value()) {
if (!serverConfigModel.isApiV1()) {
return ErrorCode::InternalError;
}
const ApiV1ServerConfig* apiV1 = serverConfigModel.as<ApiV1ServerConfig>();
if (!apiV1) {
return ErrorCode::InternalError;
}
QString serviceProtocol = apiV1->protocol;
ProtocolData protocolData = generateProtocolData(serviceProtocol);
QString installationUuid = m_appSettingsRepository->getInstallationUuid(true);
GatewayController gatewayController(m_appSettingsRepository->getGatewayEndpoint(), m_appSettingsRepository->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs,
m_appSettingsRepository->isStrictKillSwitchEnabled());
QJsonObject apiPayload;
appendProtocolDataToApiPayload(serviceProtocol, protocolData, apiPayload);
apiPayload[apiDefs::key::uuid] = installationUuid;
apiPayload[apiDefs::key::osVersion] = QSysInfo::productType();
apiPayload[apiDefs::key::appVersion] = QString(APP_VERSION);
apiPayload[configKey::accessToken] = apiV1->apiKey;
apiPayload[apiDefs::key::apiEndpoint] = apiV1->apiEndpoint;
QByteArray responseBody;
ErrorCode errorCode = gatewayController.post(QString("%1v1/proxy_config"), apiPayload, responseBody);
if (errorCode != ErrorCode::NoError) {
return errorCode;
}
QJsonObject serverConfigJson;
errorCode = extractServerConfigJsonFromResponse(responseBody, serviceProtocol, protocolData, serverConfigJson);
if (errorCode != ErrorCode::NoError) {
return errorCode;
}
ServerConfig newServerConfigModel = ServerConfig::fromJson(serverConfigJson);
if (!newServerConfigModel.isApiV1()) {
return ErrorCode::InternalError;
}
ApiV1ServerConfig* newApiV1 = newServerConfigModel.as<ApiV1ServerConfig>();
if (!newApiV1) {
return ErrorCode::InternalError;
}
newApiV1->apiKey = apiV1->apiKey;
newApiV1->apiEndpoint = apiV1->apiEndpoint;
newApiV1->crc = apiV1->crc;
m_serversRepository->editServer(serverIndex, newServerConfigModel);
return ErrorCode::NoError;
}
ErrorCode SubscriptionController::prepareVpnKeyExport(int serverIndex, QString &vpnKey)
{
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex);
if (serverConfigModel.isApiV1()) {
const ApiV1ServerConfig* apiV1 = serverConfigModel.as<ApiV1ServerConfig>();
vpnKey = apiV1 ? apiV1->vpnKey() : QString();
} else if (serverConfigModel.isApiV2()) {
ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>();
vpnKey = apiV2 ? apiV2->vpnKey() : QString();
if (vpnKey.isEmpty()) {
QJsonObject serverJson = serverConfigModel.toJson();
vpnKey = apiUtils::getPremiumV2VpnKey(serverJson);
if (vpnKey.isEmpty()) {
return ErrorCode::ApiConfigEmptyError;
}
apiV2->apiConfig.vpnKey = vpnKey;
m_serversRepository->editServer(serverIndex, serverConfigModel);
}
} else {
return ErrorCode::ApiConfigEmptyError; return ErrorCode::ApiConfigEmptyError;
} }
vpnKey = apiV2->vpnKey();
if (vpnKey.isEmpty()) {
vpnKey = apiUtils::getPremiumV2VpnKey(apiV2->toJson());
if (vpnKey.isEmpty()) {
return ErrorCode::ApiConfigEmptyError;
}
apiV2->apiConfig.vpnKey = vpnKey;
m_serversRepository->editServer(serverId, apiV2->toJson(),
serverConfigUtils::configTypeFromJson(apiV2->toJson()));
}
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode SubscriptionController::validateAndUpdateConfig(int serverIndex, bool hasInstalledContainers) ErrorCode SubscriptionController::validateAndUpdateConfig(const QString &serverId, bool hasInstalledContainers)
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); if (!m_serversRepository->apiV2Config(serverId).has_value()) {
apiDefs::ConfigSource configSource;
if (serverConfigModel.isApiV1()) {
configSource = apiDefs::ConfigSource::Telegram;
} else if (serverConfigModel.isApiV2()) {
configSource = apiDefs::ConfigSource::AmneziaGateway;
} else {
return ErrorCode::NoError; return ErrorCode::NoError;
} }
if (configSource == apiDefs::ConfigSource::Telegram && !hasInstalledContainers) { if (!hasInstalledContainers) {
removeApiConfig(serverIndex); return updateServiceFromGateway(serverId, "", true);
return updateServiceFromTelegram(serverIndex);
} else if (configSource == apiDefs::ConfigSource::AmneziaGateway && !hasInstalledContainers) {
return updateServiceFromGateway(serverIndex, "", true);
} else if (configSource && isApiKeyExpired(serverIndex)) {
qDebug() << "attempt to update api config by expires_at event";
if (configSource == apiDefs::ConfigSource::AmneziaGateway) {
return updateServiceFromGateway(serverIndex, "", true);
} else {
removeApiConfig(serverIndex);
return updateServiceFromTelegram(serverIndex);
}
} }
if (isApiKeyExpired(serverId)) {
qDebug() << "attempt to update api config by expires_at event";
return updateServiceFromGateway(serverId, "", true);
}
return ErrorCode::NoError; return ErrorCode::NoError;
} }
void SubscriptionController::removeApiConfig(int serverIndex) void SubscriptionController::removeApiConfig(const QString &serverId)
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (!apiV2.has_value()) {
return;
}
#if defined(Q_OS_IOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
QString description = serverConfigModel.description(); QString description = apiV2->description;
QString hostName = serverConfigModel.hostName(); QString hostName = apiV2->hostName;
QString vpncName = QString("%1 (%2) %3") QString vpncName = QString("%1 (%2) %3")
.arg(description) .arg(description)
.arg(hostName) .arg(hostName)
@@ -789,34 +668,21 @@ void SubscriptionController::removeApiConfig(int serverIndex)
AmneziaVPN::removeVPNC(vpncName.toStdString()); AmneziaVPN::removeVPNC(vpncName.toStdString());
#endif #endif
serverConfigModel.visit([](auto& arg) { apiV2->dns1.clear();
arg.dns1.clear(); apiV2->dns2.clear();
arg.dns2.clear(); apiV2->containers.clear();
arg.containers.clear(); apiV2->hostName.clear();
arg.hostName.clear(); apiV2->defaultContainer = DockerContainer::None;
arg.defaultContainer = DockerContainer::None; apiV2->apiConfig.publicKey = ApiConfig::PublicKeyInfo{};
});
if (serverConfigModel.isApiV2()) { m_serversRepository->editServer(serverId, apiV2->toJson(),
ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>(); serverConfigUtils::configTypeFromJson(apiV2->toJson()));
if (apiV2) {
apiV2->apiConfig.publicKey = ApiConfig::PublicKeyInfo{};
}
}
m_serversRepository->editServer(serverIndex, serverConfigModel);
} }
bool SubscriptionController::isApiKeyExpired(int serverIndex) const bool SubscriptionController::isApiKeyExpired(const QString &serverId) const
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (!apiV2.has_value()) {
if (!serverConfigModel.isApiV2()) {
return false;
}
const ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>();
if (!apiV2) {
return false; return false;
} }
const QString expiresAt = apiV2->apiConfig.publicKey.expiresAt; const QString expiresAt = apiV2->apiConfig.publicKey.expiresAt;
@@ -833,31 +699,24 @@ bool SubscriptionController::isApiKeyExpired(int serverIndex) const
return false; return false;
} }
void SubscriptionController::setCurrentProtocol(int serverIndex, const QString &protocolName) void SubscriptionController::setCurrentProtocol(const QString &serverId, const QString &protocolName)
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (serverConfigModel.isApiV2()) { if (apiV2.has_value()) {
ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>(); apiV2->apiConfig.serviceProtocol = protocolName;
if (apiV2) { m_serversRepository->editServer(serverId, apiV2->toJson(),
apiV2->apiConfig.serviceProtocol = protocolName; serverConfigUtils::configTypeFromJson(apiV2->toJson()));
}
m_serversRepository->editServer(serverIndex, serverConfigModel);
} }
} }
bool SubscriptionController::isVlessProtocol(int serverIndex) const bool SubscriptionController::isVlessProtocol(const QString &serverId) const
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (serverConfigModel.isApiV2()) { return apiV2.has_value() && apiV2->serviceProtocol() == "vless";
const ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>();
return apiV2 && apiV2->serviceProtocol() == "vless";
}
return false;
} }
ErrorCode SubscriptionController::processAppStorePurchase(const QString &userCountryCode, const QString &serviceType, ErrorCode SubscriptionController::processAppStorePurchase(const QString &userCountryCode, const QString &serviceType,
const QString &serviceProtocol, const QString &productId, const QString &serviceProtocol, const QString &productId,
ServerConfig &serverConfig,
int *duplicateServerIndex) int *duplicateServerIndex)
{ {
#if defined(Q_OS_IOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
@@ -891,13 +750,12 @@ ErrorCode SubscriptionController::processAppStorePurchase(const QString &userCou
ProtocolData protocolData = generateProtocolData(serviceProtocol); ProtocolData protocolData = generateProtocolData(serviceProtocol);
return importServiceFromAppStore(userCountryCode, serviceType, serviceProtocol, protocolData, return importServiceFromAppStore(userCountryCode, serviceType, serviceProtocol, protocolData,
originalTransactionId, isTestPurchase, serverConfig, duplicateServerIndex); originalTransactionId, isTestPurchase, duplicateServerIndex);
#else #else
Q_UNUSED(userCountryCode); Q_UNUSED(userCountryCode);
Q_UNUSED(serviceType); Q_UNUSED(serviceType);
Q_UNUSED(serviceProtocol); Q_UNUSED(serviceProtocol);
Q_UNUSED(productId); Q_UNUSED(productId);
Q_UNUSED(serverConfig);
return ErrorCode::ApiPurchaseError; return ErrorCode::ApiPurchaseError;
#endif #endif
} }
@@ -956,10 +814,9 @@ SubscriptionController::AppStoreRestoreResult SubscriptionController::processApp
<< "originalTransactionId =" << originalTransactionId << "productId =" << transactionProductId; << "originalTransactionId =" << originalTransactionId << "productId =" << transactionProductId;
ProtocolData protocolData = generateProtocolData(serviceProtocol); ProtocolData protocolData = generateProtocolData(serviceProtocol);
ServerConfig serverConfig;
int currentDuplicateServerIndex = -1; int currentDuplicateServerIndex = -1;
ErrorCode errorCode = importServiceFromAppStore(userCountryCode, serviceType, serviceProtocol, protocolData, ErrorCode errorCode = importServiceFromAppStore(userCountryCode, serviceType, serviceProtocol, protocolData,
originalTransactionId, isTestPurchase, serverConfig, originalTransactionId, isTestPurchase,
&currentDuplicateServerIndex); &currentDuplicateServerIndex);
if (errorCode == ErrorCode::ApiConfigAlreadyAdded) { if (errorCode == ErrorCode::ApiConfigAlreadyAdded) {
@@ -991,16 +848,10 @@ SubscriptionController::AppStoreRestoreResult SubscriptionController::processApp
#endif #endif
} }
ErrorCode SubscriptionController::getAccountInfo(int serverIndex, QJsonObject &accountInfo) ErrorCode SubscriptionController::getAccountInfo(const QString &serverId, QJsonObject &accountInfo)
{ {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (!apiV2.has_value()) {
if (!serverConfigModel.isApiV2()) {
return ErrorCode::InternalError;
}
const ApiV2ServerConfig* apiV2 = serverConfigModel.as<ApiV2ServerConfig>();
if (!apiV2) {
return ErrorCode::InternalError; return ErrorCode::InternalError;
} }
bool isTestPurchase = apiV2->apiConfig.isTestPurchase; bool isTestPurchase = apiV2->apiConfig.isTestPurchase;
@@ -1030,20 +881,13 @@ ErrorCode SubscriptionController::getAccountInfo(int serverIndex, QJsonObject &a
return ErrorCode::NoError; return ErrorCode::NoError;
} }
QFuture<QPair<ErrorCode, QString>> SubscriptionController::getRenewalLink(int serverIndex) QFuture<QPair<ErrorCode, QString>> SubscriptionController::getRenewalLink(const QString &serverId)
{ {
auto promise = QSharedPointer<QPromise<QPair<ErrorCode, QString>>>::create(); auto promise = QSharedPointer<QPromise<QPair<ErrorCode, QString>>>::create();
promise->start(); promise->start();
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); auto apiV2 = m_serversRepository->apiV2Config(serverId);
if (!serverConfigModel.isApiV2()) { if (!apiV2.has_value()) {
promise->addResult(qMakePair(ErrorCode::InternalError, QString()));
promise->finish();
return promise->future();
}
const ApiV2ServerConfig *apiV2 = serverConfigModel.as<ApiV2ServerConfig>();
if (!apiV2) {
promise->addResult(qMakePair(ErrorCode::InternalError, QString())); promise->addResult(qMakePair(ErrorCode::InternalError, QString()));
promise->finish(); promise->finish();
return promise->future(); return promise->future();
@@ -12,7 +12,6 @@
#include "core/utils/commonStructs.h" #include "core/utils/commonStructs.h"
#include "core/repositories/secureServersRepository.h" #include "core/repositories/secureServersRepository.h"
#include "core/repositories/secureAppSettingsRepository.h" #include "core/repositories/secureAppSettingsRepository.h"
#include "core/models/serverConfig.h"
class ServersController; class ServersController;
@@ -48,44 +47,38 @@ public:
ProtocolData generateProtocolData(const QString &protocol); ProtocolData generateProtocolData(const QString &protocol);
void appendProtocolDataToApiPayload(const QString &protocol, const ProtocolData &protocolData, QJsonObject &apiPayload); void appendProtocolDataToApiPayload(const QString &protocol, const ProtocolData &protocolData, QJsonObject &apiPayload);
ErrorCode fillServerConfig(const QJsonObject &serverConfigJson, ServerConfig &serverConfig);
ErrorCode importServiceFromGateway(const QString &userCountryCode, const QString &serviceType, ErrorCode importServiceFromGateway(const QString &userCountryCode, const QString &serviceType,
const QString &serviceProtocol, const ProtocolData &protocolData, const QString &serviceProtocol, const ProtocolData &protocolData);
ServerConfig &serverConfig);
ErrorCode importTrialFromGateway(const QString &userCountryCode, const QString &serviceType, ErrorCode importTrialFromGateway(const QString &userCountryCode, const QString &serviceType,
const QString &serviceProtocol, const QString &email, const QString &serviceProtocol, const QString &email);
ServerConfig &serverConfig);
ErrorCode importServiceFromAppStore(const QString &userCountryCode, const QString &serviceType, ErrorCode importServiceFromAppStore(const QString &userCountryCode, const QString &serviceType,
const QString &serviceProtocol, const ProtocolData &protocolData, const QString &serviceProtocol, const ProtocolData &protocolData,
const QString &transactionId, bool isTestPurchase, const QString &transactionId, bool isTestPurchase,
ServerConfig &serverConfig,
int *duplicateServerIndex = nullptr); int *duplicateServerIndex = nullptr);
ErrorCode updateServiceFromGateway(int serverIndex, const QString &newCountryCode, bool isConnectEvent); ErrorCode updateServiceFromGateway(const QString &serverId, const QString &newCountryCode, bool isConnectEvent);
ErrorCode deactivateDevice(int serverIndex); ErrorCode deactivateDevice(const QString &serverId);
ErrorCode deactivateExternalDevice(int serverIndex, const QString &uuid, const QString &serverCountryCode); ErrorCode deactivateExternalDevice(const QString &serverId, const QString &uuid, const QString &serverCountryCode);
ErrorCode exportNativeConfig(int serverIndex, const QString &serverCountryCode, QString &nativeConfig); ErrorCode exportNativeConfig(const QString &serverId, const QString &serverCountryCode, QString &nativeConfig);
ErrorCode revokeNativeConfig(int serverIndex, const QString &serverCountryCode); ErrorCode revokeNativeConfig(const QString &serverId, const QString &serverCountryCode);
ErrorCode updateServiceFromTelegram(int serverIndex); ErrorCode prepareVpnKeyExport(const QString &serverId, QString &vpnKey);
ErrorCode prepareVpnKeyExport(int serverIndex, QString &vpnKey); ErrorCode validateAndUpdateConfig(const QString &serverId, bool hasInstalledContainers);
ErrorCode validateAndUpdateConfig(int serverIndex, bool hasInstalledContainers); void removeApiConfig(const QString &serverId);
void removeApiConfig(int serverIndex); void setCurrentProtocol(const QString &serverId, const QString &protocolName);
bool isVlessProtocol(const QString &serverId) const;
void setCurrentProtocol(int serverIndex, const QString &protocolName); ErrorCode getAccountInfo(const QString &serverId, QJsonObject &accountInfo);
bool isVlessProtocol(int serverIndex) const; QFuture<QPair<ErrorCode, QString>> getRenewalLink(const QString &serverId);
ErrorCode getAccountInfo(int serverIndex, QJsonObject &accountInfo);
QFuture<QPair<ErrorCode, QString>> getRenewalLink(int serverIndex);
struct AppStoreRestoreResult struct AppStoreRestoreResult
{ {
@@ -98,7 +91,6 @@ public:
ErrorCode processAppStorePurchase(const QString &userCountryCode, const QString &serviceType, ErrorCode processAppStorePurchase(const QString &userCountryCode, const QString &serviceType,
const QString &serviceProtocol, const QString &productId, const QString &serviceProtocol, const QString &productId,
ServerConfig &serverConfig,
int *duplicateServerIndex = nullptr); int *duplicateServerIndex = nullptr);
AppStoreRestoreResult processAppStoreRestore(const QString &userCountryCode, const QString &serviceType, AppStoreRestoreResult processAppStoreRestore(const QString &userCountryCode, const QString &serviceType,
@@ -106,7 +98,7 @@ public:
private: private:
ErrorCode executeRequest(const QString &endpoint, const QJsonObject &apiPayload, QByteArray &responseBody, bool isTestPurchase = false); ErrorCode executeRequest(const QString &endpoint, const QJsonObject &apiPayload, QByteArray &responseBody, bool isTestPurchase = false);
bool isApiKeyExpired(int serverIndex) const; bool isApiKeyExpired(const QString &serverId) const;
ErrorCode extractServerConfigJsonFromResponse(const QByteArray &apiResponseBody, const QString &protocol, ErrorCode extractServerConfigJsonFromResponse(const QByteArray &apiResponseBody, const QString &protocol,
const ProtocolData &protocolData, QJsonObject &serverConfigJson); const ProtocolData &protocolData, QJsonObject &serverConfigJson);
@@ -9,11 +9,11 @@
#include "core/utils/constants/protocolConstants.h" #include "core/utils/constants/protocolConstants.h"
#include "core/utils/utilities.h" #include "core/utils/utilities.h"
#include "core/utils/networkUtilities.h" #include "core/utils/networkUtilities.h"
#include "core/utils/serverConfigUtils.h"
#include "version.h" #include "version.h"
#include "core/utils/containerEnum.h" #include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h" #include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h" #include "core/utils/protocolEnum.h"
#include "core/models/serverConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/models/protocolConfig.h" #include "core/models/protocolConfig.h"
@@ -51,7 +51,7 @@ void ConnectionController::setConnectionState(Vpn::ConnectionState state)
} }
} }
ErrorCode ConnectionController::prepareConnection(int serverIndex, ErrorCode ConnectionController::prepareConnection(const QString &serverId,
QJsonObject& vpnConfiguration, QJsonObject& vpnConfiguration,
DockerContainer& container) DockerContainer& container)
{ {
@@ -59,35 +59,98 @@ ErrorCode ConnectionController::prepareConnection(int serverIndex,
return ErrorCode::AmneziaServiceNotRunning; return ErrorCode::AmneziaServiceNotRunning;
} }
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); ContainerConfig containerConfigModel;
container = serverConfigModel.defaultContainer(); QPair<QString, QString> dns;
QString hostName;
QString description;
int configVersion = 0;
bool isApiConfig = false;
const auto kind = m_serversRepository->serverKind(serverId);
switch (kind) {
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
const auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
if (!cfg.has_value()) return ErrorCode::InternalError;
container = cfg->defaultContainer;
containerConfigModel = cfg->containerConfig(container);
dns = { cfg->dns1, cfg->dns2 };
hostName = cfg->hostName;
description = cfg->description;
break;
}
case serverConfigUtils::ConfigType::SelfHostedUser: {
const auto cfg = m_serversRepository->selfHostedUserConfig(serverId);
if (!cfg.has_value()) return ErrorCode::InternalError;
container = cfg->defaultContainer;
containerConfigModel = cfg->containerConfig(container);
dns = { cfg->dns1, cfg->dns2 };
hostName = cfg->hostName;
description = cfg->description;
break;
}
case serverConfigUtils::ConfigType::Native: {
const auto cfg = m_serversRepository->nativeConfig(serverId);
if (!cfg.has_value()) return ErrorCode::InternalError;
container = cfg->defaultContainer;
containerConfigModel = cfg->containerConfig(container);
dns = { cfg->dns1, cfg->dns2 };
hostName = cfg->hostName;
description = cfg->description;
break;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
case serverConfigUtils::ConfigType::AmneziaFreeV3:
case serverConfigUtils::ConfigType::ExternalPremium: {
const auto cfg = m_serversRepository->apiV2Config(serverId);
if (!cfg.has_value()) return ErrorCode::InternalError;
container = cfg->defaultContainer;
containerConfigModel = cfg->containerConfig(container);
dns = { cfg->dns1, cfg->dns2 };
hostName = cfg->hostName;
description = cfg->description;
configVersion = serverConfigUtils::ConfigSource::AmneziaGateway;
isApiConfig = true;
break;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
case serverConfigUtils::ConfigType::AmneziaFreeV2:
return ErrorCode::InternalError;
case serverConfigUtils::ConfigType::Invalid:
default:
return ErrorCode::InternalError;
}
if (!isContainerSupported(container)) { if (!isContainerSupported(container)) {
return ErrorCode::NotSupportedOnThisPlatform; return ErrorCode::NotSupportedOnThisPlatform;
} }
if (dns.first.isEmpty() || !NetworkUtilities::checkIPv4Format(dns.first)) {
if (m_appSettingsRepository->useAmneziaDns()) {
dns.first = protocols::dns::amneziaDnsIp;
} else {
dns.first = m_appSettingsRepository->primaryDns();
}
}
if (dns.second.isEmpty() || !NetworkUtilities::checkIPv4Format(dns.second)) {
dns.second = m_appSettingsRepository->secondaryDns();
}
ContainerConfig containerConfigModel = m_serversRepository->containerConfig(serverIndex, container); vpnConfiguration = createConnectionConfiguration(dns, isApiConfig, hostName, description, configVersion,
containerConfigModel, container);
auto dns = serverConfigModel.getDnsPair(m_appSettingsRepository->useAmneziaDns(),
m_appSettingsRepository->primaryDns(),
m_appSettingsRepository->secondaryDns());
vpnConfiguration = createConnectionConfiguration(dns, serverConfigModel, containerConfigModel, container);
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode ConnectionController::openConnection(int serverIndex) ErrorCode ConnectionController::openConnection(const QString &serverId)
{ {
QJsonObject vpnConfiguration; QJsonObject vpnConfiguration;
DockerContainer container; DockerContainer container;
ErrorCode errorCode = prepareConnection(serverIndex, vpnConfiguration, container); ErrorCode errorCode = prepareConnection(serverId, vpnConfiguration, container);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }
emit openConnectionRequested(serverIndex, container, vpnConfiguration); emit openConnectionRequested(serverId, container, vpnConfiguration);
return ErrorCode::NoError; return ErrorCode::NoError;
} }
@@ -120,7 +183,10 @@ ErrorCode ConnectionController::lastConnectionError() const
} }
QJsonObject ConnectionController::createConnectionConfiguration(const QPair<QString, QString> &dns, QJsonObject ConnectionController::createConnectionConfiguration(const QPair<QString, QString> &dns,
const ServerConfig &serverConfig, bool isApiConfig,
const QString &hostName,
const QString &description,
int configVersion,
const ContainerConfig &containerConfig, const ContainerConfig &containerConfig,
DockerContainer container) DockerContainer container)
{ {
@@ -134,7 +200,7 @@ QJsonObject ConnectionController::createConnectionConfiguration(const QPair<QStr
ConnectionSettings connectionSettings = { ConnectionSettings connectionSettings = {
{ dns.first, dns.second }, { dns.first, dns.second },
serverConfig.isApiConfig(), isApiConfig,
{ {
m_appSettingsRepository->isSitesSplitTunnelingEnabled(), m_appSettingsRepository->isSitesSplitTunnelingEnabled(),
m_appSettingsRepository->routeMode() m_appSettingsRepository->routeMode()
@@ -160,10 +226,9 @@ QJsonObject ConnectionController::createConnectionConfiguration(const QPair<QStr
vpnConfiguration[configKey::dns1] = dns.first; vpnConfiguration[configKey::dns1] = dns.first;
vpnConfiguration[configKey::dns2] = dns.second; vpnConfiguration[configKey::dns2] = dns.second;
vpnConfiguration[configKey::hostName] = serverConfig.hostName(); vpnConfiguration[configKey::hostName] = hostName;
vpnConfiguration[configKey::description] = serverConfig.description(); vpnConfiguration[configKey::description] = description;
vpnConfiguration[configKey::configVersion] = configVersion;
vpnConfiguration[configKey::configVersion] = serverConfig.configVersion();
return vpnConfiguration; return vpnConfiguration;
} }
@@ -30,11 +30,11 @@ public:
QObject* parent = nullptr); QObject* parent = nullptr);
~ConnectionController() = default; ~ConnectionController() = default;
ErrorCode prepareConnection(int serverIndex, ErrorCode prepareConnection(const QString &serverId,
QJsonObject& vpnConfiguration, QJsonObject& vpnConfiguration,
DockerContainer& container); DockerContainer& container);
ErrorCode openConnection(int serverIndex); ErrorCode openConnection(const QString &serverId);
void closeConnection(); void closeConnection();
@@ -50,7 +50,10 @@ public:
void setConnectionState(Vpn::ConnectionState state); void setConnectionState(Vpn::ConnectionState state);
QJsonObject createConnectionConfiguration(const QPair<QString, QString> &dns, QJsonObject createConnectionConfiguration(const QPair<QString, QString> &dns,
const ServerConfig &serverConfig, bool isApiConfig,
const QString &hostName,
const QString &description,
int configVersion,
const ContainerConfig &containerConfig, const ContainerConfig &containerConfig,
DockerContainer container); DockerContainer container);
@@ -60,7 +63,7 @@ public:
signals: signals:
void connectionStateChanged(Vpn::ConnectionState state); void connectionStateChanged(Vpn::ConnectionState state);
void openConnectionRequested(int serverIndex, DockerContainer container, const QJsonObject &vpnConfiguration); void openConnectionRequested(const QString &serverId, DockerContainer container, const QJsonObject &vpnConfiguration);
void closeConnectionRequested(); void closeConnectionRequested();
void setConnectionStateRequested(Vpn::ConnectionState state); void setConnectionStateRequested(Vpn::ConnectionState state);
void killSwitchModeChangedRequested(bool enabled); void killSwitchModeChangedRequested(bool enabled);
+12 -5
View File
@@ -8,7 +8,6 @@
#include "core/controllers/selfhosted/installController.h" #include "core/controllers/selfhosted/installController.h"
#include "core/controllers/selfhosted/importController.h" #include "core/controllers/selfhosted/importController.h"
#include "core/controllers/coreSignalHandlers.h" #include "core/controllers/coreSignalHandlers.h"
#include "core/models/serverConfig.h"
#include "logger.h" #include "logger.h"
#include "secureQSettings.h" #include "secureQSettings.h"
@@ -145,7 +144,7 @@ void CoreController::initCoreControllers()
m_allowedDnsController = new AllowedDnsController(m_appSettingsRepository); m_allowedDnsController = new AllowedDnsController(m_appSettingsRepository);
m_servicesCatalogController = new ServicesCatalogController(m_appSettingsRepository); m_servicesCatalogController = new ServicesCatalogController(m_appSettingsRepository);
m_subscriptionController = new SubscriptionController(m_serversRepository, m_appSettingsRepository); m_subscriptionController = new SubscriptionController(m_serversRepository, m_appSettingsRepository);
m_newsController = new NewsController(m_appSettingsRepository, m_serversController); m_newsController = new NewsController(m_appSettingsRepository, m_serversRepository);
m_updateController = new UpdateController(m_appSettingsRepository, this); m_updateController = new UpdateController(m_appSettingsRepository, this);
m_installController = new InstallController(m_serversRepository, m_appSettingsRepository, this); m_installController = new InstallController(m_serversRepository, m_appSettingsRepository, this);
@@ -165,7 +164,7 @@ void CoreController::initControllers()
setQmlContextProperty("FocusController", m_focusController); setQmlContextProperty("FocusController", m_focusController);
} }
m_installUiController = new InstallUiController(m_installController, m_serversController, m_settingsController, m_protocolsModel, m_usersController, m_installUiController = new InstallUiController(m_installController, m_serversController, m_settingsController, m_protocolsModel, m_usersController,
m_awgConfigModel, m_wireGuardConfigModel, m_openVpnConfigModel, m_xrayConfigModel, m_torConfigModel, m_awgConfigModel, m_wireGuardConfigModel, m_openVpnConfigModel, m_xrayConfigModel, m_torConfigModel,
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
m_ikev2ConfigModel, m_ikev2ConfigModel,
@@ -262,9 +261,12 @@ void CoreController::initSignalHandlers()
{ {
m_signalHandlers = new CoreSignalHandlers(this, this); m_signalHandlers = new CoreSignalHandlers(this, this);
m_signalHandlers->initAllHandlers(); m_signalHandlers->initAllHandlers();
// Trigger initial update after handlers are connected // Trigger initial update after handlers are connected
m_serversUiController->updateModel(); m_serversUiController->updateModel();
if (m_serversUiController->hasServersFromGatewayApi()) {
m_apiNewsUiController->fetchNews(false);
}
} }
void CoreController::updateTranslator(const QLocale &locale) void CoreController::updateTranslator(const QLocale &locale)
@@ -322,11 +324,16 @@ PageController* CoreController::pageController() const
void CoreController::openConnectionByIndex(int serverIndex) void CoreController::openConnectionByIndex(int serverIndex)
{ {
const QString serverId =
m_serversUiController ? m_serversUiController->getServerId(serverIndex) : QString();
if (serverId.isEmpty()) {
return;
}
if (m_serversModel) { if (m_serversModel) {
m_serversModel->setProcessedServerIndex(serverIndex); m_serversModel->setProcessedServerIndex(serverIndex);
} }
if (m_serversController) { if (m_serversController) {
m_serversController->setDefaultServerIndex(serverIndex); m_serversController->setDefaultServer(serverId);
} }
m_connectionUiController->toggleConnection(); m_connectionUiController->toggleConnection();
} }
-2
View File
@@ -84,7 +84,6 @@ class TestDefaultServerChange;
class TestServerEdgeCases; class TestServerEdgeCases;
class TestSignalOrder; class TestSignalOrder;
class TestServersModelSync; class TestServersModelSync;
class TestGatewayStacks;
class TestComplexOperations; class TestComplexOperations;
class TestSettingsSignals; class TestSettingsSignals;
class TestUiServersModelAndController; class TestUiServersModelAndController;
@@ -101,7 +100,6 @@ class CoreController : public QObject
friend class TestServerEdgeCases; friend class TestServerEdgeCases;
friend class TestSignalOrder; friend class TestSignalOrder;
friend class TestServersModelSync; friend class TestServersModelSync;
friend class TestGatewayStacks;
friend class TestComplexOperations; friend class TestComplexOperations;
friend class TestSettingsSignals; friend class TestSettingsSignals;
friend class TestUiServersModelAndController; friend class TestUiServersModelAndController;
+73 -57
View File
@@ -7,6 +7,7 @@
#include "core/utils/routeModes.h" #include "core/utils/routeModes.h"
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/repositories/secureServersRepository.h" #include "core/repositories/secureServersRepository.h"
#include "core/utils/serverConfigUtils.h"
#include "core/repositories/secureAppSettingsRepository.h" #include "core/repositories/secureAppSettingsRepository.h"
#include "vpnConnection.h" #include "vpnConnection.h"
#include "ui/controllers/qml/pageController.h" #include "ui/controllers/qml/pageController.h"
@@ -65,7 +66,6 @@ void CoreSignalHandlers::initAllHandlers()
initImportControllerHandler(); initImportControllerHandler();
initApiCountryModelUpdateHandler(); initApiCountryModelUpdateHandler();
initSubscriptionRefreshHandler(); initSubscriptionRefreshHandler();
initContainerModelUpdateHandler();
initAdminConfigRevokedHandler(); initAdminConfigRevokedHandler();
initPassphraseRequestHandler(); initPassphraseRequestHandler();
initTranslationsUpdatedHandler(); initTranslationsUpdatedHandler();
@@ -78,6 +78,7 @@ void CoreSignalHandlers::initAllHandlers()
initAllowedDnsModelUpdateHandler(); initAllowedDnsModelUpdateHandler();
initAppSplitTunnelingModelUpdateHandler(); initAppSplitTunnelingModelUpdateHandler();
initPrepareConfigHandler(); initPrepareConfigHandler();
initUnsupportedConnectDrawerHandler();
initStrictKillSwitchHandler(); initStrictKillSwitchHandler();
initAndroidSettingsHandler(); initAndroidSettingsHandler();
initAndroidConnectionHandler(); initAndroidConnectionHandler();
@@ -124,11 +125,9 @@ void CoreSignalHandlers::initInstallControllerHandler()
{ {
connect(m_coreController->m_installController, &InstallController::serverIsBusy, m_coreController->m_installUiController, &InstallUiController::serverIsBusy); connect(m_coreController->m_installController, &InstallController::serverIsBusy, m_coreController->m_installUiController, &InstallUiController::serverIsBusy);
connect(m_coreController->m_installUiController, &InstallUiController::cancelInstallation, m_coreController->m_installController, &InstallController::cancelInstallation); connect(m_coreController->m_installUiController, &InstallUiController::cancelInstallation, m_coreController->m_installController, &InstallController::cancelInstallation);
connect(m_coreController->m_installUiController, &InstallUiController::currentContainerUpdated, m_coreController->m_connectionUiController,
&ConnectionUiController::onCurrentContainerUpdated);
connect(m_coreController->m_serversUiController, &ServersUiController::processedServerIndexChanged, connect(m_coreController->m_serversUiController, &ServersUiController::processedServerIndexChanged,
m_coreController->m_installUiController, [this](int index) { m_coreController->m_installUiController, [this](int serverIndex) {
if (index >= 0) { if (serverIndex >= 0) {
m_coreController->m_installUiController->clearProcessedServerCredentials(); m_coreController->m_installUiController->clearProcessedServerCredentials();
} }
}); });
@@ -137,20 +136,20 @@ void CoreSignalHandlers::initInstallControllerHandler()
void CoreSignalHandlers::initExportControllerHandler() void CoreSignalHandlers::initExportControllerHandler()
{ {
connect(m_coreController->m_exportController, &ExportController::appendClientRequested, this, connect(m_coreController->m_exportController, &ExportController::appendClientRequested, this,
[this](int serverIndex, const QString &clientId, const QString &clientName, DockerContainer container) { [this](const QString &serverId, const QString &clientId, const QString &clientName, DockerContainer container) {
m_coreController->m_usersController->appendClient(serverIndex, clientId, clientName, container); m_coreController->m_usersController->appendClient(serverId, clientId, clientName, container);
}); });
connect(m_coreController->m_exportController, &ExportController::updateClientsRequested, this, connect(m_coreController->m_exportController, &ExportController::updateClientsRequested, this,
[this](int serverIndex, DockerContainer container) { [this](const QString &serverId, DockerContainer container) {
m_coreController->m_usersController->updateClients(serverIndex, container); m_coreController->m_usersController->updateClients(serverId, container);
}); });
connect(m_coreController->m_exportController, &ExportController::revokeClientRequested, this, connect(m_coreController->m_exportController, &ExportController::revokeClientRequested, this,
[this](int serverIndex, int row, DockerContainer container) { [this](const QString &serverId, int row, DockerContainer container) {
m_coreController->m_usersController->revokeClient(serverIndex, row, container); m_coreController->m_usersController->revokeClient(serverId, row, container);
}); });
connect(m_coreController->m_exportController, &ExportController::renameClientRequested, this, connect(m_coreController->m_exportController, &ExportController::renameClientRequested, this,
[this](int serverIndex, int row, const QString &clientName, DockerContainer container) { [this](const QString &serverId, int row, const QString &clientName, DockerContainer container) {
m_coreController->m_usersController->renameClient(serverIndex, row, clientName, container); m_coreController->m_usersController->renameClient(serverId, row, clientName, container);
}); });
} }
@@ -159,9 +158,12 @@ void CoreSignalHandlers::initImportControllerHandler()
connect(m_coreController->m_importCoreController, &ImportController::importFinished, this, [this]() { connect(m_coreController->m_importCoreController, &ImportController::importFinished, this, [this]() {
if (!m_coreController->m_connectionController->isConnected()) { if (!m_coreController->m_connectionController->isConnected()) {
int newServerIndex = m_coreController->m_serversController->getServersCount() - 1; int newServerIndex = m_coreController->m_serversController->getServersCount() - 1;
m_coreController->m_serversController->setDefaultServerIndex(newServerIndex); const QString serverId = m_coreController->m_serversController->getServerId(newServerIndex);
if (!serverId.isEmpty()) {
m_coreController->m_serversController->setDefaultServer(serverId);
}
if (m_coreController->m_serversUiController) { if (m_coreController->m_serversUiController) {
m_coreController->m_serversUiController->setProcessedServerIndex(newServerIndex); m_coreController->m_serversUiController->setProcessedServerId(serverId);
} }
} }
}); });
@@ -170,21 +172,18 @@ void CoreSignalHandlers::initImportControllerHandler()
void CoreSignalHandlers::initApiCountryModelUpdateHandler() void CoreSignalHandlers::initApiCountryModelUpdateHandler()
{ {
connect(m_coreController->m_serversUiController, &ServersUiController::updateApiCountryModel, this, [this]() { connect(m_coreController->m_serversUiController, &ServersUiController::updateApiCountryModel, this, [this]() {
int processedIndex = m_coreController->m_serversUiController->getProcessedServerIndex(); const QString processedServerId = m_coreController->m_serversUiController->getProcessedServerId();
if (processedIndex < 0 || processedIndex >= m_coreController->m_serversRepository->serversCount()) { if (processedServerId.isEmpty()) {
return; return;
} }
ServerConfig server = m_coreController->m_serversRepository->server(processedIndex);
QJsonArray availableCountries; QJsonArray availableCountries;
QString serverCountryCode; QString serverCountryCode;
if (server.isApiV2()) { const auto apiV2 = m_coreController->m_serversRepository->apiV2Config(processedServerId);
const ApiV2ServerConfig* apiV2 = server.as<ApiV2ServerConfig>(); if (apiV2.has_value()) {
if (apiV2) { availableCountries = apiV2->apiConfig.availableCountries;
availableCountries = apiV2->apiConfig.availableCountries; serverCountryCode = apiV2->apiConfig.serverCountryCode;
serverCountryCode = apiV2->apiConfig.serverCountryCode;
}
} }
m_coreController->m_apiCountryModel->updateModel(availableCountries, serverCountryCode); m_coreController->m_apiCountryModel->updateModel(availableCountries, serverCountryCode);
@@ -194,18 +193,9 @@ void CoreSignalHandlers::initApiCountryModelUpdateHandler()
void CoreSignalHandlers::initSubscriptionRefreshHandler() void CoreSignalHandlers::initSubscriptionRefreshHandler()
{ {
connect(m_coreController->m_subscriptionUiController, &SubscriptionUiController::subscriptionRefreshNeeded, this, [this]() { connect(m_coreController->m_subscriptionUiController, &SubscriptionUiController::subscriptionRefreshNeeded, this, [this]() {
const int defaultServerIndex = m_coreController->m_serversController->getDefaultServerIndex(); const QString defaultServerId = m_coreController->m_serversController->getDefaultServerId();
if (defaultServerIndex >= 0) { if (!defaultServerId.isEmpty()) {
m_coreController->m_subscriptionUiController->getAccountInfo(defaultServerIndex, false); m_coreController->m_subscriptionUiController->getAccountInfo(defaultServerId, false);
}
});
}
void CoreSignalHandlers::initContainerModelUpdateHandler()
{
connect(m_coreController->m_serversController, &ServersController::gatewayStacksExpanded, this, [this]() {
if (m_coreController->m_serversUiController->hasServersFromGatewayApi()) {
m_coreController->m_apiNewsUiController->fetchNews(false);
} }
}); });
} }
@@ -213,17 +203,17 @@ void CoreSignalHandlers::initContainerModelUpdateHandler()
void CoreSignalHandlers::initAdminConfigRevokedHandler() void CoreSignalHandlers::initAdminConfigRevokedHandler()
{ {
connect(m_coreController->m_installController, &InstallController::clientRevocationRequested, this, connect(m_coreController->m_installController, &InstallController::clientRevocationRequested, this,
[this](int serverIndex, const ContainerConfig &containerConfig, DockerContainer container) { [this](const QString &serverId, const ContainerConfig &containerConfig, DockerContainer container) {
m_coreController->m_usersController->revokeClient(serverIndex, containerConfig, container); m_coreController->m_usersController->revokeClient(serverId, containerConfig, container);
}); });
connect(m_coreController->m_installController, &InstallController::clientAppendRequested, this, connect(m_coreController->m_installController, &InstallController::clientAppendRequested, this,
[this](int serverIndex, const QString &clientId, const QString &clientName, DockerContainer container) { [this](const QString &serverId, const QString &clientId, const QString &clientName, DockerContainer container) {
m_coreController->m_usersController->appendClient(serverIndex, clientId, clientName, container); m_coreController->m_usersController->appendClient(serverId, clientId, clientName, container);
}); });
connect(m_coreController->m_usersController, &UsersController::adminConfigRevoked, m_coreController->m_serversController, connect(m_coreController->m_usersController, &UsersController::adminConfigRevoked, m_coreController->m_installController,
&ServersController::clearCachedProfile); &InstallController::clearCachedProfile);
} }
void CoreSignalHandlers::initPassphraseRequestHandler() void CoreSignalHandlers::initPassphraseRequestHandler()
@@ -251,7 +241,8 @@ void CoreSignalHandlers::initLanguageHandler()
void CoreSignalHandlers::initAutoConnectHandler() void CoreSignalHandlers::initAutoConnectHandler()
{ {
if (m_coreController->m_settingsUiController->isAutoConnectEnabled() && m_coreController->m_serversController->getDefaultServerIndex() >= 0) { if (m_coreController->m_settingsUiController->isAutoConnectEnabled()
&& !m_coreController->m_serversController->getDefaultServerId().isEmpty()) {
QTimer::singleShot(1000, this, [this]() { m_coreController->m_connectionUiController->openConnection(); }); QTimer::singleShot(1000, this, [this]() { m_coreController->m_connectionUiController->openConnection(); });
} }
} }
@@ -271,16 +262,20 @@ void CoreSignalHandlers::initServersModelUpdateHandler()
m_coreController->m_serversUiController, &ServersUiController::updateModel); m_coreController->m_serversUiController, &ServersUiController::updateModel);
connect(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged, connect(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged,
m_coreController->m_serversUiController, &ServersUiController::onDefaultServerChanged); m_coreController->m_serversUiController, &ServersUiController::onDefaultServerChanged);
connect(m_coreController->m_serversRepository, &SecureServersRepository::serverAdded, connect(m_coreController->m_serversRepository, &SecureServersRepository::serverAdded, this,
m_coreController->m_serversController, &ServersController::recomputeGatewayStacks); [this](const QString &serverId) {
connect(m_coreController->m_serversRepository, &SecureServersRepository::serverEdited, if (m_coreController->m_serversRepository->apiV2Config(serverId).has_value()) {
m_coreController->m_serversController, &ServersController::recomputeGatewayStacks); m_coreController->m_apiNewsUiController->fetchNews(false);
connect(m_coreController->m_serversRepository, &SecureServersRepository::serverRemoved, }
m_coreController->m_serversController, &ServersController::recomputeGatewayStacks); });
connect(m_coreController->m_settingsUiController, &SettingsUiController::restoreBackupFinished, connect(m_coreController->m_settingsUiController, &SettingsUiController::restoreBackupFinished, this, [this]() {
m_coreController->m_serversUiController, &ServersUiController::updateModel); m_coreController->m_serversUiController->updateModel();
if (m_coreController->m_serversUiController->hasServersFromGatewayApi()) {
m_coreController->m_apiNewsUiController->fetchNews(false);
}
});
} }
void CoreSignalHandlers::initClientManagementModelUpdateHandler() void CoreSignalHandlers::initClientManagementModelUpdateHandler()
@@ -315,7 +310,19 @@ void CoreSignalHandlers::initPrepareConfigHandler()
connect(m_coreController->m_connectionUiController, &ConnectionUiController::prepareConfig, this, [this]() { connect(m_coreController->m_connectionUiController, &ConnectionUiController::prepareConfig, this, [this]() {
m_coreController->m_connectionController->setConnectionState(Vpn::ConnectionState::Preparing); m_coreController->m_connectionController->setConnectionState(Vpn::ConnectionState::Preparing);
m_coreController->m_subscriptionUiController->validateConfig(); const QString serverId = m_coreController->m_serversController->getDefaultServerId();
if (serverId.isEmpty()) {
m_coreController->m_connectionController->setConnectionState(Vpn::ConnectionState::Disconnected);
return;
}
const serverConfigUtils::ConfigType kind = m_coreController->m_serversRepository->serverKind(serverId);
if (serverConfigUtils::isApiV2Subscription(kind) || serverConfigUtils::isLegacyApiSubscription(kind)) {
m_coreController->m_subscriptionUiController->validateConfig();
} else {
m_coreController->m_installUiController->validateConfig();
}
}); });
connect(m_coreController->m_subscriptionUiController, &SubscriptionUiController::configValidated, this, [this](bool isValid) { connect(m_coreController->m_subscriptionUiController, &SubscriptionUiController::configValidated, this, [this](bool isValid) {
@@ -324,7 +331,7 @@ void CoreSignalHandlers::initPrepareConfigHandler()
return; return;
} }
m_coreController->m_installUiController->validateConfig(); m_coreController->m_connectionUiController->openConnection();
}); });
connect(m_coreController->m_installUiController, &InstallUiController::configValidated, this, [this](bool isValid) { connect(m_coreController->m_installUiController, &InstallUiController::configValidated, this, [this](bool isValid) {
@@ -337,6 +344,12 @@ void CoreSignalHandlers::initPrepareConfigHandler()
}); });
} }
void CoreSignalHandlers::initUnsupportedConnectDrawerHandler()
{
connect(m_coreController->m_subscriptionUiController, &SubscriptionUiController::unsupportedConnectDrawerRequested,
m_coreController->m_pageController, &PageController::unsupportedConnectDrawerRequested);
}
void CoreSignalHandlers::initStrictKillSwitchHandler() void CoreSignalHandlers::initStrictKillSwitchHandler()
{ {
connect(m_coreController->m_settingsUiController, &SettingsUiController::strictKillSwitchEnabledChanged, m_coreController->m_connectionController, connect(m_coreController->m_settingsUiController, &SettingsUiController::strictKillSwitchEnabledChanged, m_coreController->m_connectionController,
@@ -348,7 +361,10 @@ void CoreSignalHandlers::initAndroidSettingsHandler()
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
connect(m_coreController->m_appSettingsRepository, &SecureAppSettingsRepository::saveLogsChanged, AndroidController::instance(), &AndroidController::setSaveLogs); connect(m_coreController->m_appSettingsRepository, &SecureAppSettingsRepository::saveLogsChanged, AndroidController::instance(), &AndroidController::setSaveLogs);
connect(m_coreController->m_appSettingsRepository, &SecureAppSettingsRepository::screenshotsEnabledChanged, AndroidController::instance(), &AndroidController::setScreenshotsEnabled); connect(m_coreController->m_appSettingsRepository, &SecureAppSettingsRepository::screenshotsEnabledChanged, AndroidController::instance(), &AndroidController::setScreenshotsEnabled);
connect(m_coreController->m_serversRepository, &SecureServersRepository::serverRemoved, AndroidController::instance(), &AndroidController::resetLastServer); connect(m_coreController->m_serversRepository, &SecureServersRepository::serverRemoved, this,
[](const QString &/*serverId*/, int removedIndex) {
AndroidController::instance()->resetLastServer(removedIndex);
});
connect(m_coreController->m_appSettingsRepository, &SecureAppSettingsRepository::settingsCleared, []() { AndroidController::instance()->resetLastServer(-1); }); connect(m_coreController->m_appSettingsRepository, &SecureAppSettingsRepository::settingsCleared, []() { AndroidController::instance()->resetLastServer(-1); });
#endif #endif
} }
+1 -1
View File
@@ -21,7 +21,6 @@ private:
void initImportControllerHandler(); void initImportControllerHandler();
void initApiCountryModelUpdateHandler(); void initApiCountryModelUpdateHandler();
void initSubscriptionRefreshHandler(); void initSubscriptionRefreshHandler();
void initContainerModelUpdateHandler();
void initAdminConfigRevokedHandler(); void initAdminConfigRevokedHandler();
void initPassphraseRequestHandler(); void initPassphraseRequestHandler();
void initTranslationsUpdatedHandler(); void initTranslationsUpdatedHandler();
@@ -34,6 +33,7 @@ private:
void initAllowedDnsModelUpdateHandler(); void initAllowedDnsModelUpdateHandler();
void initAppSplitTunnelingModelUpdateHandler(); void initAppSplitTunnelingModelUpdateHandler();
void initPrepareConfigHandler(); void initPrepareConfigHandler();
void initUnsupportedConnectDrawerHandler();
void initStrictKillSwitchHandler(); void initStrictKillSwitchHandler();
void initAndroidSettingsHandler(); void initAndroidSettingsHandler();
void initAndroidConnectionHandler(); void initAndroidConnectionHandler();
@@ -239,7 +239,7 @@ QFuture<QPair<ErrorCode, QByteArray>> GatewayController::postAsync(const QString
connect(reply, &QNetworkReply::sslErrors, [sslErrors](const QList<QSslError> &errors) { *sslErrors = errors; }); connect(reply, &QNetworkReply::sslErrors, [sslErrors](const QList<QSslError> &errors) { *sslErrors = errors; });
connect(reply, &QNetworkReply::finished, reply, [promise, sslErrors, encRequestData, endpoint, apiPayload, reply, this]() mutable { connect(reply, &QNetworkReply::finished, this, [promise, sslErrors, encRequestData, endpoint, apiPayload, reply, this]() mutable {
QByteArray encryptedResponseBody = reply->readAll(); QByteArray encryptedResponseBody = reply->readAll();
QString replyErrorString = reply->errorString(); QString replyErrorString = reply->errorString();
auto replyError = reply->error(); auto replyError = reply->error();
@@ -5,14 +5,13 @@
#include "core/configurators/configuratorBase.h" #include "core/configurators/configuratorBase.h"
#include "core/utils/selfhosted/sshSession.h" #include "core/utils/selfhosted/sshSession.h"
#include "core/utils/networkUtilities.h"
#include "core/utils/qrCodeUtils.h" #include "core/utils/qrCodeUtils.h"
#include "core/utils/serialization/serialization.h" #include "core/utils/serialization/serialization.h"
#include "core/utils/protocolEnum.h" #include "core/utils/protocolEnum.h"
#include "core/protocols/protocolUtils.h" #include "core/protocols/protocolUtils.h"
#include "core/utils/constants/configKeys.h" #include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h" #include "core/utils/constants/protocolConstants.h"
#include "core/models/serverConfig.h" #include "core/models/selfhosted/selfHostedAdminServerConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/models/protocolConfig.h" #include "core/models/protocolConfig.h"
@@ -27,18 +26,20 @@ ExportController::ExportController(SecureServersRepository* serversRepository,
{ {
} }
ExportController::ExportResult ExportController::generateFullAccessConfig(int serverIndex) ExportController::ExportResult ExportController::generateFullAccessConfig(const QString &serverId)
{ {
ExportResult result; ExportResult result;
ServerConfig serverConfig = m_serversRepository->server(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
serverConfig.visit([](auto& arg) { if (!adminConfig.has_value()) {
for (auto it = arg.containers.begin(); it != arg.containers.end(); ++it) { result.errorCode = ErrorCode::InternalError;
it.value().protocolConfig.clearClientConfig(); return result;
} }
}); for (auto it = adminConfig->containers.begin(); it != adminConfig->containers.end(); ++it) {
it.value().protocolConfig.clearClientConfig();
}
QJsonObject serverJson = serverConfig.toJson(); QJsonObject serverJson = adminConfig->toJson();
QByteArray compressedConfig = QJsonDocument(serverJson).toJson(); QByteArray compressedConfig = QJsonDocument(serverJson).toJson();
compressedConfig = qCompress(compressedConfig, 8); compressedConfig = qCompress(compressedConfig, 8);
result.config = generateVpnUrl(compressedConfig); result.config = generateVpnUrl(compressedConfig);
@@ -47,13 +48,22 @@ ExportController::ExportResult ExportController::generateFullAccessConfig(int se
return result; return result;
} }
ExportController::ExportResult ExportController::generateConnectionConfig(int serverIndex, int containerIndex, const QString &clientName) ExportController::ExportResult ExportController::generateConnectionConfig(const QString &serverId, int containerIndex, const QString &clientName)
{ {
ExportResult result; ExportResult result;
DockerContainer container = static_cast<DockerContainer>(containerIndex); DockerContainer container = static_cast<DockerContainer>(containerIndex);
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
ContainerConfig containerConfig = m_serversRepository->containerConfig(serverIndex, container); if (!adminConfig.has_value()) {
result.errorCode = ErrorCode::InternalError;
return result;
}
const ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
result.errorCode = ErrorCode::InternalError;
return result;
}
ContainerConfig containerConfig = adminConfig->containerConfig(container);
if (ContainerUtils::containerService(container) != ServiceType::Other) { if (ContainerUtils::containerService(container) != ServiceType::Other) {
SshSession sshSession; SshSession sshSession;
@@ -74,35 +84,25 @@ ExportController::ExportResult ExportController::generateConnectionConfig(int se
QString clientId = newProtocolConfig.clientId(); QString clientId = newProtocolConfig.clientId();
if (!clientId.isEmpty()) { if (!clientId.isEmpty()) {
emit appendClientRequested(serverIndex, clientId, clientName, container); emit appendClientRequested(serverId, clientId, clientName, container);
} }
} }
ServerConfig serverConfig = m_serversRepository->server(serverIndex); const QPair<QString, QString> dns = adminConfig->getDnsPair(m_appSettingsRepository->useAmneziaDns(),
serverConfig.visit([container, containerConfig](auto& arg) { m_appSettingsRepository->primaryDns(),
arg.containers.clear(); m_appSettingsRepository->secondaryDns());
arg.containers[container] = containerConfig;
arg.defaultContainer = container;
});
if (serverConfig.isSelfHosted()) { adminConfig->containers.clear();
SelfHostedServerConfig* selfHosted = serverConfig.as<SelfHostedServerConfig>(); adminConfig->containers[container] = containerConfig;
if (selfHosted) { adminConfig->defaultContainer = container;
selfHosted->userName.reset(); adminConfig->userName.clear();
selfHosted->password.reset(); adminConfig->password.clear();
selfHosted->port.reset(); adminConfig->port = 0;
}
}
auto dns = serverConfig.getDnsPair(m_appSettingsRepository->useAmneziaDns(), adminConfig->dns1 = dns.first;
m_appSettingsRepository->primaryDns(), adminConfig->dns2 = dns.second;
m_appSettingsRepository->secondaryDns());
serverConfig.visit([&dns](auto& arg) {
arg.dns1 = dns.first;
arg.dns2 = dns.second;
});
QJsonObject serverJson = serverConfig.toJson(); QJsonObject serverJson = adminConfig->toJson();
QByteArray compressedConfig = QJsonDocument(serverJson).toJson(); QByteArray compressedConfig = QJsonDocument(serverJson).toJson();
compressedConfig = qCompress(compressedConfig, 8); compressedConfig = qCompress(compressedConfig, 8);
result.config = generateVpnUrl(compressedConfig); result.config = generateVpnUrl(compressedConfig);
@@ -111,7 +111,7 @@ ExportController::ExportResult ExportController::generateConnectionConfig(int se
return result; return result;
} }
ExportController::NativeConfigResult ExportController::generateNativeConfig(int serverIndex, DockerContainer container, ExportController::NativeConfigResult ExportController::generateNativeConfig(const QString &serverId, DockerContainer container,
const ContainerConfig &containerConfig, const ContainerConfig &containerConfig,
const QString &clientName) const QString &clientName)
{ {
@@ -123,11 +123,19 @@ ExportController::NativeConfigResult ExportController::generateNativeConfig(int
Proto protocol = ContainerUtils::defaultProtocol(container); Proto protocol = ContainerUtils::defaultProtocol(container);
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
ServerConfig serverConfig = m_serversRepository->server(serverIndex); if (!adminConfig.has_value()) {
auto dns = serverConfig.getDnsPair(m_appSettingsRepository->useAmneziaDns(), result.errorCode = ErrorCode::InternalError;
m_appSettingsRepository->primaryDns(), return result;
m_appSettingsRepository->secondaryDns()); }
const ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
result.errorCode = ErrorCode::InternalError;
return result;
}
const QPair<QString, QString> dns = adminConfig->getDnsPair(m_appSettingsRepository->useAmneziaDns(),
m_appSettingsRepository->primaryDns(),
m_appSettingsRepository->secondaryDns());
ContainerConfig modifiedContainerConfig = containerConfig; ContainerConfig modifiedContainerConfig = containerConfig;
modifiedContainerConfig.container = container; modifiedContainerConfig.container = container;
@@ -157,20 +165,25 @@ ExportController::NativeConfigResult ExportController::generateNativeConfig(int
if (protocol == Proto::OpenVpn || protocol == Proto::WireGuard || protocol == Proto::Awg || protocol == Proto::Xray) { if (protocol == Proto::OpenVpn || protocol == Proto::WireGuard || protocol == Proto::Awg || protocol == Proto::Xray) {
QString clientId = newProtocolConfig.clientId(); QString clientId = newProtocolConfig.clientId();
if (!clientId.isEmpty()) { if (!clientId.isEmpty()) {
emit appendClientRequested(serverIndex, clientId, clientName, container); emit appendClientRequested(serverId, clientId, clientName, container);
} }
} }
return result; return result;
} }
ExportController::ExportResult ExportController::generateOpenVpnConfig(int serverIndex, const QString &clientName) ExportController::ExportResult ExportController::generateOpenVpnConfig(const QString &serverId, const QString &clientName)
{ {
ExportResult result; ExportResult result;
DockerContainer container = DockerContainer::OpenVpn; DockerContainer container = DockerContainer::OpenVpn;
ContainerConfig containerConfig = m_serversRepository->containerConfig(serverIndex, container); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
result.errorCode = ErrorCode::InternalError;
return result;
}
ContainerConfig containerConfig = adminConfig->containerConfig(container);
auto nativeResult = generateNativeConfig(serverIndex, container, containerConfig, clientName); auto nativeResult = generateNativeConfig(serverId, container, containerConfig, clientName);
if (nativeResult.errorCode != ErrorCode::NoError) { if (nativeResult.errorCode != ErrorCode::NoError) {
result.errorCode = nativeResult.errorCode; result.errorCode = nativeResult.errorCode;
return result; return result;
@@ -185,13 +198,18 @@ ExportController::ExportResult ExportController::generateOpenVpnConfig(int serve
return result; return result;
} }
ExportController::ExportResult ExportController::generateWireGuardConfig(int serverIndex, const QString &clientName) ExportController::ExportResult ExportController::generateWireGuardConfig(const QString &serverId, const QString &clientName)
{ {
ExportResult result; ExportResult result;
ContainerConfig containerConfig = m_serversRepository->containerConfig(serverIndex, DockerContainer::WireGuard); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
result.errorCode = ErrorCode::InternalError;
return result;
}
ContainerConfig containerConfig = adminConfig->containerConfig(DockerContainer::WireGuard);
auto nativeResult = generateNativeConfig(serverIndex, DockerContainer::WireGuard, containerConfig, clientName); auto nativeResult = generateNativeConfig(serverId, DockerContainer::WireGuard, containerConfig, clientName);
if (nativeResult.errorCode != ErrorCode::NoError) { if (nativeResult.errorCode != ErrorCode::NoError) {
result.errorCode = nativeResult.errorCode; result.errorCode = nativeResult.errorCode;
return result; return result;
@@ -206,7 +224,7 @@ ExportController::ExportResult ExportController::generateWireGuardConfig(int ser
return result; return result;
} }
ExportController::ExportResult ExportController::generateAwgConfig(int serverIndex, int containerIndex, const QString &clientName) ExportController::ExportResult ExportController::generateAwgConfig(const QString &serverId, int containerIndex, const QString &clientName)
{ {
ExportResult result; ExportResult result;
@@ -215,9 +233,14 @@ ExportController::ExportResult ExportController::generateAwgConfig(int serverInd
result.errorCode = ErrorCode::InternalError; result.errorCode = ErrorCode::InternalError;
return result; return result;
} }
ContainerConfig containerConfig = m_serversRepository->containerConfig(serverIndex, container); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
result.errorCode = ErrorCode::InternalError;
return result;
}
ContainerConfig containerConfig = adminConfig->containerConfig(container);
auto nativeResult = generateNativeConfig(serverIndex, container, containerConfig, clientName); auto nativeResult = generateNativeConfig(serverId, container, containerConfig, clientName);
if (nativeResult.errorCode != ErrorCode::NoError) { if (nativeResult.errorCode != ErrorCode::NoError) {
result.errorCode = nativeResult.errorCode; result.errorCode = nativeResult.errorCode;
return result; return result;
@@ -233,13 +256,18 @@ ExportController::ExportResult ExportController::generateAwgConfig(int serverInd
} }
ExportController::ExportResult ExportController::generateXrayConfig(int serverIndex, const QString &clientName) ExportController::ExportResult ExportController::generateXrayConfig(const QString &serverId, const QString &clientName)
{ {
ExportResult result; ExportResult result;
ContainerConfig containerConfig = m_serversRepository->containerConfig(serverIndex, DockerContainer::Xray); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
result.errorCode = ErrorCode::InternalError;
return result;
}
ContainerConfig containerConfig = adminConfig->containerConfig(DockerContainer::Xray);
auto nativeResult = generateNativeConfig(serverIndex, DockerContainer::Xray, containerConfig, clientName); auto nativeResult = generateNativeConfig(serverId, DockerContainer::Xray, containerConfig, clientName);
if (nativeResult.errorCode != ErrorCode::NoError) { if (nativeResult.errorCode != ErrorCode::NoError) {
result.errorCode = nativeResult.errorCode; result.errorCode = nativeResult.errorCode;
return result; return result;
@@ -302,22 +330,22 @@ ExportController::ExportResult ExportController::generateXrayConfig(int serverIn
return result; return result;
} }
void ExportController::updateClientManagementModel(int serverIndex, int containerIndex) void ExportController::updateClientManagementModel(const QString &serverId, int containerIndex)
{ {
DockerContainer container = static_cast<DockerContainer>(containerIndex); DockerContainer container = static_cast<DockerContainer>(containerIndex);
emit updateClientsRequested(serverIndex, container); emit updateClientsRequested(serverId, container);
} }
void ExportController::revokeConfig(int row, int serverIndex, int containerIndex) void ExportController::revokeConfig(int row, const QString &serverId, int containerIndex)
{ {
DockerContainer container = static_cast<DockerContainer>(containerIndex); DockerContainer container = static_cast<DockerContainer>(containerIndex);
emit revokeClientRequested(serverIndex, row, container); emit revokeClientRequested(serverId, row, container);
} }
void ExportController::renameClient(int row, const QString &clientName, int serverIndex, int containerIndex) void ExportController::renameClient(int row, const QString &clientName, const QString &serverId, int containerIndex)
{ {
DockerContainer container = static_cast<DockerContainer>(containerIndex); DockerContainer container = static_cast<DockerContainer>(containerIndex);
emit renameClientRequested(serverIndex, row, clientName, container); emit renameClientRequested(serverId, row, clientName, container);
} }
QString ExportController::generateVpnUrl(const QByteArray &compressedConfig) QString ExportController::generateVpnUrl(const QByteArray &compressedConfig)
@@ -37,23 +37,23 @@ public:
SecureAppSettingsRepository* appSettingsRepository, SecureAppSettingsRepository* appSettingsRepository,
QObject *parent = nullptr); QObject *parent = nullptr);
ExportResult generateFullAccessConfig(int serverIndex); ExportResult generateFullAccessConfig(const QString &serverId);
ExportResult generateConnectionConfig(int serverIndex, int containerIndex, const QString &clientName); ExportResult generateConnectionConfig(const QString &serverId, int containerIndex, const QString &clientName);
ExportResult generateOpenVpnConfig(int serverIndex, const QString &clientName); ExportResult generateOpenVpnConfig(const QString &serverId, const QString &clientName);
ExportResult generateWireGuardConfig(int serverIndex, const QString &clientName); ExportResult generateWireGuardConfig(const QString &serverId, const QString &clientName);
ExportResult generateAwgConfig(int serverIndex, int containerIndex, const QString &clientName); ExportResult generateAwgConfig(const QString &serverId, int containerIndex, const QString &clientName);
ExportResult generateXrayConfig(int serverIndex, const QString &clientName); ExportResult generateXrayConfig(const QString &serverId, const QString &clientName);
signals: signals:
void appendClientRequested(int serverIndex, const QString &clientId, const QString &clientName, DockerContainer container); void appendClientRequested(const QString &serverId, const QString &clientId, const QString &clientName, DockerContainer container);
void updateClientsRequested(int serverIndex, DockerContainer container); void updateClientsRequested(const QString &serverId, DockerContainer container);
void revokeClientRequested(int serverIndex, int row, DockerContainer container); void revokeClientRequested(const QString &serverId, int row, DockerContainer container);
void renameClientRequested(int serverIndex, int row, const QString &clientName, DockerContainer container); void renameClientRequested(const QString &serverId, int row, const QString &clientName, DockerContainer container);
public slots: public slots:
void updateClientManagementModel(int serverIndex, int containerIndex); void updateClientManagementModel(const QString &serverId, int containerIndex);
void revokeConfig(int row, int serverIndex, int containerIndex); void revokeConfig(int row, const QString &serverId, int containerIndex);
void renameClient(int row, const QString &clientName, int serverIndex, int containerIndex); void renameClient(int row, const QString &clientName, const QString &serverId, int containerIndex);
private: private:
struct NativeConfigResult struct NativeConfigResult
@@ -62,7 +62,7 @@ private:
QJsonObject jsonNativeConfig; QJsonObject jsonNativeConfig;
}; };
NativeConfigResult generateNativeConfig(int serverIndex, DockerContainer container, NativeConfigResult generateNativeConfig(const QString &serverId, DockerContainer container,
const ContainerConfig &containerConfig, const ContainerConfig &containerConfig,
const QString &clientName); const QString &clientName);
@@ -16,7 +16,7 @@
#include "core/utils/containerEnum.h" #include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h" #include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h" #include "core/utils/protocolEnum.h"
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
#include "core/utils/api/apiUtils.h" #include "core/utils/api/apiUtils.h"
@@ -27,7 +27,6 @@
#include "core/utils/constants/configKeys.h" #include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h" #include "core/utils/constants/protocolConstants.h"
#include "core/utils/qrCodeUtils.h" #include "core/utils/qrCodeUtils.h"
#include "core/models/serverConfig.h"
using namespace amnezia; using namespace amnezia;
using namespace ProtocolUtils; using namespace ProtocolUtils;
@@ -208,12 +207,18 @@ ImportController::ImportResult ImportController::extractConfigFromData(const QSt
case ConfigTypes::Amnezia: { case ConfigTypes::Amnezia: {
result.config = QJsonDocument::fromJson(config.toUtf8()).object(); result.config = QJsonDocument::fromJson(config.toUtf8()).object();
if (apiUtils::isServerFromApi(result.config)) { if (serverConfigUtils::isServerFromApi(result.config)) {
auto apiConfig = result.config.value(apiDefs::key::apiConfig).toObject(); auto apiConfig = result.config.value(apiDefs::key::apiConfig).toObject();
apiConfig[apiDefs::key::vpnKey] = data; apiConfig[apiDefs::key::vpnKey] = data;
result.config[apiDefs::key::apiConfig] = apiConfig; result.config[apiDefs::key::apiConfig] = apiConfig;
} }
if (serverConfigUtils::isLegacyApiSubscription(serverConfigUtils::configTypeFromJson(result.config))) {
result.errorCode = ErrorCode::LegacyApiV1NotSupportedError;
result.config = {};
return result;
}
processAmneziaConfig(result.config); processAmneziaConfig(result.config);
if (!result.config.empty()) { if (!result.config.empty()) {
checkForMaliciousStrings(result.config, result.maliciousWarningText); checkForMaliciousStrings(result.config, result.maliciousWarningText);
@@ -381,18 +386,29 @@ void ImportController::importConfig(const QJsonObject &config)
credentials.secretData = config.value(configKey::password).toString(); credentials.secretData = config.value(configKey::password).toString();
if (credentials.isValid() || config.contains(configKey::containers)) { if (credentials.isValid() || config.contains(configKey::containers)) {
ServerConfig serverConfig = ServerConfig::fromJson(config); m_serversRepository->addServer(QString(), config, serverConfigUtils::configTypeFromJson(config));
m_serversRepository->addServer(serverConfig);
emit importFinished(); emit importFinished();
} else if (config.contains(configKey::configVersion)) { } else if (config.contains(configKey::configVersion)) {
quint16 crc = qChecksum(QJsonDocument(config).toJson()); quint16 crc = qChecksum(QJsonDocument(config).toJson());
if (m_serversRepository->hasServerWithCrc(crc)) { bool hasServerWithCrc = false;
const QVector<QString> ids = m_serversRepository->orderedServerIds();
for (const QString &id : ids) {
const auto apiV2 = m_serversRepository->apiV2Config(id);
if (!apiV2.has_value()) {
continue;
}
if (static_cast<quint16>(apiV2->crc) == crc) {
hasServerWithCrc = true;
break;
}
}
if (hasServerWithCrc) {
emit importErrorOccurred(ErrorCode::ApiConfigAlreadyAdded, true); emit importErrorOccurred(ErrorCode::ApiConfigAlreadyAdded, true);
} else { } else {
QJsonObject configWithCrc = config; QJsonObject configWithCrc = config;
configWithCrc.insert(configKey::crc, crc); configWithCrc.insert(configKey::crc, crc);
ServerConfig serverConfig = ServerConfig::fromJson(configWithCrc); m_serversRepository->addServer(QString(), configWithCrc, serverConfigUtils::configTypeFromJson(configWithCrc));
m_serversRepository->addServer(serverConfig);
emit importFinished(); emit importFinished();
} }
} else { } else {
@@ -33,7 +33,6 @@
#include "core/protocols/protocolUtils.h" #include "core/protocols/protocolUtils.h"
#include "core/utils/constants/configKeys.h" #include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h" #include "core/utils/constants/protocolConstants.h"
#include "core/models/serverConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/models/protocols/awgProtocolConfig.h" #include "core/models/protocols/awgProtocolConfig.h"
#include "ui/models/protocols/wireguardConfigModel.h" #include "ui/models/protocols/wireguardConfigModel.h"
@@ -129,15 +128,27 @@ ErrorCode InstallController::setupContainer(const ServerCredentials &credentials
return startupContainerWorker(credentials, container, config, sshSession); return startupContainerWorker(credentials, container, config, sshSession);
} }
ErrorCode InstallController::updateContainer(int serverIndex, DockerContainer container, const ContainerConfig &oldConfig, ErrorCode InstallController::updateContainer(const QString &serverId, DockerContainer container, const ContainerConfig &oldConfig,
ContainerConfig &newConfig) ContainerConfig &newConfig)
{ {
if (!isUpdateDockerContainerRequired(container, oldConfig, newConfig)) { if (!isUpdateDockerContainerRequired(container, oldConfig, newConfig)) {
m_serversRepository->setContainerConfig(serverIndex, container, newConfig); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
adminConfig->updateContainerConfig(container, newConfig);
m_serversRepository->editServer(serverId, adminConfig->toJson(), serverConfigUtils::ConfigType::SelfHostedAdmin);
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
SshSession sshSession(this); SshSession sshSession(this);
bool reinstallRequired = isReinstallContainerRequired(container, oldConfig, newConfig); bool reinstallRequired = isReinstallContainerRequired(container, oldConfig, newConfig);
@@ -154,42 +165,51 @@ ErrorCode InstallController::updateContainer(int serverIndex, DockerContainer co
} }
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
clearCachedProfile(serverIndex, container); clearCachedProfile(serverId, container);
m_serversRepository->setContainerConfig(serverIndex, container, newConfig); adminConfig->updateContainerConfig(container, newConfig);
m_serversRepository->editServer(serverId, adminConfig->toJson(), serverConfigUtils::ConfigType::SelfHostedAdmin);
} }
return errorCode; return errorCode;
} }
void InstallController::clearCachedProfile(int serverIndex, DockerContainer container) void InstallController::clearCachedProfile(const QString &serverId, DockerContainer container)
{ {
if (ContainerUtils::containerService(container) == ServiceType::Other) { if (ContainerUtils::containerService(container) == ServiceType::Other) {
return; return;
} }
ContainerConfig containerConfigModel = m_serversRepository->containerConfig(serverIndex, container); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
m_serversRepository->clearLastConnectionConfig(serverIndex, container); return;
emit clientRevocationRequested(serverIndex, containerConfigModel, container);
}
ErrorCode InstallController::validateAndPrepareConfig(int serverIndex)
{
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex);
if (serverConfigModel.isApiConfig()) {
return ErrorCode::NoError;
} }
DockerContainer container = serverConfigModel.defaultContainer(); adminConfig->clearCachedClientProfile(container);
const ContainerConfig containerConfigModel = adminConfig->containerConfig(container);
m_serversRepository->editServer(serverId, adminConfig->toJson(), serverConfigUtils::ConfigType::SelfHostedAdmin);
emit clientRevocationRequested(serverId, containerConfigModel, container);
}
ErrorCode InstallController::validateAndPrepareConfig(const QString &serverId)
{
auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
DockerContainer container = adminConfig->defaultContainer;
if (container == DockerContainer::None) { if (container == DockerContainer::None) {
return ErrorCode::NoInstalledContainersError; return ErrorCode::NoInstalledContainersError;
} }
ContainerConfig containerConfig = m_serversRepository->containerConfig(serverIndex, container); ContainerConfig containerConfig = adminConfig->containerConfig(container);
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
SshSession sshSession; SshSession sshSession;
auto isProtocolConfigExists = [](const ContainerConfig &cfg) { auto isProtocolConfigExists = [](const ContainerConfig &cfg) {
@@ -198,20 +218,21 @@ ErrorCode InstallController::validateAndPrepareConfig(int serverIndex)
if (!isProtocolConfigExists(containerConfig)) { if (!isProtocolConfigExists(containerConfig)) {
QString clientName = QString("Admin [%1]").arg(QSysInfo::prettyProductName()); QString clientName = QString("Admin [%1]").arg(QSysInfo::prettyProductName());
ErrorCode errorCode = processContainerForAdmin(container, containerConfig, credentials, sshSession, serverIndex, clientName); ErrorCode errorCode = processContainerForAdmin(container, containerConfig, credentials, sshSession, serverId, clientName);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }
m_serversRepository->setContainerConfig(serverIndex, container, containerConfig); adminConfig->updateContainerConfig(container, containerConfig);
m_serversRepository->editServer(serverId, adminConfig->toJson(), serverConfigUtils::ConfigType::SelfHostedAdmin);
} }
return ErrorCode::NoError; return ErrorCode::NoError;
} }
void InstallController::validateConfig(int serverIndex) void InstallController::validateConfig(const QString &serverId)
{ {
QFuture<ErrorCode> future = QtConcurrent::run([this, serverIndex]() { QFuture<ErrorCode> future = QtConcurrent::run([this, serverId]() {
return validateAndPrepareConfig(serverIndex); return validateAndPrepareConfig(serverId);
}); });
auto *watcher = new QFutureWatcher<ErrorCode>(this); auto *watcher = new QFutureWatcher<ErrorCode>(this);
@@ -230,6 +251,21 @@ void InstallController::validateConfig(int serverIndex)
watcher->setFuture(future); watcher->setFuture(future);
} }
void InstallController::addEmptyServer(const ServerCredentials &credentials)
{
SelfHostedAdminServerConfig serverConfig;
serverConfig.hostName = credentials.hostName;
serverConfig.userName = credentials.userName;
serverConfig.password = credentials.secretData;
serverConfig.port = credentials.port;
serverConfig.description = m_appSettingsRepository->nextAvailableServerName();
serverConfig.displayName = serverConfig.description.isEmpty() ? serverConfig.hostName : serverConfig.description;
serverConfig.defaultContainer = DockerContainer::None;
m_serversRepository->addServer(QString(), serverConfig.toJson(),
serverConfigUtils::ConfigType::SelfHostedAdmin);
}
ErrorCode InstallController::prepareContainerConfig(DockerContainer container, const ServerCredentials &credentials, ContainerConfig &containerConfig, SshSession &sshSession) ErrorCode InstallController::prepareContainerConfig(DockerContainer container, const ServerCredentials &credentials, ContainerConfig &containerConfig, SshSession &sshSession)
{ {
if (!ContainerUtils::isSupportedByCurrentPlatform(container)) { if (!ContainerUtils::isSupportedByCurrentPlatform(container)) {
@@ -257,7 +293,7 @@ ErrorCode InstallController::prepareContainerConfig(DockerContainer container, c
return ErrorCode::NoError; return ErrorCode::NoError;
} }
void InstallController::adminAppendRequested(int serverIndex, DockerContainer container, void InstallController::adminAppendRequested(const QString &serverId, DockerContainer container,
const ContainerConfig &containerConfig, const QString &clientName) const ContainerConfig &containerConfig, const QString &clientName)
{ {
if (ContainerUtils::containerService(container) == ServiceType::Other if (ContainerUtils::containerService(container) == ServiceType::Other
@@ -266,13 +302,13 @@ void InstallController::adminAppendRequested(int serverIndex, DockerContainer co
} }
QString clientId = containerConfig.protocolConfig.clientId(); QString clientId = containerConfig.protocolConfig.clientId();
if (!clientId.isEmpty()) { if (!clientId.isEmpty()) {
emit clientAppendRequested(serverIndex, clientId, clientName, container); emit clientAppendRequested(serverId, clientId, clientName, container);
} }
} }
ErrorCode InstallController::processContainerForAdmin(DockerContainer container, ContainerConfig &containerConfig, ErrorCode InstallController::processContainerForAdmin(DockerContainer container, ContainerConfig &containerConfig,
const ServerCredentials &credentials, SshSession &sshSession, const ServerCredentials &credentials, SshSession &sshSession,
int serverIndex, const QString &clientName) const QString &serverId, const QString &clientName)
{ {
if (ContainerUtils::isSupportedByCurrentPlatform(container)) { if (ContainerUtils::isSupportedByCurrentPlatform(container)) {
ErrorCode errorCode = prepareContainerConfig(container, credentials, containerConfig, sshSession); ErrorCode errorCode = prepareContainerConfig(container, credentials, containerConfig, sshSession);
@@ -280,7 +316,7 @@ ErrorCode InstallController::processContainerForAdmin(DockerContainer container,
return errorCode; return errorCode;
} }
} }
adminAppendRequested(serverIndex, container, containerConfig, clientName); adminAppendRequested(serverId, container, containerConfig, clientName);
return ErrorCode::NoError; return ErrorCode::NoError;
} }
@@ -688,9 +724,16 @@ ErrorCode InstallController::setupServerFirewall(const ServerCredentials &creden
amnezia::genBaseVars(credentials, DockerContainer::None, QString(), QString()))); amnezia::genBaseVars(credentials, DockerContainer::None, QString(), QString())));
} }
ErrorCode InstallController::rebootServer(int serverIndex) ErrorCode InstallController::rebootServer(const QString &serverId)
{ {
auto credentials = m_serversRepository->serverCredentials(serverIndex); const auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
SshSession sshSession(this); SshSession sshSession(this);
QString script = QString("sudo reboot"); QString script = QString("sudo reboot");
@@ -709,27 +752,38 @@ ErrorCode InstallController::rebootServer(int serverIndex)
return sshSession.runScript(credentials, script, cbReadStdOut, cbReadStdErr); return sshSession.runScript(credentials, script, cbReadStdOut, cbReadStdErr);
} }
ErrorCode InstallController::removeAllContainers(int serverIndex) ErrorCode InstallController::removeAllContainers(const QString &serverId)
{ {
auto credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
SshSession sshSession(this); SshSession sshSession(this);
ErrorCode errorCode = sshSession.runScript(credentials, amnezia::scriptData(SharedScriptType::remove_all_containers)); ErrorCode errorCode = sshSession.runScript(credentials, amnezia::scriptData(SharedScriptType::remove_all_containers));
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); adminConfig->containers.clear();
serverConfigModel.visit([](auto& arg) { adminConfig->defaultContainer = DockerContainer::None;
arg.containers.clear(); m_serversRepository->editServer(serverId, adminConfig->toJson(), serverConfigUtils::ConfigType::SelfHostedAdmin);
arg.defaultContainer = DockerContainer::None;
});
m_serversRepository->editServer(serverIndex, serverConfigModel);
} }
return errorCode; return errorCode;
} }
ErrorCode InstallController::removeContainer(int serverIndex, DockerContainer container) ErrorCode InstallController::removeContainer(const QString &serverId, DockerContainer container)
{ {
auto credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
SshSession sshSession(this); SshSession sshSession(this);
ErrorCode errorCode = sshSession.runScript( ErrorCode errorCode = sshSession.runScript(
credentials, credentials,
@@ -737,11 +791,10 @@ ErrorCode InstallController::removeContainer(int serverIndex, DockerContainer co
amnezia::genBaseVars(credentials, container, QString(), QString()))); amnezia::genBaseVars(credentials, container, QString(), QString())));
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); QMap<DockerContainer, ContainerConfig> containers = adminConfig->containers;
QMap<DockerContainer, ContainerConfig> containers = serverConfigModel.containers();
containers.remove(container); containers.remove(container);
DockerContainer defaultContainer = serverConfigModel.defaultContainer(); DockerContainer defaultContainer = adminConfig->defaultContainer;
if (defaultContainer == container) { if (defaultContainer == container) {
if (containers.isEmpty()) { if (containers.isEmpty()) {
defaultContainer = DockerContainer::None; defaultContainer = DockerContainer::None;
@@ -749,12 +802,10 @@ ErrorCode InstallController::removeContainer(int serverIndex, DockerContainer co
defaultContainer = containers.begin().key(); defaultContainer = containers.begin().key();
} }
} }
serverConfigModel.visit([&containers, defaultContainer](auto& arg) { adminConfig->containers = containers;
arg.containers = containers; adminConfig->defaultContainer = defaultContainer;
arg.defaultContainer = defaultContainer; m_serversRepository->editServer(serverId, adminConfig->toJson(), serverConfigUtils::ConfigType::SelfHostedAdmin);
});
m_serversRepository->editServer(serverIndex, serverConfigModel);
} }
return errorCode; return errorCode;
@@ -815,9 +866,16 @@ bool InstallController::isUpdateDockerContainerRequired(DockerContainer containe
return true; return true;
} }
ErrorCode InstallController::scanServerForInstalledContainers(int serverIndex) ErrorCode InstallController::scanServerForInstalledContainers(const QString &serverId)
{ {
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
SshSession sshSession(this); SshSession sshSession(this);
QMap<DockerContainer, ContainerConfig> installedContainers; QMap<DockerContainer, ContainerConfig> installedContainers;
@@ -826,8 +884,7 @@ ErrorCode InstallController::scanServerForInstalledContainers(int serverIndex)
return errorCode; return errorCode;
} }
ServerConfig serverConfigModel = m_serversRepository->server(serverIndex); QMap<DockerContainer, ContainerConfig> containers = adminConfig->containers;
QMap<DockerContainer, ContainerConfig> containers = serverConfigModel.containers();
bool hasNewContainers = false; bool hasNewContainers = false;
QString clientName = QString("Admin [%1]").arg(QSysInfo::prettyProductName()); QString clientName = QString("Admin [%1]").arg(QSysInfo::prettyProductName());
@@ -835,29 +892,25 @@ ErrorCode InstallController::scanServerForInstalledContainers(int serverIndex)
if (!containers.contains(iterator.key())) { if (!containers.contains(iterator.key())) {
ContainerConfig containerConfig = iterator.value(); ContainerConfig containerConfig = iterator.value();
errorCode = processContainerForAdmin(iterator.key(), containerConfig, credentials, sshSession, errorCode = processContainerForAdmin(iterator.key(), containerConfig, credentials, sshSession,
serverIndex, clientName); serverId, clientName);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }
containers.insert(iterator.key(), containerConfig); containers.insert(iterator.key(), containerConfig);
hasNewContainers = true; hasNewContainers = true;
DockerContainer defaultContainer = serverConfigModel.defaultContainer(); DockerContainer defaultContainer = adminConfig->defaultContainer;
if (defaultContainer == DockerContainer::None if (defaultContainer == DockerContainer::None
&& ContainerUtils::containerService(iterator.key()) != ServiceType::Other && ContainerUtils::containerService(iterator.key()) != ServiceType::Other
&& ContainerUtils::isSupportedByCurrentPlatform(iterator.key())) { && ContainerUtils::isSupportedByCurrentPlatform(iterator.key())) {
serverConfigModel.visit([iterator](auto& arg) { adminConfig->defaultContainer = iterator.key();
arg.defaultContainer = iterator.key();
});
} }
} }
} }
if (hasNewContainers) { if (hasNewContainers) {
serverConfigModel.visit([&containers](auto& arg) { adminConfig->containers = containers;
arg.containers = containers; m_serversRepository->editServer(serverId, adminConfig->toJson(), serverConfigUtils::ConfigType::SelfHostedAdmin);
});
m_serversRepository->editServer(serverIndex, serverConfigModel);
} }
return ErrorCode::NoError; return ErrorCode::NoError;
@@ -899,7 +952,7 @@ ErrorCode InstallController::installServer(const ServerCredentials &credentials,
preparedContainers.insert(container, containerConfig); preparedContainers.insert(container, containerConfig);
} }
SelfHostedServerConfig serverConfig; SelfHostedAdminServerConfig serverConfig;
serverConfig.hostName = credentials.hostName; serverConfig.hostName = credentials.hostName;
serverConfig.userName = credentials.userName; serverConfig.userName = credentials.userName;
serverConfig.password = credentials.secretData; serverConfig.password = credentials.secretData;
@@ -912,21 +965,29 @@ ErrorCode InstallController::installServer(const ServerCredentials &credentials,
serverConfig.defaultContainer = container; serverConfig.defaultContainer = container;
m_serversRepository->addServer(ServerConfig(serverConfig)); serverConfig.displayName = serverConfig.description.isEmpty() ? serverConfig.hostName : serverConfig.description;
int serverIndex = m_serversRepository->serversCount() - 1; const QString newServerId = m_serversRepository->addServer(QString(), serverConfig.toJson(),
serverConfigUtils::ConfigType::SelfHostedAdmin);
QString clientName = QString("Admin [%1]").arg(QSysInfo::prettyProductName()); QString clientName = QString("Admin [%1]").arg(QSysInfo::prettyProductName());
for (auto iterator = preparedContainers.begin(); iterator != preparedContainers.end(); iterator++) { for (auto iterator = preparedContainers.begin(); iterator != preparedContainers.end(); iterator++) {
adminAppendRequested(serverIndex, iterator.key(), iterator.value(), clientName); adminAppendRequested(newServerId, iterator.key(), iterator.value(), clientName);
} }
return ErrorCode::NoError; return ErrorCode::NoError;
} }
ErrorCode InstallController::installContainer(int serverIndex, DockerContainer container, int port, ErrorCode InstallController::installContainer(const QString &serverId, DockerContainer container, int port,
TransportProto transportProto, bool &wasContainerInstalled) TransportProto transportProto, bool &wasContainerInstalled)
{ {
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
SshSession sshSession(this); SshSession sshSession(this);
QMap<DockerContainer, ContainerConfig> installedContainers; QMap<DockerContainer, ContainerConfig> installedContainers;
@@ -949,15 +1010,17 @@ ErrorCode InstallController::installContainer(int serverIndex, DockerContainer c
QString clientName = QString("Admin [%1]").arg(QSysInfo::prettyProductName()); QString clientName = QString("Admin [%1]").arg(QSysInfo::prettyProductName());
for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) { for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
ContainerConfig existingConfigModel = m_serversRepository->containerConfig(serverIndex, iterator.key()); ContainerConfig existingConfigModel = adminConfig->containerConfig(iterator.key());
if (existingConfigModel.container == DockerContainer::None) { if (existingConfigModel.container == DockerContainer::None) {
ContainerConfig containerConfig = iterator.value(); ContainerConfig containerConfig = iterator.value();
errorCode = processContainerForAdmin(iterator.key(), containerConfig, credentials, sshSession, errorCode = processContainerForAdmin(iterator.key(), containerConfig, credentials, sshSession,
serverIndex, clientName); serverId, clientName);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }
m_serversRepository->setContainerConfig(serverIndex, iterator.key(), containerConfig); adminConfig->updateContainerConfig(iterator.key(), containerConfig);
m_serversRepository->editServer(serverId, adminConfig->toJson(),
serverConfigUtils::ConfigType::SelfHostedAdmin);
} }
} }
@@ -993,7 +1056,15 @@ bool InstallController::isServerAlreadyExists(const ServerCredentials &credentia
{ {
int serversCount = m_serversRepository->serversCount(); int serversCount = m_serversRepository->serversCount();
for (int i = 0; i < serversCount; i++) { for (int i = 0; i < serversCount; i++) {
const ServerCredentials existingCredentials = m_serversRepository->serverCredentials(i); const QString existingServerId = m_serversRepository->serverIdAt(i);
const auto adminConfig = m_serversRepository->selfHostedAdminConfig(existingServerId);
if (!adminConfig.has_value()) {
continue;
}
const ServerCredentials existingCredentials = adminConfig->credentials();
if (!existingCredentials.isValid()) {
continue;
}
if (credentials.hostName == existingCredentials.hostName && credentials.port == existingCredentials.port) { if (credentials.hostName == existingCredentials.hostName && credentials.port == existingCredentials.port) {
existingServerIndex = i; existingServerIndex = i;
return true; return true;
@@ -33,22 +33,22 @@ public:
~InstallController(); ~InstallController();
ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, ContainerConfig &config, bool isUpdate = false); ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, ContainerConfig &config, bool isUpdate = false);
ErrorCode updateContainer(int serverIndex, DockerContainer container, const ContainerConfig &oldConfig, ContainerConfig &newConfig); ErrorCode updateContainer(const QString &serverId, DockerContainer container, const ContainerConfig &oldConfig, ContainerConfig &newConfig);
ErrorCode rebootServer(int serverIndex); ErrorCode rebootServer(const QString &serverId);
ErrorCode removeAllContainers(int serverIndex); ErrorCode removeAllContainers(const QString &serverId);
ErrorCode removeContainer(int serverIndex, DockerContainer container); ErrorCode removeContainer(const QString &serverId, DockerContainer container);
ContainerConfig generateConfig(DockerContainer container, int port, TransportProto transportProto); ContainerConfig generateConfig(DockerContainer container, int port, TransportProto transportProto);
ErrorCode getAlreadyInstalledContainers(const ServerCredentials &credentials, QMap<DockerContainer, ContainerConfig> &installedContainers, SshSession &sshSession); ErrorCode getAlreadyInstalledContainers(const ServerCredentials &credentials, QMap<DockerContainer, ContainerConfig> &installedContainers, SshSession &sshSession);
ErrorCode scanServerForInstalledContainers(int serverIndex); ErrorCode scanServerForInstalledContainers(const QString &serverId);
ErrorCode installContainer(const ServerCredentials &credentials, DockerContainer container, int port, TransportProto transportProto, ContainerConfig &config); ErrorCode installContainer(const ServerCredentials &credentials, DockerContainer container, int port, TransportProto transportProto, ContainerConfig &config);
ErrorCode installServer(const ServerCredentials &credentials, DockerContainer container, int port, TransportProto transportProto, ErrorCode installServer(const ServerCredentials &credentials, DockerContainer container, int port, TransportProto transportProto,
bool &wasContainerInstalled); bool &wasContainerInstalled);
ErrorCode installContainer(int serverIndex, DockerContainer container, int port, TransportProto transportProto, ErrorCode installContainer(const QString &serverId, DockerContainer container, int port, TransportProto transportProto,
bool &wasContainerInstalled); bool &wasContainerInstalled);
bool isUpdateDockerContainerRequired(DockerContainer container, const ContainerConfig &oldConfig, const ContainerConfig &newConfig); bool isUpdateDockerContainerRequired(DockerContainer container, const ContainerConfig &oldConfig, const ContainerConfig &newConfig);
@@ -62,11 +62,13 @@ public:
void cancelInstallation(); void cancelInstallation();
void clearCachedProfile(int serverIndex, DockerContainer container); void clearCachedProfile(const QString &serverId, DockerContainer container);
ErrorCode validateAndPrepareConfig(int serverIndex); ErrorCode validateAndPrepareConfig(const QString &serverId);
void validateConfig(int serverIndex); void validateConfig(const QString &serverId);
void addEmptyServer(const ServerCredentials &credentials);
signals: signals:
void configValidated(bool isValid); void configValidated(bool isValid);
@@ -74,8 +76,8 @@ signals:
void serverIsBusy(const bool isBusy); void serverIsBusy(const bool isBusy);
void cancelInstallationRequested(); void cancelInstallationRequested();
void clientRevocationRequested(int serverIndex, const ContainerConfig &containerConfig, DockerContainer container); void clientRevocationRequested(const QString &serverId, const ContainerConfig &containerConfig, DockerContainer container);
void clientAppendRequested(int serverIndex, const QString &clientId, const QString &clientName, DockerContainer container); void clientAppendRequested(const QString &serverId, const QString &clientId, const QString &clientName, DockerContainer container);
private: private:
ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container, SshSession &sshSession); ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container, SshSession &sshSession);
@@ -95,9 +97,9 @@ private:
ErrorCode processContainerForAdmin(DockerContainer container, ContainerConfig &containerConfig, ErrorCode processContainerForAdmin(DockerContainer container, ContainerConfig &containerConfig,
const ServerCredentials &credentials, SshSession &sshSession, const ServerCredentials &credentials, SshSession &sshSession,
int serverIndex, const QString &clientName); const QString &serverId, const QString &clientName);
void adminAppendRequested(int serverIndex, DockerContainer container, void adminAppendRequested(const QString &serverId, DockerContainer container,
const ContainerConfig &containerConfig, const QString &clientName); const ContainerConfig &containerConfig, const QString &clientName);
static void updateContainerConfigAfterInstallation(DockerContainer container, ContainerConfig &containerConfig, const QString &stdOut); static void updateContainerConfigAfterInstallation(DockerContainer container, ContainerConfig &containerConfig, const QString &stdOut);
@@ -114,4 +116,3 @@ private:
}; };
#endif // INSTALLCONTROLLER_H #endif // INSTALLCONTROLLER_H
@@ -14,7 +14,6 @@
#include "core/protocols/protocolUtils.h" #include "core/protocols/protocolUtils.h"
#include "core/utils/constants/configKeys.h" #include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h" #include "core/utils/constants/protocolConstants.h"
#include "core/models/serverConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
using namespace amnezia; using namespace amnezia;
@@ -292,11 +291,18 @@ ErrorCode UsersController::getXrayClients(const DockerContainer container, const
return error; return error;
} }
ErrorCode UsersController::updateClients(int serverIndex, const DockerContainer container) ErrorCode UsersController::updateClients(const QString &serverId, const DockerContainer container)
{ {
ErrorCode error = ErrorCode::NoError; ErrorCode error = ErrorCode::NoError;
SshSession sshSession; SshSession sshSession;
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable"); QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
if (container == DockerContainer::OpenVpn) { if (container == DockerContainer::OpenVpn) {
@@ -381,20 +387,27 @@ ErrorCode UsersController::updateClients(int serverIndex, const DockerContainer
} }
ErrorCode UsersController::appendClient(int serverIndex, const QString &clientId, const QString &clientName, const DockerContainer container) ErrorCode UsersController::appendClient(const QString &serverId, const QString &clientId, const QString &clientName, const DockerContainer container)
{ {
ErrorCode error = ErrorCode::NoError; ErrorCode error = ErrorCode::NoError;
SshSession sshSession; SshSession sshSession;
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
error = updateClients(serverIndex, container); error = updateClients(serverId, container);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
return error; return error;
} }
int existingIndex = clientIndexById(clientId, m_clientsTable); int existingIndex = clientIndexById(clientId, m_clientsTable);
if (existingIndex >= 0) { if (existingIndex >= 0) {
return renameClient(serverIndex, existingIndex, clientName, container, true); return renameClient(serverId, existingIndex, clientName, container, true);
} }
QJsonObject client; QJsonObject client;
@@ -426,7 +439,7 @@ ErrorCode UsersController::appendClient(int serverIndex, const QString &clientId
return error; return error;
} }
ErrorCode UsersController::renameClient(int serverIndex, const int row, const QString &clientName, ErrorCode UsersController::renameClient(const QString &serverId, const int row, const QString &clientName,
const DockerContainer container, bool addTimeStamp) const DockerContainer container, bool addTimeStamp)
{ {
if (row < 0 || row >= m_clientsTable.size()) { if (row < 0 || row >= m_clientsTable.size()) {
@@ -434,7 +447,14 @@ ErrorCode UsersController::renameClient(int serverIndex, const int row, const QS
} }
SshSession sshSession; SshSession sshSession;
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
auto client = m_clientsTable.at(row).toObject(); auto client = m_clientsTable.at(row).toObject();
auto userData = client[configKey::userData].toObject(); auto userData = client[configKey::userData].toObject();
@@ -470,7 +490,7 @@ ErrorCode UsersController::renameClient(int serverIndex, const int row, const QS
} }
ErrorCode UsersController::revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials, ErrorCode UsersController::revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials,
const int serverIndex, SshSession* sshSession, QJsonArray &clientsTable) SshSession* sshSession, QJsonArray &clientsTable)
{ {
if (row < 0 || row >= clientsTable.size()) { if (row < 0 || row >= clientsTable.size()) {
return ErrorCode::InternalError; return ErrorCode::InternalError;
@@ -689,14 +709,21 @@ ErrorCode UsersController::revokeXray(const int row,
return error; return error;
} }
ErrorCode UsersController::revokeClient(int serverIndex, const int index, const DockerContainer container) ErrorCode UsersController::revokeClient(const QString &serverId, const int index, const DockerContainer container)
{ {
if (index < 0 || index >= m_clientsTable.size()) { if (index < 0 || index >= m_clientsTable.size()) {
return ErrorCode::InternalError; return ErrorCode::InternalError;
} }
SshSession sshSession; SshSession sshSession;
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
QString clientId = m_clientsTable.at(index).toObject().value(configKey::clientId).toString(); QString clientId = m_clientsTable.at(index).toObject().value(configKey::clientId).toString();
ErrorCode errorCode = ErrorCode::NoError; ErrorCode errorCode = ErrorCode::NoError;
@@ -704,7 +731,7 @@ ErrorCode UsersController::revokeClient(int serverIndex, const int index, const
switch(container) switch(container)
{ {
case DockerContainer::OpenVpn: { case DockerContainer::OpenVpn: {
errorCode = revokeOpenVpn(index, container, credentials, serverIndex, &sshSession, m_clientsTable); errorCode = revokeOpenVpn(index, container, credentials, &sshSession, m_clientsTable);
break; break;
} }
case DockerContainer::WireGuard: case DockerContainer::WireGuard:
@@ -724,12 +751,15 @@ ErrorCode UsersController::revokeClient(int serverIndex, const int index, const
} }
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
ServerConfig serverConfig = m_serversRepository->server(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
ContainerConfig containerCfg = m_serversRepository->containerConfig(serverIndex, container); if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ContainerConfig containerCfg = adminConfig->containerConfig(container);
QString containerClientId = containerCfg.protocolConfig.clientId(); QString containerClientId = containerCfg.protocolConfig.clientId();
if (!clientId.isEmpty() && !containerClientId.isEmpty() && containerClientId.contains(clientId)) { if (!clientId.isEmpty() && !containerClientId.isEmpty() && containerClientId.contains(clientId)) {
emit adminConfigRevoked(serverIndex, container); emit adminConfigRevoked(serverId, container);
} }
emit clientRevoked(index); emit clientRevoked(index);
@@ -739,13 +769,20 @@ ErrorCode UsersController::revokeClient(int serverIndex, const int index, const
return errorCode; return errorCode;
} }
ErrorCode UsersController::revokeClient(int serverIndex, const ContainerConfig &containerConfig, const DockerContainer container) ErrorCode UsersController::revokeClient(const QString &serverId, const ContainerConfig &containerConfig, const DockerContainer container)
{ {
SshSession sshSession; SshSession sshSession;
ServerCredentials credentials = m_serversRepository->serverCredentials(serverIndex); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return ErrorCode::InternalError;
}
ServerCredentials credentials = adminConfig->credentials();
if (!credentials.isValid()) {
return ErrorCode::InternalError;
}
ErrorCode errorCode = ErrorCode::NoError; ErrorCode errorCode = ErrorCode::NoError;
errorCode = updateClients(serverIndex, container); errorCode = updateClients(serverId, container);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }
@@ -778,7 +815,7 @@ ErrorCode UsersController::revokeClient(int serverIndex, const ContainerConfig &
switch (container) switch (container)
{ {
case DockerContainer::OpenVpn: { case DockerContainer::OpenVpn: {
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, &sshSession, m_clientsTable); errorCode = revokeOpenVpn(row, container, credentials, &sshSession, m_clientsTable);
break; break;
} }
case DockerContainer::WireGuard: case DockerContainer::WireGuard:
@@ -797,7 +834,7 @@ ErrorCode UsersController::revokeClient(int serverIndex, const ContainerConfig &
} }
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
emit adminConfigRevoked(serverIndex, container); emit adminConfigRevoked(serverId, container);
emit clientRevoked(row); emit clientRevoked(row);
emit clientsUpdated(m_clientsTable); emit clientsUpdated(m_clientsTable);
} }
@@ -37,21 +37,21 @@ signals:
void clientAdded(const QJsonObject &client); void clientAdded(const QJsonObject &client);
void clientRenamed(int row, const QString &newName); void clientRenamed(int row, const QString &newName);
void clientRevoked(int row); void clientRevoked(int row);
void adminConfigRevoked(int serverIndex, DockerContainer container); void adminConfigRevoked(const QString &serverId, DockerContainer container);
public slots: public slots:
ErrorCode updateClients(int serverIndex, const DockerContainer container); ErrorCode updateClients(const QString &serverId, const DockerContainer container);
ErrorCode appendClient(int serverIndex, const QString &clientId, const QString &clientName, const DockerContainer container); ErrorCode appendClient(const QString &serverId, const QString &clientId, const QString &clientName, const DockerContainer container);
ErrorCode renameClient(int serverIndex, const int row, const QString &userName, const DockerContainer container, bool addTimeStamp = false); ErrorCode renameClient(const QString &serverId, const int row, const QString &userName, const DockerContainer container, bool addTimeStamp = false);
ErrorCode revokeClient(int serverIndex, const int index, const DockerContainer container); ErrorCode revokeClient(const QString &serverId, const int index, const DockerContainer container);
ErrorCode revokeClient(int serverIndex, const ContainerConfig &containerConfig, const DockerContainer container); ErrorCode revokeClient(const QString &serverId, const ContainerConfig &containerConfig, const DockerContainer container);
private: private:
bool isClientExists(const QString &clientId, const QJsonArray &clientsTable); bool isClientExists(const QString &clientId, const QJsonArray &clientsTable);
int clientIndexById(const QString &clientId, const QJsonArray &clientsTable); int clientIndexById(const QString &clientId, const QJsonArray &clientsTable);
void migration(const QByteArray &clientsTableString, QJsonArray &clientsTable); void migration(const QByteArray &clientsTableString, QJsonArray &clientsTable);
ErrorCode revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials, const int serverIndex, ErrorCode revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials,
SshSession* sshSession, QJsonArray &clientsTable); SshSession* sshSession, QJsonArray &clientsTable);
ErrorCode revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials, ErrorCode revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials,
SshSession* sshSession, QJsonArray &clientsTable); SshSession* sshSession, QJsonArray &clientsTable);
@@ -73,4 +73,3 @@ private:
}; };
#endif // USERSCONTROLLER_H #endif // USERSCONTROLLER_H
+349 -140
View File
@@ -1,81 +1,268 @@
#include "serversController.h" #include "serversController.h"
#include "core/utils/networkUtilities.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/api/apiEnums.h"
#include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h"
#include "core/utils/protocolEnum.h" #include "core/utils/protocolEnum.h"
#include "core/protocols/protocolUtils.h" #include "core/protocols/protocolUtils.h"
#include "core/utils/constants/configKeys.h" #include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h"
#include "core/models/serverConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/models/serverDescription.h"
#if defined(Q_OS_IOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
#include <AmneziaVPN-Swift.h> #include <AmneziaVPN-Swift.h>
#endif #endif
ServersController::ServersController(SecureServersRepository* serversRepository, ServersController::ServersController(SecureServersRepository *serversRepository,
SecureAppSettingsRepository* appSettingsRepository, SecureAppSettingsRepository *appSettingsRepository, QObject *parent)
QObject *parent)
: QObject(parent), m_serversRepository(serversRepository), m_appSettingsRepository(appSettingsRepository) : QObject(parent), m_serversRepository(serversRepository), m_appSettingsRepository(appSettingsRepository)
{ {
recomputeGatewayStacks(); ensureDefaultServerValid();
} }
void ServersController::addServer(const ServerConfig &server) void ServersController::ensureDefaultServerValid()
{ {
m_serversRepository->addServer(server); if (!getServersCount()) {
} return;
}
void ServersController::editServer(int index, const ServerConfig &server)
{ const QString defaultId = getDefaultServerId();
m_serversRepository->editServer(index, server); if (!defaultId.isEmpty() && indexOfServerId(defaultId) >= 0) {
} return;
}
void ServersController::removeServer(int index)
{ const QString firstId = getServerId(0);
m_serversRepository->removeServer(index); if (!firstId.isEmpty()) {
} setDefaultServer(firstId);
void ServersController::setDefaultServerIndex(int index)
{
m_serversRepository->setDefaultServer(index);
}
void ServersController::setDefaultContainer(int serverIndex, DockerContainer container)
{
m_serversRepository->setDefaultContainer(serverIndex, container);
}
void ServersController::updateContainerConfig(int serverIndex, DockerContainer container, const ContainerConfig &config)
{
m_serversRepository->setContainerConfig(serverIndex, container, config);
}
void ServersController::clearCachedProfile(int serverIndex, DockerContainer container)
{
m_serversRepository->clearLastConnectionConfig(serverIndex, container);
}
QJsonArray ServersController::getServersArray() const
{
QJsonArray result;
QVector<ServerConfig> servers = m_serversRepository->servers();
for (const ServerConfig& server : servers) {
result.append(server.toJson());
} }
return result;
} }
QVector<ServerConfig> ServersController::getServers() const bool ServersController::renameServer(const QString &serverId, const QString &name)
{ {
return m_serversRepository->servers(); const serverConfigUtils::ConfigType kind = m_serversRepository->serverKind(serverId);
switch (kind) {
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
if (!cfg.has_value()) return false;
cfg->description = name;
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
return true;
}
case serverConfigUtils::ConfigType::SelfHostedUser: {
auto cfg = m_serversRepository->selfHostedUserConfig(serverId);
if (!cfg.has_value()) return false;
cfg->description = name;
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
return true;
}
case serverConfigUtils::ConfigType::Native: {
auto cfg = m_serversRepository->nativeConfig(serverId);
if (!cfg.has_value()) return false;
cfg->description = name;
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
return true;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
case serverConfigUtils::ConfigType::AmneziaFreeV3:
case serverConfigUtils::ConfigType::ExternalPremium: {
auto cfg = m_serversRepository->apiV2Config(serverId);
if (!cfg.has_value()) return false;
cfg->name = name;
cfg->nameOverriddenByUser = true;
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
return true;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
case serverConfigUtils::ConfigType::AmneziaFreeV2:
case serverConfigUtils::ConfigType::Invalid:
default:
return false;
}
} }
ContainerConfig ServersController::getContainerConfig(int serverIndex, DockerContainer container) const void ServersController::removeServer(const QString &serverId)
{ {
return m_serversRepository->containerConfig(serverIndex, container); m_serversRepository->removeServer(serverId);
}
void ServersController::setDefaultServer(const QString &serverId)
{
m_serversRepository->setDefaultServer(serverId);
}
void ServersController::setDefaultContainer(const QString &serverId, DockerContainer container)
{
const serverConfigUtils::ConfigType kind = m_serversRepository->serverKind(serverId);
switch (kind) {
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
if (!cfg.has_value()) return;
cfg->defaultContainer = container;
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
return;
}
case serverConfigUtils::ConfigType::SelfHostedUser: {
auto cfg = m_serversRepository->selfHostedUserConfig(serverId);
if (!cfg.has_value()) return;
cfg->defaultContainer = container;
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
return;
}
case serverConfigUtils::ConfigType::Native: {
auto cfg = m_serversRepository->nativeConfig(serverId);
if (!cfg.has_value()) return;
cfg->defaultContainer = container;
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
return;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
case serverConfigUtils::ConfigType::AmneziaFreeV3:
case serverConfigUtils::ConfigType::ExternalPremium: {
auto cfg = m_serversRepository->apiV2Config(serverId);
if (!cfg.has_value()) return;
cfg->defaultContainer = container;
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
return;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
case serverConfigUtils::ConfigType::AmneziaFreeV2:
case serverConfigUtils::ConfigType::Invalid:
default:
return;
}
}
QVector<ServerDescription> ServersController::buildServerDescriptions(bool isAmneziaDnsEnabled) const
{
QVector<ServerDescription> out;
const QVector<QString> ids = m_serversRepository->orderedServerIds();
out.reserve(ids.size());
for (const QString &id : ids) {
ServerDescription d;
using Kind = serverConfigUtils::ConfigType;
const Kind kind = m_serversRepository->serverKind(id);
switch (kind) {
case Kind::SelfHostedAdmin: {
const auto cfg = m_serversRepository->selfHostedAdminConfig(id);
if (!cfg) {
continue;
}
d = buildServerDescription(*cfg, isAmneziaDnsEnabled);
break;
}
case Kind::SelfHostedUser: {
const auto cfg = m_serversRepository->selfHostedUserConfig(id);
if (!cfg) {
continue;
}
d = buildServerDescription(*cfg, isAmneziaDnsEnabled);
break;
}
case Kind::Native: {
const auto cfg = m_serversRepository->nativeConfig(id);
if (!cfg) {
continue;
}
d = buildServerDescription(*cfg, isAmneziaDnsEnabled);
break;
}
case Kind::AmneziaPremiumV2:
case Kind::AmneziaFreeV3:
case Kind::ExternalPremium: {
const auto cfg = m_serversRepository->apiV2Config(id);
if (!cfg) {
continue;
}
d = buildServerDescription(*cfg, isAmneziaDnsEnabled);
break;
}
case Kind::AmneziaPremiumV1:
case Kind::AmneziaFreeV2: {
const auto cfg = m_serversRepository->legacyApiConfig(id);
if (!cfg) {
continue;
}
d = buildServerDescription(*cfg, isAmneziaDnsEnabled);
break;
}
case Kind::Invalid:
default:
continue;
}
d.serverId = id;
out.append(d);
}
return out;
}
QMap<DockerContainer, ContainerConfig> ServersController::getServerContainersMap(const QString &serverId) const
{
switch (m_serversRepository->serverKind(serverId)) {
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
const auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
return cfg.has_value() ? cfg->containers : QMap<DockerContainer, ContainerConfig>{};
}
case serverConfigUtils::ConfigType::SelfHostedUser: {
const auto cfg = m_serversRepository->selfHostedUserConfig(serverId);
return cfg.has_value() ? cfg->containers : QMap<DockerContainer, ContainerConfig>{};
}
case serverConfigUtils::ConfigType::Native: {
const auto cfg = m_serversRepository->nativeConfig(serverId);
return cfg.has_value() ? cfg->containers : QMap<DockerContainer, ContainerConfig>{};
}
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
case serverConfigUtils::ConfigType::AmneziaFreeV3:
case serverConfigUtils::ConfigType::ExternalPremium: {
const auto cfg = m_serversRepository->apiV2Config(serverId);
return cfg.has_value() ? cfg->containers : QMap<DockerContainer, ContainerConfig>{};
}
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
case serverConfigUtils::ConfigType::AmneziaFreeV2: {
const auto cfg = m_serversRepository->legacyApiConfig(serverId);
return cfg.has_value() ? cfg->containers : QMap<DockerContainer, ContainerConfig>{};
}
case serverConfigUtils::ConfigType::Invalid:
default:
return {};
}
}
DockerContainer ServersController::getDefaultContainer(const QString &serverId) const
{
switch (m_serversRepository->serverKind(serverId)) {
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
const auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
return cfg.has_value() ? cfg->defaultContainer : DockerContainer::None;
}
case serverConfigUtils::ConfigType::SelfHostedUser: {
const auto cfg = m_serversRepository->selfHostedUserConfig(serverId);
return cfg.has_value() ? cfg->defaultContainer : DockerContainer::None;
}
case serverConfigUtils::ConfigType::Native: {
const auto cfg = m_serversRepository->nativeConfig(serverId);
return cfg.has_value() ? cfg->defaultContainer : DockerContainer::None;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
case serverConfigUtils::ConfigType::AmneziaFreeV3:
case serverConfigUtils::ConfigType::ExternalPremium: {
const auto cfg = m_serversRepository->apiV2Config(serverId);
return cfg.has_value() ? cfg->defaultContainer : DockerContainer::None;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
case serverConfigUtils::ConfigType::AmneziaFreeV2: {
const auto cfg = m_serversRepository->legacyApiConfig(serverId);
return cfg.has_value() ? cfg->defaultContainer : DockerContainer::None;
}
case serverConfigUtils::ConfigType::Invalid:
default:
return DockerContainer::None;
}
}
ContainerConfig ServersController::getContainerConfig(const QString &serverId, DockerContainer container) const
{
return getServerContainersMap(serverId).value(container);
} }
int ServersController::getDefaultServerIndex() const int ServersController::getDefaultServerIndex() const
@@ -83,114 +270,131 @@ int ServersController::getDefaultServerIndex() const
return m_serversRepository->defaultServerIndex(); return m_serversRepository->defaultServerIndex();
} }
QString ServersController::getDefaultServerId() const
{
return m_serversRepository->defaultServerId();
}
int ServersController::getServersCount() const int ServersController::getServersCount() const
{ {
return m_serversRepository->serversCount(); return m_serversRepository->serversCount();
} }
ServerConfig ServersController::getServerConfig(int serverIndex) const QString ServersController::getServerId(int serverIndex) const
{ {
return m_serversRepository->server(serverIndex); return m_serversRepository->serverIdAt(serverIndex);
} }
ServerCredentials ServersController::getServerCredentials(int serverIndex) const int ServersController::indexOfServerId(const QString &serverId) const
{ {
return m_serversRepository->serverCredentials(serverIndex); return m_serversRepository->indexOfServerId(serverId);
} }
QPair<QString, QString> ServersController::getDnsPair(int serverIndex, bool isAmneziaDnsEnabled) const QString ServersController::notificationDisplayName(const QString &serverId) const
{ {
ServerConfig serverConfig = m_serversRepository->server(serverIndex); if (serverId.isEmpty()) {
return serverConfig.getDnsPair(isAmneziaDnsEnabled, return {};
m_appSettingsRepository->primaryDns(), }
m_appSettingsRepository->secondaryDns());
}
ServersController::GatewayStacksData ServersController::gatewayStacks() const using Kind = serverConfigUtils::ConfigType;
{ switch (m_serversRepository->serverKind(serverId)) {
return m_gatewayStacks; case Kind::SelfHostedAdmin: {
} if (const auto cfg = m_serversRepository->selfHostedAdminConfig(serverId)) {
if (!cfg->displayName.isEmpty()) {
void ServersController::recomputeGatewayStacks() return cfg->displayName;
{
GatewayStacksData computed;
bool hasNewTags = false;
QVector<ServerConfig> servers = m_serversRepository->servers();
for (const ServerConfig& serverConfig : servers) {
if (serverConfig.isApiV2()) {
const ApiV2ServerConfig* apiV2 = serverConfig.as<ApiV2ServerConfig>();
if (!apiV2) continue;
const QString userCountryCode = apiV2->apiConfig.userCountryCode;
const QString serviceType = apiV2->serviceType();
if (!userCountryCode.isEmpty()) {
if (!m_gatewayStacks.userCountryCodes.contains(userCountryCode)) {
hasNewTags = true;
}
computed.userCountryCodes.insert(userCountryCode);
}
if (!serviceType.isEmpty()) {
if (!m_gatewayStacks.serviceTypes.contains(serviceType)) {
hasNewTags = true;
}
computed.serviceTypes.insert(serviceType);
} }
} }
break;
} }
case Kind::SelfHostedUser: {
m_gatewayStacks = std::move(computed); if (const auto cfg = m_serversRepository->selfHostedUserConfig(serverId)) {
if (hasNewTags) { if (!cfg->displayName.isEmpty()) {
emit gatewayStacksExpanded(); return cfg->displayName;
}
}
bool ServersController::GatewayStacksData::operator==(const GatewayStacksData &other) const
{
return userCountryCodes == other.userCountryCodes && serviceTypes == other.serviceTypes;
}
QJsonObject ServersController::GatewayStacksData::toJson() const
{
QJsonObject json;
QJsonArray userCountryCodesArray;
for (const QString &code : userCountryCodes) {
userCountryCodesArray.append(code);
}
json[apiDefs::key::userCountryCode] = userCountryCodesArray;
QJsonArray serviceTypesArray;
for (const QString &type : serviceTypes) {
serviceTypesArray.append(type);
}
json[apiDefs::key::serviceType] = serviceTypesArray;
return json;
}
bool ServersController::isServerFromApiAlreadyExists(const QString &userCountryCode, const QString &serviceType, const QString &serviceProtocol) const
{
QVector<ServerConfig> servers = m_serversRepository->servers();
for (const ServerConfig& serverConfig : servers) {
if (serverConfig.isApiV2()) {
const ApiV2ServerConfig* apiV2 = serverConfig.as<ApiV2ServerConfig>();
if (!apiV2) return false;
if (apiV2->apiConfig.userCountryCode == userCountryCode
&& apiV2->serviceType() == serviceType
&& apiV2->serviceProtocol() == serviceProtocol) {
return true;
} }
} }
break;
}
case Kind::Native: {
if (const auto cfg = m_serversRepository->nativeConfig(serverId)) {
if (!cfg->displayName.isEmpty()) {
return cfg->displayName;
}
}
break;
}
case Kind::AmneziaPremiumV2:
case Kind::AmneziaFreeV3:
case Kind::ExternalPremium: {
if (const auto cfg = m_serversRepository->apiV2Config(serverId)) {
if (!cfg->displayName.isEmpty()) {
return cfg->displayName;
}
}
break;
}
case Kind::AmneziaPremiumV1:
case Kind::AmneziaFreeV2: {
if (const auto cfg = m_serversRepository->legacyApiConfig(serverId)) {
if (!cfg->displayName.isEmpty()) {
return cfg->displayName;
}
}
break;
}
default:
break;
}
const int idx = indexOfServerId(serverId);
if (idx >= 0) {
return QString::number(idx + 1);
}
return serverId;
}
std::optional<ApiV2ServerConfig> ServersController::apiV2Config(const QString &serverId) const
{
return m_serversRepository->apiV2Config(serverId);
}
std::optional<SelfHostedAdminServerConfig> ServersController::selfHostedAdminConfig(const QString &serverId) const
{
return m_serversRepository->selfHostedAdminConfig(serverId);
}
ServerCredentials ServersController::getServerCredentials(const QString &serverId) const
{
const auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
if (cfg.has_value()) {
const ServerCredentials creds = cfg->credentials();
if (creds.isValid()) {
return creds;
}
}
return ServerCredentials {};
}
bool ServersController::isServerFromApiAlreadyExists(const QString &userCountryCode, const QString &serviceType,
const QString &serviceProtocol) const
{
const QVector<QString> ids = m_serversRepository->orderedServerIds();
for (const QString &id : ids) {
const auto apiV2 = m_serversRepository->apiV2Config(id);
if (!apiV2.has_value()) {
continue;
}
if (apiV2->apiConfig.userCountryCode == userCountryCode && apiV2->serviceType() == serviceType
&& apiV2->serviceProtocol() == serviceProtocol) {
return true;
}
} }
return false; return false;
} }
bool ServersController::hasInstalledContainers(int serverIndex) const bool ServersController::hasInstalledContainers(const QString &serverId) const
{ {
ServerConfig serverConfig = m_serversRepository->server(serverIndex); const QMap<DockerContainer, ContainerConfig> containers = getServerContainersMap(serverId);
QMap<DockerContainer, ContainerConfig> containers = serverConfig.containers();
for (auto it = containers.begin(); it != containers.end(); ++it) { for (auto it = containers.begin(); it != containers.end(); ++it) {
DockerContainer container = it.key(); DockerContainer container = it.key();
if (ContainerUtils::containerService(container) == ServiceType::Vpn) { if (ContainerUtils::containerService(container) == ServiceType::Vpn) {
@@ -203,3 +407,8 @@ bool ServersController::hasInstalledContainers(int serverIndex) const
return false; return false;
} }
bool ServersController::isLegacyApiV1Server(const QString &serverId) const
{
return !serverId.isEmpty()
&& serverConfigUtils::isLegacyApiSubscription(m_serversRepository->serverKind(serverId));
}
+23 -45
View File
@@ -1,11 +1,11 @@
#ifndef SERVERSCONTROLLER_H #ifndef SERVERSCONTROLLER_H
#define SERVERSCONTROLLER_H #define SERVERSCONTROLLER_H
#include <optional>
#include <QObject> #include <QObject>
#include <QJsonObject>
#include <QJsonArray>
#include <QSet>
#include <QVector> #include <QVector>
#include <QMap>
#include <QPair> #include <QPair>
@@ -17,34 +17,18 @@
#include "core/utils/commonStructs.h" #include "core/utils/commonStructs.h"
#include "core/repositories/secureServersRepository.h" #include "core/repositories/secureServersRepository.h"
#include "core/repositories/secureAppSettingsRepository.h" #include "core/repositories/secureAppSettingsRepository.h"
#include "core/models/serverConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/models/serverDescription.h"
class SshSession; class SshSession;
class InstallController; class InstallController;
using namespace amnezia; using namespace amnezia;
/**
* @brief Core business logic controller for server operations
*
* This controller contains pure business logic for managing servers.
*/
class ServersController : public QObject class ServersController : public QObject
{ {
Q_OBJECT Q_OBJECT
public:
struct GatewayStacksData
{
QSet<QString> userCountryCodes;
QSet<QString> serviceTypes;
bool isEmpty() const { return userCountryCodes.isEmpty() && serviceTypes.isEmpty(); }
bool operator==(const GatewayStacksData &other) const;
QJsonObject toJson() const;
};
public: public:
explicit ServersController(SecureServersRepository* serversRepository, explicit ServersController(SecureServersRepository* serversRepository,
SecureAppSettingsRepository* appSettingsRepository = nullptr, SecureAppSettingsRepository* appSettingsRepository = nullptr,
@@ -52,44 +36,38 @@ public:
~ServersController() = default; ~ServersController() = default;
// Server management // Server management
void addServer(const ServerConfig &server); bool renameServer(const QString &serverId, const QString &name);
void editServer(int index, const ServerConfig &server); void removeServer(const QString &serverId);
void removeServer(int index); void setDefaultServer(const QString &serverId);
void setDefaultServerIndex(int index);
// Container management // Container management
void setDefaultContainer(int serverIndex, DockerContainer container); void setDefaultContainer(const QString &serverId, DockerContainer container);
void updateContainerConfig(int serverIndex, DockerContainer container, const ContainerConfig &config);
// Cache management
void clearCachedProfile(int serverIndex, DockerContainer container);
// Getters // Getters
QJsonArray getServersArray() const; QVector<ServerDescription> buildServerDescriptions(bool isAmneziaDnsEnabled) const;
QVector<ServerConfig> getServers() const;
int getDefaultServerIndex() const; int getDefaultServerIndex() const;
QString getDefaultServerId() const;
int getServersCount() const; int getServersCount() const;
ServerConfig getServerConfig(int serverIndex) const; QString getServerId(int serverIndex) const;
ServerCredentials getServerCredentials(int serverIndex) const; int indexOfServerId(const QString &serverId) const;
ContainerConfig getContainerConfig(int serverIndex, DockerContainer container) const; QString notificationDisplayName(const QString &serverId) const;
QPair<QString, QString> getDnsPair(int serverIndex, bool isAmneziaDnsEnabled) const; std::optional<ApiV2ServerConfig> apiV2Config(const QString &serverId) const;
std::optional<SelfHostedAdminServerConfig> selfHostedAdminConfig(const QString &serverId) const;
GatewayStacksData gatewayStacks() const; ServerCredentials getServerCredentials(const QString &serverId) const;
QMap<DockerContainer, ContainerConfig> getServerContainersMap(const QString &serverId) const;
DockerContainer getDefaultContainer(const QString &serverId) const;
ContainerConfig getContainerConfig(const QString &serverId, DockerContainer container) const;
// Validation // Validation
bool isServerFromApiAlreadyExists(const QString &userCountryCode, const QString &serviceType, const QString &serviceProtocol) const; bool isServerFromApiAlreadyExists(const QString &userCountryCode, const QString &serviceType, const QString &serviceProtocol) const;
bool hasInstalledContainers(int serverIndex) const; bool hasInstalledContainers(const QString &serverId) const;
bool isLegacyApiV1Server(const QString &serverId) const;
signals:
void gatewayStacksExpanded();
public slots:
void recomputeGatewayStacks();
private: private:
void ensureDefaultServerValid();
SecureServersRepository* m_serversRepository; SecureServersRepository* m_serversRepository;
SecureAppSettingsRepository* m_appSettingsRepository; SecureAppSettingsRepository* m_appSettingsRepository;
GatewayStacksData m_gatewayStacks;
}; };
#endif // SERVERSCONTROLLER_H #endif // SERVERSCONTROLLER_H
@@ -179,12 +179,9 @@ QString SettingsController::getAppVersion() const
void SettingsController::clearSettings() void SettingsController::clearSettings()
{ {
int serverCount = m_serversRepository->serversCount();
m_appSettingsRepository->clearSettings(); m_appSettingsRepository->clearSettings();
m_serversRepository->setServersArray(QJsonArray()); m_serversRepository->clearServers();
m_serversRepository->setDefaultServer(0);
emit siteSplitTunnelingRouteModeChanged(RouteMode::VpnOnlyForwardSites); emit siteSplitTunnelingRouteModeChanged(RouteMode::VpnOnlyForwardSites);
emit siteSplitTunnelingToggled(false); emit siteSplitTunnelingToggled(false);
+1 -1
View File
@@ -6,7 +6,7 @@
#include <QString> #include <QString>
#include <QDateTime> #include <QDateTime>
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
@@ -1,140 +0,0 @@
#include "apiV1ServerConfig.h"
#include <QJsonArray>
#include <QJsonDocument>
#include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h"
#include "core/utils/protocolEnum.h"
#include "core/protocols/protocolUtils.h"
#include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h"
#include "core/utils/api/apiUtils.h"
namespace amnezia
{
using namespace ContainerEnumNS;
bool ApiV1ServerConfig::isPremium() const
{
constexpr QLatin1String premiumV1Endpoint(PREM_V1_ENDPOINT);
return apiEndpoint.contains(premiumV1Endpoint);
}
bool ApiV1ServerConfig::isFree() const
{
constexpr QLatin1String freeV2Endpoint(FREE_V2_ENDPOINT);
return apiEndpoint.contains(freeV2Endpoint);
}
QString ApiV1ServerConfig::vpnKey() const
{
QJsonObject json = toJson();
return apiUtils::getPremiumV1VpnKey(json);
}
bool ApiV1ServerConfig::hasContainers() const
{
return !containers.isEmpty();
}
ContainerConfig ApiV1ServerConfig::containerConfig(DockerContainer container) const
{
if (!containers.contains(container)) {
return ContainerConfig{};
}
return containers.value(container);
}
QJsonObject ApiV1ServerConfig::toJson() const
{
QJsonObject obj;
if (!name.isEmpty()) {
obj[configKey::name] = name;
}
if (!description.isEmpty()) {
obj[configKey::description] = description;
}
if (!protocol.isEmpty()) {
obj[apiDefs::key::protocol] = protocol;
}
if (!apiEndpoint.isEmpty()) {
obj[apiDefs::key::apiEndpoint] = apiEndpoint;
}
if (!apiKey.isEmpty()) {
obj[apiDefs::key::apiKey] = apiKey;
}
obj[configKey::configVersion] = configVersion;
if (!hostName.isEmpty()) {
obj[configKey::hostName] = hostName;
}
QJsonArray containersArray;
for (auto it = containers.begin(); it != containers.end(); ++it) {
QJsonObject containerObj = it.value().toJson();
containersArray.append(containerObj);
}
if (!containersArray.isEmpty()) {
obj[configKey::containers] = containersArray;
}
if (defaultContainer != DockerContainer::None) {
obj[configKey::defaultContainer] = ContainerUtils::containerToString(defaultContainer);
}
if (!dns1.isEmpty()) {
obj[configKey::dns1] = dns1;
}
if (!dns2.isEmpty()) {
obj[configKey::dns2] = dns2;
}
if (crc > 0) {
obj[configKey::crc] = crc;
}
return obj;
}
ApiV1ServerConfig ApiV1ServerConfig::fromJson(const QJsonObject& json)
{
ApiV1ServerConfig config;
config.name = json.value(configKey::name).toString();
config.description = json.value(configKey::description).toString();
config.protocol = json.value(apiDefs::key::protocol).toString();
config.apiEndpoint = json.value(apiDefs::key::apiEndpoint).toString();
config.apiKey = json.value(apiDefs::key::apiKey).toString();
config.configVersion = json.value(configKey::configVersion).toInt(1);
config.hostName = json.value(configKey::hostName).toString();
QJsonArray containersArray = json.value(configKey::containers).toArray();
for (const QJsonValue& val : containersArray) {
QJsonObject containerObj = val.toObject();
ContainerConfig containerConfig = ContainerConfig::fromJson(containerObj);
QString containerStr = containerObj.value(configKey::container).toString();
DockerContainer container = ContainerUtils::containerFromString(containerStr);
config.containers.insert(container, containerConfig);
}
QString defaultContainerStr = json.value(configKey::defaultContainer).toString();
config.defaultContainer = ContainerUtils::containerFromString(defaultContainerStr);
config.dns1 = json.value(configKey::dns1).toString();
config.dns2 = json.value(configKey::dns2).toString();
config.crc = json.value(configKey::crc).toInt(0);
return config;
}
} // namespace amnezia
@@ -1,47 +0,0 @@
#ifndef APIV1SERVERCONFIG_H
#define APIV1SERVERCONFIG_H
#include <QJsonObject>
#include <QMap>
#include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h"
#include "core/models/containerConfig.h"
#include "core/utils/api/apiEnums.h"
#include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h"
namespace amnezia
{
using namespace ContainerEnumNS;
struct ApiV1ServerConfig {
QString description;
QString hostName;
QMap<DockerContainer, ContainerConfig> containers;
DockerContainer defaultContainer;
QString dns1;
QString dns2;
QString name;
QString protocol;
QString apiEndpoint;
QString apiKey;
int crc;
int configVersion;
bool isPremium() const;
bool isFree() const;
QString vpnKey() const;
bool hasContainers() const;
ContainerConfig containerConfig(DockerContainer container) const;
QJsonObject toJson() const;
static ApiV1ServerConfig fromJson(const QJsonObject& json);
};
} // namespace amnezia
#endif // APIV1SERVERCONFIG_H
@@ -80,6 +80,9 @@ QJsonObject ApiV2ServerConfig::toJson() const
if (!description.isEmpty()) { if (!description.isEmpty()) {
obj[configKey::description] = description; obj[configKey::description] = description;
} }
if (!displayName.isEmpty()) {
obj[configKey::displayName] = displayName;
}
obj[configKey::configVersion] = configVersion; obj[configKey::configVersion] = configVersion;
@@ -131,6 +134,7 @@ ApiV2ServerConfig ApiV2ServerConfig::fromJson(const QJsonObject& json)
config.name = json.value(configKey::name).toString(); config.name = json.value(configKey::name).toString();
config.nameOverriddenByUser = json.value(configKey::nameOverriddenByUser).toBool(false); config.nameOverriddenByUser = json.value(configKey::nameOverriddenByUser).toBool(false);
config.description = json.value(configKey::description).toString(); config.description = json.value(configKey::description).toString();
config.displayName = json.value(configKey::displayName).toString();
config.configVersion = json.value(configKey::configVersion).toInt(2); config.configVersion = json.value(configKey::configVersion).toInt(2);
config.hostName = json.value(configKey::hostName).toString(); config.hostName = json.value(configKey::hostName).toString();
@@ -163,6 +167,10 @@ ApiV2ServerConfig ApiV2ServerConfig::fromJson(const QJsonObject& json)
config.authData = AuthData::fromJson(authDataObj); config.authData = AuthData::fromJson(authDataObj);
} }
if (config.displayName.isEmpty()) {
config.displayName = config.name.isEmpty() ? config.description : config.name;
}
return config; return config;
} }
+2 -1
View File
@@ -10,7 +10,7 @@
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/models/api/apiConfig.h" #include "core/models/api/apiConfig.h"
#include "core/models/api/authData.h" #include "core/models/api/authData.h"
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
@@ -21,6 +21,7 @@ using namespace ContainerEnumNS;
struct ApiV2ServerConfig { struct ApiV2ServerConfig {
QString description; QString description;
QString displayName;
QString hostName; QString hostName;
QMap<DockerContainer, ContainerConfig> containers; QMap<DockerContainer, ContainerConfig> containers;
DockerContainer defaultContainer; DockerContainer defaultContainer;
+1 -1
View File
@@ -4,7 +4,7 @@
#include <QJsonObject> #include <QJsonObject>
#include <QString> #include <QString>
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
@@ -0,0 +1,43 @@
#include "legacyApiServerConfig.h"
#include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/configKeys.h"
namespace amnezia
{
bool LegacyApiServerConfig::hasContainers() const
{
return !containers.isEmpty();
}
ContainerConfig LegacyApiServerConfig::containerConfig(DockerContainer container) const
{
if (!containers.contains(container)) {
return ContainerConfig{};
}
return containers.value(container);
}
LegacyApiServerConfig LegacyApiServerConfig::fromJson(const QJsonObject &json)
{
LegacyApiServerConfig config;
config.name = json.value(configKey::name).toString();
config.description = json.value(configKey::description).toString();
config.displayName = json.value(configKey::displayName).toString();
config.hostName = json.value(configKey::hostName).toString();
config.crc = json.value(configKey::crc).toInt(0);
config.configVersion = json.value(configKey::configVersion).toInt(1);
config.apiEndpoint = json.value(apiDefs::key::apiEndpoint).toString();
if (config.displayName.isEmpty()) {
config.displayName = config.name.isEmpty() ? config.description : config.name;
}
return config;
}
} // namespace amnezia
@@ -0,0 +1,38 @@
#ifndef LEGACYAPISERVERCONFIG_H
#define LEGACYAPISERVERCONFIG_H
#include <QJsonObject>
#include <QMap>
#include "core/utils/containerEnum.h"
#include "core/utils/protocolEnum.h"
#include "core/models/containerConfig.h"
namespace amnezia
{
using namespace ContainerEnumNS;
struct LegacyApiServerConfig {
QString description;
QString displayName;
QString hostName;
QMap<DockerContainer, ContainerConfig> containers;
DockerContainer defaultContainer = DockerContainer::None;
QString dns1;
QString dns2;
QString name;
int crc = 0;
int configVersion = 0;
QString apiEndpoint;
bool hasContainers() const;
ContainerConfig containerConfig(DockerContainer container) const;
static LegacyApiServerConfig fromJson(const QJsonObject &json);
};
} // namespace amnezia
#endif // LEGACYAPISERVERCONFIG_H
@@ -35,6 +35,9 @@ QJsonObject NativeServerConfig::toJson() const
if (!description.isEmpty()) { if (!description.isEmpty()) {
obj[configKey::description] = this->description; obj[configKey::description] = this->description;
} }
if (!displayName.isEmpty()) {
obj[configKey::displayName] = displayName;
}
if (!hostName.isEmpty()) { if (!hostName.isEmpty()) {
obj[configKey::hostName] = hostName; obj[configKey::hostName] = hostName;
} }
@@ -67,6 +70,7 @@ NativeServerConfig NativeServerConfig::fromJson(const QJsonObject& json)
NativeServerConfig config; NativeServerConfig config;
config.description = json.value(configKey::description).toString(); config.description = json.value(configKey::description).toString();
config.displayName = json.value(configKey::displayName).toString();
config.hostName = json.value(configKey::hostName).toString(); config.hostName = json.value(configKey::hostName).toString();
QJsonArray containersArray = json.value(configKey::containers).toArray(); QJsonArray containersArray = json.value(configKey::containers).toArray();
@@ -86,6 +90,10 @@ NativeServerConfig NativeServerConfig::fromJson(const QJsonObject& json)
config.dns1 = json.value(configKey::dns1).toString(); config.dns1 = json.value(configKey::dns1).toString();
config.dns2 = json.value(configKey::dns2).toString(); config.dns2 = json.value(configKey::dns2).toString();
if (config.displayName.isEmpty()) {
config.displayName = config.description.isEmpty() ? config.hostName : config.description;
}
return config; return config;
} }
@@ -16,6 +16,7 @@ using namespace ContainerEnumNS;
struct NativeServerConfig { struct NativeServerConfig {
QString description; QString description;
QString displayName;
QString hostName; QString hostName;
QMap<DockerContainer, ContainerConfig> containers; QMap<DockerContainer, ContainerConfig> containers;
DockerContainer defaultContainer; DockerContainer defaultContainer;
@@ -0,0 +1,170 @@
#include "selfHostedAdminServerConfig.h"
#include <QJsonArray>
#include "core/protocols/protocolUtils.h"
#include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h"
#include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h"
#include "core/utils/networkUtilities.h"
namespace amnezia
{
using namespace ContainerEnumNS;
bool SelfHostedAdminServerConfig::hasCredentials() const
{
return !userName.isEmpty() && !password.isEmpty() && port > 0;
}
bool SelfHostedAdminServerConfig::isReadOnly() const
{
return !hasCredentials();
}
ServerCredentials SelfHostedAdminServerConfig::credentials() const
{
ServerCredentials creds;
creds.hostName = hostName;
creds.userName = userName;
creds.secretData = password;
creds.port = port;
return creds;
}
bool SelfHostedAdminServerConfig::hasContainers() const
{
return !containers.isEmpty();
}
ContainerConfig SelfHostedAdminServerConfig::containerConfig(DockerContainer container) const
{
if (!containers.contains(container)) {
return ContainerConfig{};
}
return containers.value(container);
}
void SelfHostedAdminServerConfig::updateContainerConfig(DockerContainer container, const ContainerConfig &config)
{
containers[container] = config;
}
void SelfHostedAdminServerConfig::clearCachedClientProfile(DockerContainer container)
{
if (ContainerUtils::containerService(container) == ServiceType::Other) {
return;
}
ContainerConfig cleared = containerConfig(container);
cleared.protocolConfig.clearClientConfig();
containers[container] = cleared;
}
QPair<QString, QString> SelfHostedAdminServerConfig::getDnsPair(bool isAmneziaDnsEnabled, const QString &primaryDns,
const QString &secondaryDns) const
{
QString d1 = dns1;
QString d2 = dns2;
const bool dnsOnServer = containers.contains(DockerContainer::Dns);
if (d1.isEmpty() || !NetworkUtilities::checkIPv4Format(d1)) {
d1 = (isAmneziaDnsEnabled && dnsOnServer) ? protocols::dns::amneziaDnsIp : primaryDns;
}
if (d2.isEmpty() || !NetworkUtilities::checkIPv4Format(d2)) {
d2 = secondaryDns;
}
return { d1, d2 };
}
QJsonObject SelfHostedAdminServerConfig::toJson() const
{
QJsonObject obj;
if (!description.isEmpty()) {
obj[configKey::description] = this->description;
}
if (!displayName.isEmpty()) {
obj[configKey::displayName] = displayName;
}
if (!hostName.isEmpty()) {
obj[configKey::hostName] = hostName;
}
QJsonArray containersArray;
for (auto it = containers.begin(); it != containers.end(); ++it) {
QJsonObject containerObj = it.value().toJson();
containersArray.append(containerObj);
}
if (!containersArray.isEmpty()) {
obj[configKey::containers] = containersArray;
}
if (defaultContainer != DockerContainer::None) {
obj[configKey::defaultContainer] = ContainerUtils::containerToString(defaultContainer);
}
if (!dns1.isEmpty()) {
obj[configKey::dns1] = dns1;
}
if (!dns2.isEmpty()) {
obj[configKey::dns2] = dns2;
}
if (!userName.isEmpty()) {
obj[configKey::userName] = userName;
}
if (!password.isEmpty()) {
obj[configKey::password] = password;
}
if (port > 0) {
obj[configKey::port] = port;
}
return obj;
}
SelfHostedAdminServerConfig SelfHostedAdminServerConfig::fromJson(const QJsonObject &json)
{
SelfHostedAdminServerConfig config;
config.description = json.value(configKey::description).toString();
config.displayName = json.value(configKey::displayName).toString();
config.hostName = json.value(configKey::hostName).toString();
QJsonArray containersArray = json.value(configKey::containers).toArray();
for (const QJsonValue &val : containersArray) {
QJsonObject containerObj = val.toObject();
ContainerConfig cc = ContainerConfig::fromJson(containerObj);
QString containerStr = containerObj.value(configKey::container).toString();
DockerContainer container = ContainerUtils::containerFromString(containerStr);
config.containers.insert(container, cc);
}
QString defaultContainerStr = json.value(configKey::defaultContainer).toString();
config.defaultContainer = ContainerUtils::containerFromString(defaultContainerStr);
config.dns1 = json.value(configKey::dns1).toString();
config.dns2 = json.value(configKey::dns2).toString();
config.userName = json.value(configKey::userName).toString();
config.password = json.value(configKey::password).toString();
if (json.contains(configKey::port)) {
config.port = json.value(configKey::port).toInt();
} else {
config.port = 0;
}
if (config.displayName.isEmpty()) {
config.displayName = config.description.isEmpty() ? config.hostName : config.description;
}
return config;
}
} // namespace amnezia
@@ -0,0 +1,53 @@
#ifndef SELFHOSTEDADMINSERVERCONFIG_H
#define SELFHOSTEDADMINSERVERCONFIG_H
#include <QJsonObject>
#include <QMap>
#include <QPair>
#include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h"
#include "core/models/containerConfig.h"
#include "core/utils/errorCodes.h"
#include "core/utils/routeModes.h"
#include "core/utils/commonStructs.h"
namespace amnezia
{
using namespace ContainerEnumNS;
struct SelfHostedAdminServerConfig {
QString description;
QString displayName;
QString hostName;
QMap<DockerContainer, ContainerConfig> containers;
DockerContainer defaultContainer;
QString dns1;
QString dns2;
QString userName;
QString password;
int port = 0;
bool hasCredentials() const;
bool isReadOnly() const;
ServerCredentials credentials() const;
bool hasContainers() const;
ContainerConfig containerConfig(DockerContainer container) const;
void updateContainerConfig(DockerContainer container, const ContainerConfig &config);
void clearCachedClientProfile(DockerContainer container);
QPair<QString, QString> getDnsPair(bool isAmneziaDnsEnabled, const QString &primaryDns,
const QString &secondaryDns) const;
QJsonObject toJson() const;
static SelfHostedAdminServerConfig fromJson(const QJsonObject &json);
};
} // namespace amnezia
#endif // SELFHOSTEDADMINSERVERCONFIG_H
@@ -1,53 +1,40 @@
#include "selfHostedServerConfig.h" #include "selfHostedUserServerConfig.h"
#include <QJsonArray> #include <QJsonArray>
#include <QJsonDocument>
#include <stdexcept>
#include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h"
#include "core/utils/protocolEnum.h"
#include "core/protocols/protocolUtils.h" #include "core/protocols/protocolUtils.h"
#include "core/utils/constants/configKeys.h" #include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h" #include "core/utils/constants/protocolConstants.h"
#include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h"
namespace amnezia namespace amnezia
{ {
using namespace ContainerEnumNS; using namespace ContainerEnumNS;
bool SelfHostedServerConfig::hasCredentials() const bool SelfHostedUserServerConfig::hasCredentials() const
{ {
return userName.has_value() && password.has_value() && port.has_value(); return false;
} }
bool SelfHostedServerConfig::isReadOnly() const bool SelfHostedUserServerConfig::isReadOnly() const
{ {
return !hasCredentials(); return true;
} }
std::optional<ServerCredentials> SelfHostedServerConfig::credentials() const std::optional<ServerCredentials> SelfHostedUserServerConfig::credentials() const
{ {
if (!hasCredentials()) { return std::nullopt;
return std::nullopt;
}
ServerCredentials creds;
creds.hostName = hostName;
creds.userName = userName.value();
creds.secretData = password.value();
creds.port = port.value();
return creds;
} }
bool SelfHostedServerConfig::hasContainers() const bool SelfHostedUserServerConfig::hasContainers() const
{ {
return !containers.isEmpty(); return !containers.isEmpty();
} }
ContainerConfig SelfHostedServerConfig::containerConfig(DockerContainer container) const ContainerConfig SelfHostedUserServerConfig::containerConfig(DockerContainer container) const
{ {
if (!containers.contains(container)) { if (!containers.contains(container)) {
return ContainerConfig{}; return ContainerConfig{};
@@ -55,17 +42,20 @@ ContainerConfig SelfHostedServerConfig::containerConfig(DockerContainer containe
return containers.value(container); return containers.value(container);
} }
QJsonObject SelfHostedServerConfig::toJson() const QJsonObject SelfHostedUserServerConfig::toJson() const
{ {
QJsonObject obj; QJsonObject obj;
if (!description.isEmpty()) { if (!description.isEmpty()) {
obj[configKey::description] = this->description; obj[configKey::description] = this->description;
} }
if (!displayName.isEmpty()) {
obj[configKey::displayName] = displayName;
}
if (!hostName.isEmpty()) { if (!hostName.isEmpty()) {
obj[configKey::hostName] = hostName; obj[configKey::hostName] = hostName;
} }
QJsonArray containersArray; QJsonArray containersArray;
for (auto it = containers.begin(); it != containers.end(); ++it) { for (auto it = containers.begin(); it != containers.end(); ++it) {
QJsonObject containerObj = it.value().toJson(); QJsonObject containerObj = it.value().toJson();
@@ -74,67 +64,51 @@ QJsonObject SelfHostedServerConfig::toJson() const
if (!containersArray.isEmpty()) { if (!containersArray.isEmpty()) {
obj[configKey::containers] = containersArray; obj[configKey::containers] = containersArray;
} }
if (defaultContainer != DockerContainer::None) { if (defaultContainer != DockerContainer::None) {
obj[configKey::defaultContainer] = ContainerUtils::containerToString(defaultContainer); obj[configKey::defaultContainer] = ContainerUtils::containerToString(defaultContainer);
} }
if (!dns1.isEmpty()) { if (!dns1.isEmpty()) {
obj[configKey::dns1] = dns1; obj[configKey::dns1] = dns1;
} }
if (!dns2.isEmpty()) { if (!dns2.isEmpty()) {
obj[configKey::dns2] = dns2; obj[configKey::dns2] = dns2;
} }
if (userName.has_value()) {
obj[configKey::userName] = userName.value();
}
if (password.has_value()) {
obj[configKey::password] = password.value();
}
if (port.has_value()) {
obj[configKey::port] = port.value();
}
return obj; return obj;
} }
SelfHostedServerConfig SelfHostedServerConfig::fromJson(const QJsonObject& json) SelfHostedUserServerConfig SelfHostedUserServerConfig::fromJson(const QJsonObject &json)
{ {
SelfHostedServerConfig config; SelfHostedUserServerConfig config;
config.description = json.value(configKey::description).toString(); config.description = json.value(configKey::description).toString();
config.displayName = json.value(configKey::displayName).toString();
config.hostName = json.value(configKey::hostName).toString(); config.hostName = json.value(configKey::hostName).toString();
QJsonArray containersArray = json.value(configKey::containers).toArray(); QJsonArray containersArray = json.value(configKey::containers).toArray();
for (const QJsonValue& val : containersArray) { for (const QJsonValue &val : containersArray) {
QJsonObject containerObj = val.toObject(); QJsonObject containerObj = val.toObject();
ContainerConfig containerConfig = ContainerConfig::fromJson(containerObj); ContainerConfig cc = ContainerConfig::fromJson(containerObj);
QString containerStr = containerObj.value(configKey::container).toString(); QString containerStr = containerObj.value(configKey::container).toString();
DockerContainer container = ContainerUtils::containerFromString(containerStr); DockerContainer container = ContainerUtils::containerFromString(containerStr);
config.containers.insert(container, containerConfig); config.containers.insert(container, cc);
} }
QString defaultContainerStr = json.value(configKey::defaultContainer).toString(); QString defaultContainerStr = json.value(configKey::defaultContainer).toString();
config.defaultContainer = ContainerUtils::containerFromString(defaultContainerStr); config.defaultContainer = ContainerUtils::containerFromString(defaultContainerStr);
config.dns1 = json.value(configKey::dns1).toString(); config.dns1 = json.value(configKey::dns1).toString();
config.dns2 = json.value(configKey::dns2).toString(); config.dns2 = json.value(configKey::dns2).toString();
if (json.contains(configKey::userName)) { if (config.displayName.isEmpty()) {
config.userName = json.value(configKey::userName).toString(); config.displayName = config.description.isEmpty() ? config.hostName : config.description;
} }
if (json.contains(configKey::password)) {
config.password = json.value(configKey::password).toString();
}
if (json.contains(configKey::port)) {
config.port = json.value(configKey::port).toInt();
}
return config; return config;
} }
} // namespace amnezia } // namespace amnezia
@@ -1,5 +1,5 @@
#ifndef SELFHOSTEDSERVERCONFIG_H #ifndef SELFHOSTEDUSERSERVERCONFIG_H
#define SELFHOSTEDSERVERCONFIG_H #define SELFHOSTEDUSERSERVERCONFIG_H
#include <QJsonObject> #include <QJsonObject>
#include <QMap> #include <QMap>
@@ -9,8 +9,6 @@
#include "core/utils/containers/containerUtils.h" #include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h" #include "core/utils/protocolEnum.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/utils/errorCodes.h"
#include "core/utils/routeModes.h"
#include "core/utils/commonStructs.h" #include "core/utils/commonStructs.h"
namespace amnezia namespace amnezia
@@ -18,28 +16,24 @@ namespace amnezia
using namespace ContainerEnumNS; using namespace ContainerEnumNS;
struct SelfHostedServerConfig { struct SelfHostedUserServerConfig {
QString description; QString description;
QString displayName;
QString hostName; QString hostName;
QMap<DockerContainer, ContainerConfig> containers; QMap<DockerContainer, ContainerConfig> containers;
DockerContainer defaultContainer; DockerContainer defaultContainer;
QString dns1; QString dns1;
QString dns2; QString dns2;
std::optional<QString> userName;
std::optional<QString> password;
std::optional<int> port;
bool hasCredentials() const; bool hasCredentials() const;
bool isReadOnly() const; bool isReadOnly() const;
std::optional<ServerCredentials> credentials() const; std::optional<ServerCredentials> credentials() const;
bool hasContainers() const; bool hasContainers() const;
ContainerConfig containerConfig(DockerContainer container) const; ContainerConfig containerConfig(DockerContainer container) const;
QJsonObject toJson() const; QJsonObject toJson() const;
static SelfHostedServerConfig fromJson(const QJsonObject& json); static SelfHostedUserServerConfig fromJson(const QJsonObject &json);
}; };
} // namespace amnezia } // namespace amnezia
#endif // SELFHOSTEDSERVERCONFIG_H #endif // SELFHOSTEDUSERSERVERCONFIG_H
-234
View File
@@ -1,234 +0,0 @@
#include "serverConfig.h"
#include "core/utils/api/apiUtils.h"
#include "core/utils/networkUtilities.h"
#include "core/models/selfhosted/selfHostedServerConfig.h"
#include "core/models/selfhosted/nativeServerConfig.h"
#include "core/models/api/apiV1ServerConfig.h"
#include "core/models/api/apiV2ServerConfig.h"
#include "core/utils/protocolEnum.h"
#include "core/protocols/protocolUtils.h"
#include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h"
namespace amnezia
{
using namespace ContainerEnumNS;
QString ServerConfig::description() const
{
return std::visit([](const auto& v) { return v.description; }, data);
}
QString ServerConfig::hostName() const
{
return std::visit([](const auto& v) { return v.hostName; }, data);
}
QString ServerConfig::displayName() const
{
if (isApiV1()) {
const auto *apiV1 = as<ApiV1ServerConfig>();
return apiV1 ? apiV1->name : description();
}
if (isApiV2()) {
const auto *apiV2 = as<ApiV2ServerConfig>();
return apiV2 ? apiV2->name : description();
}
QString name = description();
return name.isEmpty() ? hostName() : name;
}
QMap<DockerContainer, ContainerConfig> ServerConfig::containers() const
{
return std::visit([](const auto& v) { return v.containers; }, data);
}
DockerContainer ServerConfig::defaultContainer() const
{
return std::visit([](const auto& v) { return v.defaultContainer; }, data);
}
QString ServerConfig::dns1() const
{
return std::visit([](const auto& v) { return v.dns1; }, data);
}
QString ServerConfig::dns2() const
{
return std::visit([](const auto& v) { return v.dns2; }, data);
}
bool ServerConfig::hasContainers() const
{
return std::visit([](const auto& v) { return v.hasContainers(); }, data);
}
ContainerConfig ServerConfig::containerConfig(DockerContainer container) const
{
return std::visit([container](const auto& v) { return v.containerConfig(container); }, data);
}
int ServerConfig::crc() const
{
return std::visit([](const auto& v) -> int {
using T = std::decay_t<decltype(v)>;
if constexpr (std::is_same_v<T, ApiV1ServerConfig> ||
std::is_same_v<T, ApiV2ServerConfig>) {
return v.crc;
}
return 0;
}, data);
}
int ServerConfig::configVersion() const
{
return std::visit([](const auto& v) -> int {
using T = std::decay_t<decltype(v)>;
if constexpr (std::is_same_v<T, ApiV1ServerConfig>) {
return apiDefs::ConfigSource::Telegram;
} else if constexpr (std::is_same_v<T, ApiV2ServerConfig>) {
return apiDefs::ConfigSource::AmneziaGateway;
}
return 0; // SelfHostedServerConfig or NativeServerConfig
}, data);
}
bool ServerConfig::isSelfHosted() const
{
return std::holds_alternative<SelfHostedServerConfig>(data);
}
bool ServerConfig::isNative() const
{
return std::holds_alternative<NativeServerConfig>(data);
}
bool ServerConfig::isApiV1() const
{
return std::holds_alternative<ApiV1ServerConfig>(data);
}
bool ServerConfig::isApiV2() const
{
return std::holds_alternative<ApiV2ServerConfig>(data);
}
bool ServerConfig::isApiConfig() const
{
return isApiV1() || isApiV2();
}
QJsonObject ServerConfig::toJson() const
{
return std::visit([](const auto& v) { return v.toJson(); }, data);
}
ServerConfig ServerConfig::fromJson(const QJsonObject& json)
{
apiDefs::ConfigType configType = apiUtils::getConfigType(json);
switch (configType) {
case apiDefs::ConfigType::SelfHosted: {
bool hasThirdPartyConfig = false;
QJsonArray containersArray = json.value(configKey::containers).toArray();
for (const QJsonValue& val : containersArray) {
QJsonObject containerObj = val.toObject();
for (auto it = containerObj.begin(); it != containerObj.end(); ++it) {
QString key = it.key();
if (key != configKey::container) {
QJsonObject protocolObj = it.value().toObject();
if (protocolObj.contains(configKey::isThirdPartyConfig) &&
protocolObj.value(configKey::isThirdPartyConfig).toBool()) {
hasThirdPartyConfig = true;
break;
}
}
}
if (hasThirdPartyConfig) {
break;
}
}
if (hasThirdPartyConfig) {
return ServerConfig{NativeServerConfig::fromJson(json)};
} else {
return ServerConfig{SelfHostedServerConfig::fromJson(json)};
}
}
case apiDefs::ConfigType::AmneziaPremiumV1:
case apiDefs::ConfigType::AmneziaFreeV2:
return ServerConfig{ApiV1ServerConfig::fromJson(json)};
case apiDefs::ConfigType::AmneziaPremiumV2:
case apiDefs::ConfigType::AmneziaFreeV3:
case apiDefs::ConfigType::ExternalPremium:
return ServerConfig{ApiV2ServerConfig::fromJson(json)};
default: {
// Check if any container has isThirdPartyConfig
bool hasThirdPartyConfig = false;
QJsonArray containersArray = json.value(configKey::containers).toArray();
for (const QJsonValue& val : containersArray) {
QJsonObject containerObj = val.toObject();
// Check all protocol keys in the container object
for (auto it = containerObj.begin(); it != containerObj.end(); ++it) {
QString key = it.key();
if (key != configKey::container) {
QJsonObject protocolObj = it.value().toObject();
if (protocolObj.contains(configKey::isThirdPartyConfig) &&
protocolObj.value(configKey::isThirdPartyConfig).toBool()) {
hasThirdPartyConfig = true;
break;
}
}
}
if (hasThirdPartyConfig) {
break;
}
}
if (hasThirdPartyConfig) {
return ServerConfig{NativeServerConfig::fromJson(json)};
} else {
return ServerConfig{SelfHostedServerConfig::fromJson(json)};
}
}
}
}
QPair<QString, QString> ServerConfig::getDnsPair(bool isAmneziaDnsEnabled,
const QString &primaryDns,
const QString &secondaryDns) const
{
QPair<QString, QString> dns;
QMap<DockerContainer, ContainerConfig> serverContainers = containers();
bool isDnsContainerInstalled = false;
for (auto it = serverContainers.begin(); it != serverContainers.end(); ++it) {
if (it.key() == DockerContainer::Dns) {
isDnsContainerInstalled = true;
break;
}
}
dns.first = dns1();
dns.second = dns2();
if (dns.first.isEmpty() || !NetworkUtilities::checkIPv4Format(dns.first)) {
if (isAmneziaDnsEnabled && isDnsContainerInstalled) {
dns.first = protocols::dns::amneziaDnsIp;
} else {
dns.first = primaryDns;
}
}
if (dns.second.isEmpty() || !NetworkUtilities::checkIPv4Format(dns.second)) {
dns.second = secondaryDns;
}
return dns;
}
} // namespace amnezia
-92
View File
@@ -1,92 +0,0 @@
#ifndef SERVERCONFIG_H
#define SERVERCONFIG_H
#include <variant>
#include <QJsonObject>
#include <QMap>
#include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h"
#include "core/models/selfhosted/selfHostedServerConfig.h"
#include "core/models/selfhosted/nativeServerConfig.h"
#include "core/models/api/apiV1ServerConfig.h"
#include "core/models/api/apiV2ServerConfig.h"
#include "core/models/containerConfig.h"
namespace amnezia
{
using namespace ContainerEnumNS;
struct ServerConfig {
using Variant = std::variant<
SelfHostedServerConfig,
NativeServerConfig,
ApiV1ServerConfig,
ApiV2ServerConfig
>;
Variant data;
ServerConfig() = default;
ServerConfig(const Variant& v) : data(v) {}
ServerConfig(Variant&& v) : data(std::move(v)) {}
template<typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<std::remove_reference_t<T>>, ServerConfig>::value>>
ServerConfig(const T& v) : data(v) {}
template<typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<std::remove_reference_t<T>>, ServerConfig>::value>>
ServerConfig(T&& v) : data(std::forward<T>(v)) {}
QString description() const;
QString hostName() const;
QString displayName() const;
QMap<DockerContainer, ContainerConfig> containers() const;
DockerContainer defaultContainer() const;
QString dns1() const;
QString dns2() const;
bool hasContainers() const;
ContainerConfig containerConfig(DockerContainer container) const;
int crc() const;
int configVersion() const;
bool isSelfHosted() const;
bool isNative() const;
bool isApiV1() const;
bool isApiV2() const;
bool isApiConfig() const;
template<typename T>
T* as() {
return std::get_if<T>(&data);
}
template<typename T>
const T* as() const {
return std::get_if<T>(&data);
}
QJsonObject toJson() const;
static ServerConfig fromJson(const QJsonObject& json);
template<typename Visitor>
auto visit(Visitor&& visitor) {
return std::visit(std::forward<Visitor>(visitor), data);
}
template<typename Visitor>
auto visit(Visitor&& visitor) const {
return std::visit(std::forward<Visitor>(visitor), data);
}
QPair<QString, QString> getDnsPair(bool isAmneziaDnsEnabled,
const QString &primaryDns,
const QString &secondaryDns) const;
};
} // namespace amnezia
#endif // SERVERCONFIG_H
+187
View File
@@ -0,0 +1,187 @@
#include "serverDescription.h"
#include <QMap>
#include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h"
#include "core/utils/constants/protocolConstants.h"
#include "core/utils/api/apiUtils.h"
#include "core/utils/containers/containerUtils.h"
#include "core/protocols/protocolUtils.h"
#include "core/models/protocols/awgProtocolConfig.h"
using namespace amnezia;
namespace
{
bool computeHasInstalledVpnContainers(const QMap<DockerContainer, ContainerConfig> &containers)
{
for (auto it = containers.begin(); it != containers.end(); ++it) {
const DockerContainer container = it.key();
if (ContainerUtils::containerService(container) == ServiceType::Vpn || container == DockerContainer::SSXray) {
return true;
}
}
return false;
}
template <typename T>
ServerDescription buildBaseDescription(const T &server)
{
ServerDescription row;
row.hostName = server.hostName;
row.defaultContainer = server.defaultContainer;
row.primaryDnsIsAmnezia = (server.dns1 == protocols::dns::amneziaDnsIp);
row.hasInstalledVpnContainers = computeHasInstalledVpnContainers(server.containers);
return row;
}
QString getBaseDescription(const QMap<DockerContainer, ContainerConfig> &containers,
bool isAmneziaDnsEnabled,
bool hasWriteAccess,
bool primaryDnsIsAmnezia)
{
QString description;
if (hasWriteAccess) {
const bool isDnsInstalled = containers.contains(DockerContainer::Dns);
if (isAmneziaDnsEnabled && isDnsInstalled) {
description += QStringLiteral("Amnezia DNS | ");
}
} else if (primaryDnsIsAmnezia) {
description += QStringLiteral("Amnezia DNS | ");
}
return description;
}
QString getProtocolName(DockerContainer defaultContainer, const QMap<DockerContainer, ContainerConfig> &containers)
{
QString containerName = ContainerUtils::containerHumanNames().value(defaultContainer);
QString protocolVersion;
if (ContainerUtils::isAwgContainer(defaultContainer)) {
const auto it = containers.constFind(defaultContainer);
if (it != containers.cend()) {
if (const AwgProtocolConfig *awg = it->getAwgProtocolConfig()) {
protocolVersion = ProtocolUtils::getProtocolVersionString(awg->toJson());
if (defaultContainer == DockerContainer::Awg && !awg->serverConfig.isThirdPartyConfig) {
containerName = QStringLiteral("AmneziaWG Legacy");
}
}
}
}
return containerName + protocolVersion + QStringLiteral(" | ");
}
} // namespace
namespace amnezia
{
ServerDescription buildServerDescription(const SelfHostedAdminServerConfig &server, bool isAmneziaDnsEnabled)
{
ServerDescription row = buildBaseDescription(server);
row.selfHostedSshCredentials.hostName = server.hostName;
row.selfHostedSshCredentials.userName = server.userName;
row.selfHostedSshCredentials.secretData = server.password;
row.selfHostedSshCredentials.port = server.port > 0 ? server.port : 22;
row.hasWriteAccess = !row.selfHostedSshCredentials.userName.isEmpty()
&& !row.selfHostedSshCredentials.secretData.isEmpty();
row.serverName = server.displayName;
row.baseDescription = getBaseDescription(server.containers, isAmneziaDnsEnabled, row.hasWriteAccess, row.primaryDnsIsAmnezia);
const QString protocolName = getProtocolName(server.defaultContainer, server.containers);
row.expandedServerDescription = row.baseDescription + row.hostName;
row.collapsedServerDescription = row.baseDescription + protocolName + row.hostName;
return row;
}
ServerDescription buildServerDescription(const SelfHostedUserServerConfig &server, bool isAmneziaDnsEnabled)
{
ServerDescription row = buildBaseDescription(server);
row.selfHostedSshCredentials.hostName = server.hostName;
row.selfHostedSshCredentials.port = 22;
row.hasWriteAccess = false;
row.serverName = server.displayName;
row.baseDescription = getBaseDescription(server.containers, isAmneziaDnsEnabled, row.hasWriteAccess, row.primaryDnsIsAmnezia);
const QString protocolName = getProtocolName(server.defaultContainer, server.containers);
row.expandedServerDescription = row.baseDescription + row.hostName;
row.collapsedServerDescription = row.baseDescription + protocolName + row.hostName;
return row;
}
ServerDescription buildServerDescription(const NativeServerConfig &server, bool isAmneziaDnsEnabled)
{
ServerDescription row = buildBaseDescription(server);
row.hasWriteAccess = false;
row.serverName = server.displayName;
row.baseDescription = getBaseDescription(server.containers, isAmneziaDnsEnabled, row.hasWriteAccess, row.primaryDnsIsAmnezia);
const QString protocolName = getProtocolName(server.defaultContainer, server.containers);
row.expandedServerDescription = row.baseDescription + row.hostName;
row.collapsedServerDescription = row.baseDescription + protocolName + row.hostName;
return row;
}
ServerDescription buildServerDescription(const LegacyApiServerConfig &server, bool /*isAmneziaDnsEnabled*/)
{
ServerDescription row = buildBaseDescription(server);
row.configVersion = serverConfigUtils::ConfigSource::Telegram;
row.isApiV1 = true;
row.isServerFromGatewayApi = false;
row.hasWriteAccess = false;
row.serverName = server.displayName;
row.baseDescription = server.description;
const QString fullDescriptionForCollapsed = row.baseDescription;
row.collapsedServerDescription = fullDescriptionForCollapsed;
row.expandedServerDescription = fullDescriptionForCollapsed;
return row;
}
ServerDescription buildServerDescription(const ApiV2ServerConfig &server, bool /*isAmneziaDnsEnabled*/)
{
ServerDescription row = buildBaseDescription(server);
row.configVersion = serverConfigUtils::ConfigSource::AmneziaGateway;
row.isApiV2 = true;
row.isServerFromGatewayApi = true;
row.isPremium = server.isPremium() || server.isExternalPremium();
row.hasWriteAccess = false;
row.serverName = server.displayName;
row.baseDescription = server.apiConfig.serverCountryCode.isEmpty() ? server.description : server.apiConfig.serverCountryName;
row.isCountrySelectionAvailable = !server.apiConfig.availableCountries.isEmpty();
row.apiAvailableCountries = server.apiConfig.availableCountries;
row.apiServerCountryCode = server.apiConfig.serverCountryCode;
row.isAdVisible = server.apiConfig.serviceInfo.isAdVisible;
row.adHeader = server.apiConfig.serviceInfo.adHeader;
row.adDescription = server.apiConfig.serviceInfo.adDescription;
row.adEndpoint = server.apiConfig.serviceInfo.adEndpoint;
row.isRenewalAvailable = server.apiConfig.serviceInfo.isRenewalAvailable;
if (!server.apiConfig.isInAppPurchase) {
if (server.apiConfig.subscriptionExpiredByServer) {
row.isSubscriptionExpired = true;
} else if (!server.apiConfig.subscription.endDate.isEmpty()) {
row.isSubscriptionExpired = apiUtils::isSubscriptionExpired(server.apiConfig.subscription.endDate);
row.isSubscriptionExpiringSoon = apiUtils::isSubscriptionExpiringSoon(server.apiConfig.subscription.endDate);
}
}
const QString fullDescriptionForCollapsed = row.baseDescription;
row.collapsedServerDescription = fullDescriptionForCollapsed;
row.expandedServerDescription = fullDescriptionForCollapsed;
return row;
}
} // namespace amnezia
+64
View File
@@ -0,0 +1,64 @@
#ifndef SERVERDESCRIPTION_H
#define SERVERDESCRIPTION_H
#include <QString>
#include <QJsonArray>
#include "core/utils/containerEnum.h"
#include "core/utils/selfhosted/sshSession.h"
#include "core/models/selfhosted/selfHostedAdminServerConfig.h"
#include "core/models/selfhosted/selfHostedUserServerConfig.h"
#include "core/models/selfhosted/nativeServerConfig.h"
#include "core/models/api/legacyApiServerConfig.h"
#include "core/models/api/apiV2ServerConfig.h"
namespace amnezia
{
struct ServerDescription
{
QString serverId;
QString serverName;
QString baseDescription;
QString hostName;
int configVersion = 0;
ServerCredentials selfHostedSshCredentials;
bool hasWriteAccess = false;
bool primaryDnsIsAmnezia = false;
DockerContainer defaultContainer = DockerContainer::None;
bool hasInstalledVpnContainers = false;
bool isApiV1 = false;
bool isApiV2 = false;
bool isServerFromGatewayApi = false;
bool isPremium = false;
bool isCountrySelectionAvailable = false;
QJsonArray apiAvailableCountries;
QString apiServerCountryCode;
bool isAdVisible = false;
QString adHeader;
QString adDescription;
QString adEndpoint;
bool isRenewalAvailable = false;
bool isSubscriptionExpired = false;
bool isSubscriptionExpiringSoon = false;
QString collapsedServerDescription;
QString expandedServerDescription;
};
ServerDescription buildServerDescription(const SelfHostedAdminServerConfig &server, bool isAmneziaDnsEnabled);
ServerDescription buildServerDescription(const SelfHostedUserServerConfig &server, bool isAmneziaDnsEnabled);
ServerDescription buildServerDescription(const NativeServerConfig &server, bool isAmneziaDnsEnabled);
ServerDescription buildServerDescription(const LegacyApiServerConfig &server, bool isAmneziaDnsEnabled);
ServerDescription buildServerDescription(const ApiV2ServerConfig &server, bool isAmneziaDnsEnabled);
} // namespace amnezia
#endif
@@ -2,15 +2,16 @@
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonArray> #include <QJsonArray>
#include <QJsonObject>
#include <QUuid> #include <QUuid>
#include "core/utils/errorCodes.h" #include "core/utils/errorCodes.h"
#include "core/utils/routeModes.h" #include "core/utils/routeModes.h"
#include "core/utils/commonStructs.h" #include "core/utils/commonStructs.h"
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
#include "core/models/serverConfig.h" #include "core/utils/constants/configKeys.h"
#include "core/utils/networkUtilities.h" #include "core/utils/networkUtilities.h"
using namespace amnezia; using namespace amnezia;
@@ -1,26 +1,44 @@
#include "secureServersRepository.h" #include "secureServersRepository.h"
#include <QJsonDocument>
#include <QJsonArray> #include <QJsonArray>
#include <QJsonDocument>
#include <QJsonValue>
#include <QUuid>
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h"
#include "core/models/serverConfig.h"
#include "core/models/containerConfig.h"
#include "core/utils/protocolEnum.h"
#include "core/protocols/protocolUtils.h"
#include "core/utils/constants/configKeys.h" #include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h"
SecureServersRepository::SecureServersRepository(SecureQSettings* settings, QObject *parent) using namespace amnezia;
namespace {
QString readStorageServerId(const QJsonObject &json)
{
return json.value(QString(configKey::storageServerId)).toString().trimmed();
}
QJsonObject withoutStorageServerId(const QJsonObject &json)
{
QJsonObject o = json;
o.remove(QString(configKey::storageServerId));
return o;
}
QJsonObject embedStorageServerId(const QString &serverId, const QJsonObject &payloadSansId)
{
QJsonObject o = payloadSansId;
o.insert(QString(configKey::storageServerId), serverId);
return o;
}
} // namespace
SecureServersRepository::SecureServersRepository(SecureQSettings *settings, QObject *parent)
: QObject(parent), m_settings(settings) : QObject(parent), m_settings(settings)
{ {
QJsonArray arr = QJsonDocument::fromJson(value("Servers/serversList").toByteArray()).array(); loadFromStorage();
for (const QJsonValue &val : arr) { persistDefaultServerFields();
m_servers.append(ServerConfig::fromJson(val.toObject()));
}
m_defaultServerIndex = value("Servers/defaultServerIndex", 0).toInt();
} }
QVariant SecureServersRepository::value(const QString &key, const QVariant &defaultValue) const QVariant SecureServersRepository::value(const QString &key, const QVariant &defaultValue) const
@@ -33,216 +51,322 @@ void SecureServersRepository::setValue(const QString &key, const QVariant &value
m_settings->setValue(key, value); m_settings->setValue(key, value);
} }
void SecureServersRepository::clearServerStateMaps()
{
m_serverJsonById.clear();
m_orderedServerIds.clear();
}
QString SecureServersRepository::normalizedOrGeneratedServerId(const QString &candidateId) const
{
const QString trimmed = candidateId.trimmed();
if (!trimmed.isEmpty() && !m_serverJsonById.contains(trimmed)) {
return trimmed;
}
return QUuid::createUuid().toString(QUuid::WithoutBraces);
}
void SecureServersRepository::updateDefaultServerFromStorage()
{
const QString storedDefaultId = value(QStringLiteral("Servers/defaultServerId"), QString()).toString();
if (!storedDefaultId.isEmpty() && m_serverJsonById.contains(storedDefaultId)) {
m_defaultServerId = storedDefaultId;
return;
}
const int storedDefaultIndex = value("Servers/defaultServerIndex", 0).toInt();
if (storedDefaultIndex >= 0 && storedDefaultIndex < m_orderedServerIds.size()) {
m_defaultServerId = m_orderedServerIds.at(storedDefaultIndex);
return;
}
if (!m_orderedServerIds.isEmpty()) {
m_defaultServerId = m_orderedServerIds.first();
return;
}
m_defaultServerId.clear();
}
void SecureServersRepository::persistDefaultServerFields()
{
if (m_orderedServerIds.isEmpty()) {
m_defaultServerId.clear();
} else if (!m_orderedServerIds.contains(m_defaultServerId)) {
m_defaultServerId = m_orderedServerIds.first();
}
setValue("Servers/defaultServerId", m_defaultServerId);
}
void SecureServersRepository::loadFromStorage()
{
clearServerStateMaps();
const QJsonArray serversArray =
QJsonDocument::fromJson(value(QStringLiteral("Servers/serversList"), QByteArray()).toByteArray())
.array();
for (int i = 0; i < serversArray.size(); ++i) {
const QJsonObject json = serversArray.at(i).toObject();
const QString candidateId = readStorageServerId(json);
const QString serverId = normalizedOrGeneratedServerId(candidateId);
const QJsonObject strippedJson = withoutStorageServerId(json);
const serverConfigUtils::ConfigType kind = serverConfigUtils::configTypeFromJson(strippedJson);
if (m_serverJsonById.contains(serverId) || kind == serverConfigUtils::ConfigType::Invalid) {
continue;
}
m_serverJsonById.insert(serverId, embedStorageServerId(serverId, strippedJson));
m_orderedServerIds.append(serverId);
}
updateDefaultServerFromStorage();
}
void SecureServersRepository::syncToStorage() void SecureServersRepository::syncToStorage()
{ {
QJsonArray arr; QJsonArray serversArray;
for (const ServerConfig &cfg : m_servers) {
arr.append(cfg.toJson()); for (const QString &serverId : m_orderedServerIds) {
if (!m_serverJsonById.contains(serverId)) {
continue;
}
serversArray.append(m_serverJsonById.value(serverId));
} }
setValue("Servers/serversList", QJsonDocument(arr).toJson());
setValue("Servers/serversList", QJsonDocument(serversArray).toJson());
persistDefaultServerFields();
} }
void SecureServersRepository::invalidateCache() void SecureServersRepository::invalidateCache()
{ {
m_servers.clear(); loadFromStorage();
QJsonArray arr = QJsonDocument::fromJson(value("Servers/serversList").toByteArray()).array();
for (const QJsonValue &val : arr) {
m_servers.append(ServerConfig::fromJson(val.toObject()));
}
m_defaultServerIndex = value("Servers/defaultServerIndex", 0).toInt();
} }
void SecureServersRepository::setServersArray(const QJsonArray &servers) void SecureServersRepository::clearServers()
{ {
m_servers.clear(); clearServerStateMaps();
for (const QJsonValue &val : servers) {
m_servers.append(ServerConfig::fromJson(val.toObject())); m_defaultServerId.clear();
}
syncToStorage(); syncToStorage();
} }
void SecureServersRepository::addServer(const ServerConfig &server) QString SecureServersRepository::addServer(const QString &serverId, const QJsonObject &serverJson, serverConfigUtils::ConfigType kind)
{ {
m_servers.append(server); const QString id = normalizedOrGeneratedServerId(serverId);
if (m_serverJsonById.contains(id) || kind == serverConfigUtils::ConfigType::Invalid) {
return id;
}
const QJsonObject strippedJson = withoutStorageServerId(serverJson);
if (serverConfigUtils::configTypeFromJson(strippedJson) != kind) {
return id;
}
m_serverJsonById.insert(id, embedStorageServerId(id, strippedJson));
m_orderedServerIds.append(id);
if (m_defaultServerId.isEmpty()) {
m_defaultServerId = id;
}
syncToStorage(); syncToStorage();
emit serverAdded(server); emit serverAdded(id);
return id;
} }
void SecureServersRepository::editServer(int index, const ServerConfig &server) void SecureServersRepository::editServer(const QString &serverId, const QJsonObject &serverJson, serverConfigUtils::ConfigType kind)
{ {
if (index < 0 || index >= m_servers.size()) { if (indexOfServerId(serverId) < 0 || kind == serverConfigUtils::ConfigType::Invalid) {
return; return;
} }
m_servers.replace(index, server); if (!m_serverJsonById.contains(serverId)) {
syncToStorage();
emit serverEdited(index, server);
}
void SecureServersRepository::removeServer(int index)
{
if (index < 0 || index >= m_servers.size()) {
return; return;
} }
int defaultIndex = m_defaultServerIndex;
m_servers.removeAt(index);
if (defaultIndex == index) { const QJsonObject oldJson = m_serverJsonById.value(serverId);
setDefaultServer(0); const serverConfigUtils::ConfigType oldKind = serverConfigUtils::configTypeFromJson(withoutStorageServerId(oldJson));
} else if (defaultIndex > index) {
setDefaultServer(defaultIndex - 1); m_serverJsonById.remove(serverId);
const QJsonObject strippedNew = withoutStorageServerId(serverJson);
if (serverConfigUtils::configTypeFromJson(strippedNew) != kind) {
const QJsonObject strippedOld = withoutStorageServerId(oldJson);
if (oldKind != serverConfigUtils::ConfigType::Invalid && serverConfigUtils::configTypeFromJson(strippedOld) == oldKind) {
m_serverJsonById.insert(serverId, embedStorageServerId(serverId, strippedOld));
}
return;
}
m_serverJsonById.insert(serverId, embedStorageServerId(serverId, strippedNew));
syncToStorage();
emit serverEdited(serverId);
}
void SecureServersRepository::removeServer(const QString &serverId)
{
const int removedIndex = indexOfServerId(serverId);
if (removedIndex < 0) {
return;
}
if (!m_serverJsonById.contains(serverId)) {
return;
} }
if (m_servers.isEmpty()) { const QString previousDefaultId = m_defaultServerId;
setDefaultServer(0); const int previousDefaultIndex = defaultServerIndex();
m_serverJsonById.remove(serverId);
m_orderedServerIds.removeAt(removedIndex);
if (m_orderedServerIds.isEmpty()) {
m_defaultServerId.clear();
} else if (m_defaultServerId == serverId) {
const int fallbackIndex = qMin(removedIndex, m_orderedServerIds.size() - 1);
m_defaultServerId = m_orderedServerIds.at(fallbackIndex);
} else if (!m_orderedServerIds.contains(m_defaultServerId)) {
m_defaultServerId = m_orderedServerIds.first();
}
const int newDefaultIndex = defaultServerIndex();
if (previousDefaultId != m_defaultServerId || previousDefaultIndex != newDefaultIndex) {
emit defaultServerChanged(m_defaultServerId);
} }
syncToStorage(); syncToStorage();
emit serverRemoved(index); emit serverRemoved(serverId, removedIndex);
} }
ServerConfig SecureServersRepository::server(int index) const serverConfigUtils::ConfigType SecureServersRepository::serverKind(const QString &serverId) const
{ {
if (index < 0 || index >= m_servers.size()) { const auto it = m_serverJsonById.constFind(serverId);
return SelfHostedServerConfig{}; if (it == m_serverJsonById.constEnd()) {
return serverConfigUtils::ConfigType::Invalid;
} }
return m_servers.at(index); return serverConfigUtils::configTypeFromJson(withoutStorageServerId(it.value()));
} }
QVector<ServerConfig> SecureServersRepository::servers() const std::optional<SelfHostedAdminServerConfig> SecureServersRepository::selfHostedAdminConfig(const QString &serverId) const
{ {
return m_servers; const auto it = m_serverJsonById.constFind(serverId);
if (it == m_serverJsonById.constEnd()) {
return std::nullopt;
}
const QJsonObject strippedJson = withoutStorageServerId(it.value());
if (serverConfigUtils::configTypeFromJson(strippedJson) != serverConfigUtils::ConfigType::SelfHostedAdmin) {
return std::nullopt;
}
return SelfHostedAdminServerConfig::fromJson(strippedJson);
}
std::optional<SelfHostedUserServerConfig> SecureServersRepository::selfHostedUserConfig(const QString &serverId) const
{
const auto it = m_serverJsonById.constFind(serverId);
if (it == m_serverJsonById.constEnd()) {
return std::nullopt;
}
const QJsonObject strippedJson = withoutStorageServerId(it.value());
if (serverConfigUtils::configTypeFromJson(strippedJson) != serverConfigUtils::ConfigType::SelfHostedUser) {
return std::nullopt;
}
return SelfHostedUserServerConfig::fromJson(strippedJson);
}
std::optional<NativeServerConfig> SecureServersRepository::nativeConfig(const QString &serverId) const
{
const auto it = m_serverJsonById.constFind(serverId);
if (it == m_serverJsonById.constEnd()) {
return std::nullopt;
}
const QJsonObject strippedJson = withoutStorageServerId(it.value());
if (serverConfigUtils::configTypeFromJson(strippedJson) != serverConfigUtils::ConfigType::Native) {
return std::nullopt;
}
return NativeServerConfig::fromJson(strippedJson);
}
std::optional<ApiV2ServerConfig> SecureServersRepository::apiV2Config(const QString &serverId) const
{
const auto it = m_serverJsonById.constFind(serverId);
if (it == m_serverJsonById.constEnd()) {
return std::nullopt;
}
const QJsonObject strippedJson = withoutStorageServerId(it.value());
if (!serverConfigUtils::isApiV2Subscription(serverConfigUtils::configTypeFromJson(strippedJson))) {
return std::nullopt;
}
return ApiV2ServerConfig::fromJson(strippedJson);
}
std::optional<LegacyApiServerConfig> SecureServersRepository::legacyApiConfig(const QString &serverId) const
{
const auto it = m_serverJsonById.constFind(serverId);
if (it == m_serverJsonById.constEnd()) {
return std::nullopt;
}
const QJsonObject strippedJson = withoutStorageServerId(it.value());
if (!serverConfigUtils::isLegacyApiSubscription(serverConfigUtils::configTypeFromJson(strippedJson))) {
return std::nullopt;
}
return LegacyApiServerConfig::fromJson(strippedJson);
} }
int SecureServersRepository::serversCount() const int SecureServersRepository::serversCount() const
{ {
return m_servers.size(); return m_orderedServerIds.size();
}
QString SecureServersRepository::serverIdAt(int index) const
{
if (index < 0 || index >= m_orderedServerIds.size()) {
return QString();
}
return m_orderedServerIds.at(index);
}
QVector<QString> SecureServersRepository::orderedServerIds() const
{
return m_orderedServerIds;
}
int SecureServersRepository::indexOfServerId(const QString &serverId) const
{
return m_orderedServerIds.indexOf(serverId);
} }
int SecureServersRepository::defaultServerIndex() const int SecureServersRepository::defaultServerIndex() const
{ {
return m_defaultServerIndex; if (m_orderedServerIds.isEmpty()) {
return 0;
}
const int idx = m_orderedServerIds.indexOf(m_defaultServerId);
return idx >= 0 ? idx : 0;
} }
void SecureServersRepository::setDefaultServer(int index) QString SecureServersRepository::defaultServerId() const
{ {
if (index < 0) { return m_defaultServerId;
}
void SecureServersRepository::setDefaultServer(const QString &serverId)
{
if (m_orderedServerIds.isEmpty()) {
return; return;
} }
if (m_servers.size() > 0 && index >= m_servers.size()) { if (!m_serverJsonById.contains(serverId)) {
return; return;
} }
if (m_servers.isEmpty() && index != 0) {
if (indexOfServerId(serverId) < 0) {
return; return;
} }
if (m_defaultServerIndex == index) {
if (m_defaultServerId == serverId) {
return; return;
} }
m_defaultServerIndex = index;
setValue("Servers/defaultServerIndex", index);
emit defaultServerChanged(index);
}
void SecureServersRepository::setDefaultContainer(int serverIndex, DockerContainer container) m_defaultServerId = serverId;
{ persistDefaultServerFields();
ServerConfig config = server(serverIndex); emit defaultServerChanged(m_defaultServerId);
config.visit([container](auto& arg) {
arg.defaultContainer = container;
});
editServer(serverIndex, config);
}
ContainerConfig SecureServersRepository::containerConfig(int serverIndex, DockerContainer container) const
{
ServerConfig config = server(serverIndex);
return config.containerConfig(container);
}
void SecureServersRepository::setContainerConfig(int serverIndex, DockerContainer container, const ContainerConfig &config)
{
ServerConfig serverConfig = server(serverIndex);
serverConfig.visit([container, &config](auto& arg) {
arg.containers[container] = config;
});
editServer(serverIndex, serverConfig);
}
void SecureServersRepository::clearLastConnectionConfig(int serverIndex, DockerContainer container)
{
ServerConfig serverConfig = server(serverIndex);
ContainerConfig containerCfg = serverConfig.containerConfig(container);
containerCfg.protocolConfig.clearClientConfig();
setContainerConfig(serverIndex, container, containerCfg);
}
ServerCredentials SecureServersRepository::serverCredentials(int index) const
{
ServerConfig config = server(index);
if (config.isSelfHosted()) {
const SelfHostedServerConfig* selfHosted = config.as<SelfHostedServerConfig>();
if (!selfHosted) return ServerCredentials();
auto creds = selfHosted->credentials();
if (creds.has_value()) {
return creds.value();
}
}
return ServerCredentials{};
}
bool SecureServersRepository::hasServerWithVpnKey(const QString &vpnKey) const
{
QString normalizedInput = vpnKey.trimmed();
if (normalizedInput.startsWith(QStringLiteral("vpn://"), Qt::CaseInsensitive)) {
normalizedInput = normalizedInput.mid(QStringLiteral("vpn://").size());
}
if (normalizedInput.isEmpty()) {
return false;
}
QVector<ServerConfig> serversList = servers();
for (const ServerConfig& serverConfig : serversList) {
if (serverConfig.isApiV1()) {
const ApiV1ServerConfig* apiV1 = serverConfig.as<ApiV1ServerConfig>();
if (!apiV1) continue;
QString storedKey = apiV1->vpnKey();
if (storedKey.isEmpty()) {
continue;
}
QString normalizedStored = storedKey.trimmed();
if (normalizedStored.startsWith(QStringLiteral("vpn://"), Qt::CaseInsensitive)) {
normalizedStored = normalizedStored.mid(QStringLiteral("vpn://").size());
}
if (normalizedInput == normalizedStored) {
return true;
}
} else if (serverConfig.isApiV2()) {
const ApiV2ServerConfig* apiV2 = serverConfig.as<ApiV2ServerConfig>();
if (!apiV2) continue;
QString storedKey = apiV2->vpnKey();
if (storedKey.isEmpty()) {
continue;
}
QString normalizedStored = storedKey.trimmed();
if (normalizedStored.startsWith(QStringLiteral("vpn://"), Qt::CaseInsensitive)) {
normalizedStored = normalizedStored.mid(QStringLiteral("vpn://").size());
}
if (normalizedInput == normalizedStored) {
return true;
}
}
}
return false;
}
bool SecureServersRepository::hasServerWithCrc(quint16 crc) const
{
for (const ServerConfig& serverConfig : m_servers) {
if (static_cast<quint16>(serverConfig.crc()) == crc) {
return true;
}
}
return false;
} }
@@ -1,14 +1,20 @@
#ifndef SECURESERVERSREPOSITORY_H #ifndef SECURESERVERSREPOSITORY_H
#define SECURESERVERSREPOSITORY_H #define SECURESERVERSREPOSITORY_H
#include <QHash>
#include <QJsonObject>
#include <QObject> #include <QObject>
#include <QVector> #include <QVector>
#include <QJsonArray>
#include <QJsonDocument>
#include <QtGlobal> #include <QtGlobal>
#include <optional>
#include "core/models/serverConfig.h" #include "core/models/selfhosted/selfHostedAdminServerConfig.h"
#include "core/models/selfhosted/selfHostedUserServerConfig.h"
#include "core/models/selfhosted/nativeServerConfig.h"
#include "core/models/api/apiV2ServerConfig.h"
#include "core/models/api/legacyApiServerConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/utils/serverConfigUtils.h"
#include "secureQSettings.h" #include "secureQSettings.h"
using namespace amnezia; using namespace amnezia;
@@ -18,47 +24,57 @@ class SecureServersRepository : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit SecureServersRepository(SecureQSettings* settings, QObject *parent = nullptr); explicit SecureServersRepository(SecureQSettings *settings, QObject *parent = nullptr);
QString addServer(const QString &serverId, const QJsonObject &serverJson, serverConfigUtils::ConfigType kind);
void editServer(const QString &serverId, const QJsonObject &serverJson, serverConfigUtils::ConfigType kind);
void removeServer(const QString &serverId);
serverConfigUtils::ConfigType serverKind(const QString &serverId) const;
std::optional<SelfHostedAdminServerConfig> selfHostedAdminConfig(const QString &serverId) const;
std::optional<SelfHostedUserServerConfig> selfHostedUserConfig(const QString &serverId) const;
std::optional<NativeServerConfig> nativeConfig(const QString &serverId) const;
std::optional<ApiV2ServerConfig> apiV2Config(const QString &serverId) const;
std::optional<LegacyApiServerConfig> legacyApiConfig(const QString &serverId) const;
void addServer(const ServerConfig &server);
void editServer(int index, const ServerConfig &server);
void removeServer(int index);
ServerConfig server(int index) const;
QVector<ServerConfig> servers() const;
int serversCount() const; int serversCount() const;
int indexOfServerId(const QString &serverId) const;
QString serverIdAt(int index) const;
QVector<QString> orderedServerIds() const;
int defaultServerIndex() const; int defaultServerIndex() const;
void setDefaultServer(int index); QString defaultServerId() const;
void setDefaultServer(const QString &serverId);
void setDefaultContainer(int serverIndex, DockerContainer container); void clearServers();
ContainerConfig containerConfig(int serverIndex, DockerContainer container) const;
void setContainerConfig(int serverIndex, DockerContainer container, const ContainerConfig &config);
void clearLastConnectionConfig(int serverIndex, DockerContainer container);
ServerCredentials serverCredentials(int index) const;
bool hasServerWithVpnKey(const QString &vpnKey) const;
bool hasServerWithCrc(quint16 crc) const;
void setServersArray(const QJsonArray &servers);
void invalidateCache(); void invalidateCache();
signals: signals:
void serverAdded(ServerConfig config); void serverAdded(const QString &serverId);
void serverEdited(int index, ServerConfig config); void serverEdited(const QString &serverId);
void serverRemoved(int index); void serverRemoved(const QString &serverId, int removedIndex);
void defaultServerChanged(int index); void defaultServerChanged(const QString &defaultServerId);
private: private:
void loadFromStorage();
void updateDefaultServerFromStorage();
void persistDefaultServerFields();
QString normalizedOrGeneratedServerId(const QString &candidateId) const;
void syncToStorage(); void syncToStorage();
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; QVariant value(const QString &key, const QVariant &defaultValue) const;
void setValue(const QString &key, const QVariant &value); void setValue(const QString &key, const QVariant &value);
SecureQSettings* m_settings; void clearServerStateMaps();
QVector<ServerConfig> m_servers; SecureQSettings *m_settings;
int m_defaultServerIndex = 0;
QHash<QString, QJsonObject> m_serverJsonById;
QVector<QString> m_orderedServerIds;
QString m_defaultServerId;
}; };
#endif // SECURESERVERSREPOSITORY_H #endif // SECURESERVERSREPOSITORY_H
-25
View File
@@ -1,25 +0,0 @@
#ifndef APIENUMS_H
#define APIENUMS_H
namespace apiDefs
{
enum ConfigType {
AmneziaFreeV2 = 0,
AmneziaFreeV3,
AmneziaPremiumV1,
AmneziaPremiumV2,
AmneziaTrialV2,
SelfHosted,
ExternalPremium,
ExternalTrial
};
enum ConfigSource {
Telegram = 1,
AmneziaGateway
};
}
#endif // APIENUMS_H
+7 -64
View File
@@ -1,5 +1,6 @@
#include "apiUtils.h" #include "apiUtils.h"
#include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/configKeys.h" #include "core/utils/constants/configKeys.h"
#include <QDateTime> #include <QDateTime>
#include <QJsonDocument> #include <QJsonDocument>
@@ -75,63 +76,6 @@ bool apiUtils::isSubscriptionExpiringSoon(const QString &subscriptionEndDate, in
return endDate <= nowUtc.addDays(withinDays); return endDate <= nowUtc.addDays(withinDays);
} }
bool apiUtils::isServerFromApi(const QJsonObject &serverConfigObject)
{
auto configVersion = serverConfigObject.value(configKey::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(configKey::configVersion).toInt();
switch (configVersion) {
case apiDefs::ConfigSource::Telegram: {
constexpr QLatin1String freeV2Endpoint(FREE_V2_ENDPOINT);
constexpr QLatin1String premiumV1Endpoint(PREM_V1_ENDPOINT);
auto apiEndpoint = serverConfigObject.value(apiDefs::key::apiEndpoint).toString();
if (apiEndpoint.contains(premiumV1Endpoint)) {
return apiDefs::ConfigType::AmneziaPremiumV1;
} else if (apiEndpoint.contains(freeV2Endpoint)) {
return apiDefs::ConfigType::AmneziaFreeV2;
}
};
case apiDefs::ConfigSource::AmneziaGateway: {
constexpr QLatin1String servicePremium("amnezia-premium");
constexpr QLatin1String serviceFree("amnezia-free");
constexpr QLatin1String serviceExternalPremium("external-premium");
constexpr QLatin1String serviceExternalTrial("external-trial");
auto apiConfigObject = serverConfigObject.value(apiDefs::key::apiConfig).toObject();
auto serviceType = apiConfigObject.value(apiDefs::key::serviceType).toString();
if (serviceType == servicePremium) {
return apiDefs::ConfigType::AmneziaPremiumV2;
} else if (serviceType == serviceFree) {
return apiDefs::ConfigType::AmneziaFreeV3;
} else if (serviceType == serviceExternalPremium) {
return apiDefs::ConfigType::ExternalPremium;
} else if (serviceType == serviceExternalTrial) {
return apiDefs::ConfigType::ExternalTrial;
}
}
default: {
return apiDefs::ConfigType::SelfHosted;
}
};
}
apiDefs::ConfigSource apiUtils::getConfigSource(const QJsonObject &serverConfigObject)
{
return static_cast<apiDefs::ConfigSource>(serverConfigObject.value(configKey::configVersion).toInt());
}
amnezia::ErrorCode apiUtils::checkNetworkReplyErrors(const QList<QSslError> &sslErrors, const QString &replyErrorString, amnezia::ErrorCode apiUtils::checkNetworkReplyErrors(const QList<QSslError> &sslErrors, const QString &replyErrorString,
const QNetworkReply::NetworkError &replyError, const int httpStatusCode, const QNetworkReply::NetworkError &replyError, const int httpStatusCode,
const QByteArray &responseBody) const QByteArray &responseBody)
@@ -197,14 +141,14 @@ amnezia::ErrorCode apiUtils::checkNetworkReplyErrors(const QList<QSslError> &ssl
bool apiUtils::isPremiumServer(const QJsonObject &serverConfigObject) bool apiUtils::isPremiumServer(const QJsonObject &serverConfigObject)
{ {
static const QSet<apiDefs::ConfigType> premiumTypes = { apiDefs::ConfigType::AmneziaPremiumV1, apiDefs::ConfigType::AmneziaPremiumV2, static const QSet<serverConfigUtils::ConfigType> premiumTypes = { serverConfigUtils::ConfigType::AmneziaPremiumV1, serverConfigUtils::ConfigType::AmneziaPremiumV2,
apiDefs::ConfigType::ExternalPremium, apiDefs::ConfigType::ExternalTrial }; serverConfigUtils::ConfigType::ExternalPremium };
return premiumTypes.contains(getConfigType(serverConfigObject)); return premiumTypes.contains(serverConfigUtils::configTypeFromJson(serverConfigObject));
} }
QString apiUtils::getPremiumV1VpnKey(const QJsonObject &serverConfigObject) QString apiUtils::getPremiumV1VpnKey(const QJsonObject &serverConfigObject)
{ {
if (apiUtils::getConfigType(serverConfigObject) != apiDefs::ConfigType::AmneziaPremiumV1) { if (serverConfigUtils::configTypeFromJson(serverConfigObject) != serverConfigUtils::ConfigType::AmneziaPremiumV1) {
return {}; return {};
} }
@@ -242,9 +186,8 @@ QString apiUtils::getPremiumV1VpnKey(const QJsonObject &serverConfigObject)
QString apiUtils::getPremiumV2VpnKey(const QJsonObject &serverConfigObject) QString apiUtils::getPremiumV2VpnKey(const QJsonObject &serverConfigObject)
{ {
auto configType = apiUtils::getConfigType(serverConfigObject); auto configType = serverConfigUtils::configTypeFromJson(serverConfigObject);
if (configType != apiDefs::ConfigType::AmneziaPremiumV2 && configType != apiDefs::ConfigType::ExternalPremium if (configType != serverConfigUtils::ConfigType::AmneziaPremiumV2 && configType != serverConfigUtils::ConfigType::ExternalPremium) {
&& configType != apiDefs::ConfigType::ExternalTrial) {
return {}; return {};
} }
+1 -6
View File
@@ -4,7 +4,7 @@
#include <QNetworkReply> #include <QNetworkReply>
#include <QObject> #include <QObject>
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
#include "core/utils/errorCodes.h" #include "core/utils/errorCodes.h"
@@ -13,17 +13,12 @@
namespace apiUtils namespace apiUtils
{ {
bool isServerFromApi(const QJsonObject &serverConfigObject);
bool isSubscriptionExpired(const QString &subscriptionEndDate); bool isSubscriptionExpired(const QString &subscriptionEndDate);
bool isSubscriptionExpiringSoon(const QString &subscriptionEndDate, int withinDays = 30); bool isSubscriptionExpiringSoon(const QString &subscriptionEndDate, int withinDays = 30);
bool isPremiumServer(const QJsonObject &serverConfigObject); bool isPremiumServer(const QJsonObject &serverConfigObject);
apiDefs::ConfigType getConfigType(const QJsonObject &serverConfigObject);
apiDefs::ConfigSource getConfigSource(const QJsonObject &serverConfigObject);
amnezia::ErrorCode checkNetworkReplyErrors(const QList<QSslError> &sslErrors, const QString &replyErrorString, amnezia::ErrorCode checkNetworkReplyErrors(const QList<QSslError> &sslErrors, const QString &replyErrorString,
const QNetworkReply::NetworkError &replyError, const int httpStatusCode, const QNetworkReply::NetworkError &replyError, const int httpStatusCode,
const QByteArray &responseBody); const QByteArray &responseBody);
+4 -4
View File
@@ -3,9 +3,9 @@
namespace apiDefs namespace apiDefs
{ {
const int requestTimeoutMsecs = 12 * 1000; // 12 secs
} constexpr int requestTimeoutMsecs = 12 * 1000; // 12 secs
} // namespace apiDefs
#endif // APICONSTANTS_H #endif // APICONSTANTS_H
+2 -3
View File
@@ -2,7 +2,6 @@
#define APIKEYS_H #define APIKEYS_H
#include <QLatin1String> #include <QLatin1String>
#include "core/utils/api/apiEnums.h"
namespace apiDefs namespace apiDefs
{ {
@@ -82,7 +81,7 @@ namespace apiDefs
constexpr QLatin1String expiresAt("expires_at"); constexpr QLatin1String expiresAt("expires_at");
constexpr QLatin1String isConnectEvent("is_connect_event"); constexpr QLatin1String isConnectEvent("is_connect_event");
constexpr QLatin1String certificate("certificate"); constexpr QLatin1String certificate("certificate");
} } // namespace key
} } // namespace apiDefs
#endif // APIKEYS_H #endif // APIKEYS_H
+3
View File
@@ -18,6 +18,7 @@ namespace amnezia
constexpr QLatin1String serverIndex("serverIndex"); constexpr QLatin1String serverIndex("serverIndex");
constexpr QLatin1String description("description"); constexpr QLatin1String description("description");
constexpr QLatin1String displayName("displayName");
constexpr QLatin1String name("name"); constexpr QLatin1String name("name");
constexpr QLatin1String cert("cert"); constexpr QLatin1String cert("cert");
constexpr QLatin1String accessToken("api_key"); constexpr QLatin1String accessToken("api_key");
@@ -121,6 +122,8 @@ namespace amnezia
constexpr QLatin1String latestHandshake("latestHandshake"); constexpr QLatin1String latestHandshake("latestHandshake");
constexpr QLatin1String dataReceived("dataReceived"); constexpr QLatin1String dataReceived("dataReceived");
constexpr QLatin1String dataSent("dataSent"); constexpr QLatin1String dataSent("dataSent");
constexpr QLatin1String storageServerId("storageServerId");
} }
} }
+3 -2
View File
@@ -71,10 +71,11 @@ namespace amnezia
// import and install errors // import and install errors
ImportInvalidConfigError = 900, ImportInvalidConfigError = 900,
ImportBackupFileUseRestoreInstead = 903,
RestoreBackupInvalidError = 904,
ImportOpenConfigError = 901, ImportOpenConfigError = 901,
NoInstalledContainersError = 902, NoInstalledContainersError = 902,
ImportBackupFileUseRestoreInstead = 903,
RestoreBackupInvalidError = 904,
LegacyApiV1NotSupportedError = 905,
// Android errors // Android errors
AndroidError = 1000, AndroidError = 1000,
+1
View File
@@ -59,6 +59,7 @@ QString errorString(ErrorCode code) {
case (ErrorCode::ImportInvalidConfigError): errorMessage = QObject::tr("The config does not contain any containers and credentials for connecting to the server"); break; case (ErrorCode::ImportInvalidConfigError): errorMessage = QObject::tr("The config does not contain any containers and credentials for connecting to the server"); break;
case (ErrorCode::ImportBackupFileUseRestoreInstead): errorMessage = QObject::tr("Backup files cannot be imported here. Use 'Restore from backup' instead."); break; case (ErrorCode::ImportBackupFileUseRestoreInstead): errorMessage = QObject::tr("Backup files cannot be imported here. Use 'Restore from backup' instead."); break;
case (ErrorCode::RestoreBackupInvalidError): errorMessage = QObject::tr("Backup file is corrupted or has invalid format"); break; case (ErrorCode::RestoreBackupInvalidError): errorMessage = QObject::tr("Backup file is corrupted or has invalid format"); break;
case (ErrorCode::LegacyApiV1NotSupportedError): errorMessage = QObject::tr("This legacy Amnezia subscription format is no longer supported"); break;
case (ErrorCode::ImportOpenConfigError): errorMessage = QObject::tr("Unable to open config file"); break; case (ErrorCode::ImportOpenConfigError): errorMessage = QObject::tr("Unable to open config file"); break;
case (ErrorCode::NoInstalledContainersError): errorMessage = QObject::tr("VPN Protocols is not installed.\n Please install VPN container at first"); break; case (ErrorCode::NoInstalledContainersError): errorMessage = QObject::tr("VPN Protocols is not installed.\n Please install VPN container at first"); break;
+122
View File
@@ -0,0 +1,122 @@
#include "serverConfigUtils.h"
#include <QJsonArray>
#include <QJsonValue>
#include "core/models/selfhosted/selfHostedAdminServerConfig.h"
#include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/configKeys.h"
namespace
{
bool hasThirdPartyConfig(const QJsonObject &json)
{
const QJsonArray containersArray = json.value(amnezia::configKey::containers).toArray();
for (const QJsonValue &val : containersArray) {
const QJsonObject containerObj = val.toObject();
for (auto it = containerObj.begin(); it != containerObj.end(); ++it) {
if (it.key() == amnezia::configKey::container) {
continue;
}
const QJsonObject protocolObj = it.value().toObject();
if (protocolObj.contains(amnezia::configKey::isThirdPartyConfig)
&& protocolObj.value(amnezia::configKey::isThirdPartyConfig).toBool()) {
return true;
}
}
}
return false;
}
} // namespace
namespace serverConfigUtils
{
bool isServerFromApi(const QJsonObject &serverConfigObject)
{
const int configVersion = serverConfigObject.value(amnezia::configKey::configVersion).toInt();
switch (configVersion) {
case ConfigSource::Telegram:
case ConfigSource::AmneziaGateway:
return true;
default:
return false;
}
}
ConfigSource getConfigSource(const QJsonObject &serverConfigObject)
{
return static_cast<ConfigSource>(serverConfigObject.value(amnezia::configKey::configVersion).toInt());
}
ConfigType configTypeFromJson(const QJsonObject &serverConfigObject)
{
const int configVersion = serverConfigObject.value(amnezia::configKey::configVersion).toInt();
switch (configVersion) {
case ConfigSource::Telegram: {
constexpr QLatin1String freeV2Endpoint(FREE_V2_ENDPOINT);
constexpr QLatin1String premiumV1Endpoint(PREM_V1_ENDPOINT);
const QString apiEndpointValue = serverConfigObject.value(apiDefs::key::apiEndpoint).toString();
if (apiEndpointValue.contains(premiumV1Endpoint)) {
return ConfigType::AmneziaPremiumV1;
}
if (apiEndpointValue.contains(freeV2Endpoint)) {
return ConfigType::AmneziaFreeV2;
}
}
[[fallthrough]];
case ConfigSource::AmneziaGateway: {
constexpr QLatin1String servicePremium("amnezia-premium");
constexpr QLatin1String serviceFree("amnezia-free");
constexpr QLatin1String serviceExternalPremium("external-premium");
const QJsonObject apiConfigObject = serverConfigObject.value(apiDefs::key::apiConfig).toObject();
const QString serviceTypeStr = apiConfigObject.value(apiDefs::key::serviceType).toString();
if (serviceTypeStr == servicePremium) {
return ConfigType::AmneziaPremiumV2;
}
if (serviceTypeStr == serviceFree) {
return ConfigType::AmneziaFreeV3;
}
if (serviceTypeStr == serviceExternalPremium) {
return ConfigType::ExternalPremium;
}
break;
}
default:
break;
}
if (hasThirdPartyConfig(serverConfigObject)) {
return ConfigType::Native;
}
const amnezia::SelfHostedAdminServerConfig adminProbe =
amnezia::SelfHostedAdminServerConfig::fromJson(serverConfigObject);
return adminProbe.hasCredentials() ? ConfigType::SelfHostedAdmin : ConfigType::SelfHostedUser;
}
bool isLegacyApiSubscription(ConfigType configType)
{
return configType == ConfigType::AmneziaPremiumV1 || configType == ConfigType::AmneziaFreeV2;
}
bool isApiV2Subscription(ConfigType configType)
{
switch (configType) {
case ConfigType::AmneziaPremiumV2:
case ConfigType::AmneziaFreeV3:
case ConfigType::ExternalPremium:
return true;
default:
return false;
}
}
} // namespace serverConfigUtils
+40
View File
@@ -0,0 +1,40 @@
#ifndef SERVERCONFIGUTILS_H
#define SERVERCONFIGUTILS_H
#include <QJsonObject>
namespace serverConfigUtils
{
enum ConfigType {
AmneziaFreeV2 = 0,
AmneziaFreeV3,
AmneziaPremiumV1,
AmneziaPremiumV2,
SelfHosted,
ExternalPremium,
SelfHostedAdmin = 8,
SelfHostedUser,
Native,
Invalid
};
enum ConfigSource {
Telegram = 1,
AmneziaGateway
};
bool isServerFromApi(const QJsonObject &serverConfigObject);
ConfigSource getConfigSource(const QJsonObject &serverConfigObject);
ConfigType configTypeFromJson(const QJsonObject &serverConfigObject);
bool isLegacyApiSubscription(ConfigType configType);
bool isApiV2Subscription(ConfigType configType);
} // namespace serverConfigUtils
#endif // SERVERCONFIGUTILS_H
-10
View File
@@ -95,15 +95,6 @@ target_link_libraries(test_servers_model_sync PRIVATE
test_common test_common
) )
add_executable(test_gateway_stacks
testGatewayStacks.cpp
)
target_link_libraries(test_gateway_stacks PRIVATE
Qt6::Test
test_common
)
add_executable(test_complex_operations add_executable(test_complex_operations
testComplexOperations.cpp testComplexOperations.cpp
) )
@@ -148,7 +139,6 @@ add_test(NAME DefaultServerChangeTest COMMAND test_default_server_change)
add_test(NAME ServerEdgeCasesTest COMMAND test_server_edge_cases) add_test(NAME ServerEdgeCasesTest COMMAND test_server_edge_cases)
add_test(NAME SignalOrderTest COMMAND test_signal_order) add_test(NAME SignalOrderTest COMMAND test_signal_order)
add_test(NAME ServersModelSyncTest COMMAND test_servers_model_sync) add_test(NAME ServersModelSyncTest COMMAND test_servers_model_sync)
add_test(NAME GatewayStacksTest COMMAND test_gateway_stacks)
add_test(NAME ComplexOperationsTest COMMAND test_complex_operations) add_test(NAME ComplexOperationsTest COMMAND test_complex_operations)
add_test(NAME SettingsSignalsTest COMMAND test_settings_signals) add_test(NAME SettingsSignalsTest COMMAND test_settings_signals)
add_test(NAME UiServersModelAndControllerTest COMMAND test_ui_servers_model_and_controller) add_test(NAME UiServersModelAndControllerTest COMMAND test_ui_servers_model_and_controller)
+3 -3
View File
@@ -8,7 +8,7 @@
#include <QSignalSpy> #include <QSignalSpy>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h" #include "core/utils/constants/configKeys.h"
#include "vpnConnection.h" #include "vpnConnection.h"
#include "secureQSettings.h" #include "secureQSettings.h"
@@ -117,8 +117,8 @@ private slots:
QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged signal should NOT be emitted (default is already 0)"); QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged signal should NOT be emitted (default is already 0)");
QVERIFY2(m_coreController->m_serversRepository->serversCount() > 0, "Server should be added"); QVERIFY2(m_coreController->m_serversRepository->serversCount() > 0, "Server should be added");
int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); const QString serverId = m_coreController->m_serversRepository->defaultServerId();
auto exportResult = m_coreController->m_exportController->generateFullAccessConfig(serverIndex); auto exportResult = m_coreController->m_exportController->generateFullAccessConfig(serverId);
QVERIFY2(exportResult.errorCode == ErrorCode::NoError, "Export should succeed"); QVERIFY2(exportResult.errorCode == ErrorCode::NoError, "Export should succeed");
QVERIFY2(!exportResult.config.isEmpty(), "Exported config should not be empty"); QVERIFY2(!exportResult.config.isEmpty(), "Exported config should not be empty");
+15 -16
View File
@@ -5,7 +5,8 @@
#include <QSignalSpy> #include <QSignalSpy>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h" #include "core/models/serverDescription.h"
#include "tests/testServerRepositoryHelpers.h"
#include "vpnConnection.h" #include "vpnConnection.h"
#include "secureQSettings.h" #include "secureQSettings.h"
@@ -37,7 +38,7 @@ private slots:
void init() { void init() {
m_settings->clearSettings(); m_settings->clearSettings();
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
m_coreController->m_serversModel->updateModel(QVector<ServerConfig>(), -1, false); m_coreController->m_serversModel->updateModel(QVector<ServerDescription>(), -1);
} }
} }
@@ -65,35 +66,33 @@ private slots:
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 3, "Should have 3 servers"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 3, "Should have 3 servers");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 2, "Default should be index 2"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 2, "Default should be index 2");
ServerConfig server0 = m_coreController->m_serversController->getServerConfig(0); amnezia::test::setServerDescription(m_coreController->m_serversRepository,
server0.visit([](auto& arg) { m_coreController->m_serversController->getServerId(0),
arg.description = "Edited First Server"; QStringLiteral("Edited First Server"));
});
m_coreController->m_serversController->editServer(0, server0);
QVERIFY2(serverEditedSpy.count() == 1, "serverEdited should be emitted"); QVERIFY2(serverEditedSpy.count() == 1, "serverEdited should be emitted");
QString editedDesc0 = m_coreController->m_serversRepository->server(0).description(); QString editedDesc0 = amnezia::test::serverDescription(m_coreController->m_serversRepository,
m_coreController->m_serversRepository->serverIdAt(0));
QVERIFY2(editedDesc0 == "Edited First Server", "First server should be edited"); QVERIFY2(editedDesc0 == "Edited First Server", "First server should be edited");
m_coreController->m_serversController->removeServer(1); m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(1));
QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved should be emitted"); QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved should be emitted");
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 2, "Should have 2 servers"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 2, "Should have 2 servers");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Default should be index 1 (was 2, removed 1)"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Default should be index 1 (was 2, removed 1)");
m_coreController->m_serversController->setDefaultServerIndex(0); m_coreController->m_serversController->setDefaultServer(m_coreController->m_serversController->getServerId(0));
QVERIFY2(defaultServerChangedSpy.count() == 4, "defaultServerChanged should be emitted again"); QVERIFY2(defaultServerChangedSpy.count() == 4, "defaultServerChanged should be emitted again");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default should be index 0"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default should be index 0");
ServerConfig server0After = m_coreController->m_serversController->getServerConfig(0); amnezia::test::setServerDescription(m_coreController->m_serversRepository,
server0After.visit([](auto& arg) { m_coreController->m_serversController->getServerId(0),
arg.description = "Final Edited Server"; QStringLiteral("Final Edited Server"));
});
m_coreController->m_serversController->editServer(0, server0After);
QVERIFY2(serverEditedSpy.count() == 2, "serverEdited should be emitted again"); QVERIFY2(serverEditedSpy.count() == 2, "serverEdited should be emitted again");
QString finalDesc0 = m_coreController->m_serversRepository->server(0).description(); QString finalDesc0 = amnezia::test::serverDescription(m_coreController->m_serversRepository,
m_coreController->m_serversRepository->serverIdAt(0));
QVERIFY2(finalDesc0 == "Final Edited Server", "First server should be edited again"); QVERIFY2(finalDesc0 == "Final Edited Server", "First server should be edited again");
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 2, "Final servers count should be 2"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 2, "Final servers count should be 2");
+17 -14
View File
@@ -5,7 +5,8 @@
#include <QSignalSpy> #include <QSignalSpy>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h" #include "core/models/serverDescription.h"
#include "tests/testServerRepositoryHelpers.h"
#include "ui/models/serversModel.h" #include "ui/models/serversModel.h"
#include "vpnConnection.h" #include "vpnConnection.h"
#include "secureQSettings.h" #include "secureQSettings.h"
@@ -39,7 +40,7 @@ private slots:
m_settings->clearSettings(); m_settings->clearSettings();
m_coreController->m_serversRepository->invalidateCache(); m_coreController->m_serversRepository->invalidateCache();
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
m_coreController->m_serversModel->updateModel(QVector<ServerConfig>(), -1, false); m_coreController->m_serversModel->updateModel(QVector<ServerDescription>(), -1);
} }
} }
@@ -60,9 +61,10 @@ private slots:
QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged); QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged);
m_coreController->m_serversController->setDefaultServerIndex(0); m_coreController->m_serversController->setDefaultServer(m_coreController->m_serversController->getServerId(0));
QVERIFY2(defaultServerChangedSpy.count() == 1, "defaultServerChanged signal should be emitted"); QVERIFY2(defaultServerChangedSpy.count() == 1, "defaultServerChanged signal should be emitted");
QVERIFY2(defaultServerChangedSpy.at(0).at(0).toInt() == 0, "defaultServerChanged should emit index 0"); QVERIFY2(defaultServerChangedSpy.at(0).at(0).toString() == m_coreController->m_serversController->getServerId(0),
"defaultServerChanged should emit new default server id");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default server index should be 0"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default server index should be 0");
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
@@ -70,9 +72,10 @@ private slots:
QVERIFY2(modelDefaultIndex == 0, "Model should reflect default server"); QVERIFY2(modelDefaultIndex == 0, "Model should reflect default server");
} }
m_coreController->m_serversController->setDefaultServerIndex(2); m_coreController->m_serversController->setDefaultServer(m_coreController->m_serversController->getServerId(2));
QVERIFY2(defaultServerChangedSpy.count() == 2, "defaultServerChanged signal should be emitted again"); QVERIFY2(defaultServerChangedSpy.count() == 2, "defaultServerChanged signal should be emitted again");
QVERIFY2(defaultServerChangedSpy.at(1).at(0).toInt() == 2, "defaultServerChanged should emit index 2"); QVERIFY2(defaultServerChangedSpy.at(1).at(0).toString() == m_coreController->m_serversController->getServerId(2),
"defaultServerChanged should emit new default server id");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 2, "Default server index should be 2"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 2, "Default server index should be 2");
} }
@@ -94,28 +97,28 @@ private slots:
QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged); QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged);
QSignalSpy serverRemovedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverRemoved); QSignalSpy serverRemovedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverRemoved);
m_coreController->m_serversController->removeServer(0); m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(0));
QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted"); QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted");
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 2, "Should have 2 servers"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 2, "Should have 2 servers");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Default should be index 1 (was 2, removed 0)"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Default should be index 1 (was 2, removed 0)");
ServerConfig remainingServer1 = m_coreController->m_serversRepository->server(0); QString desc1 = amnezia::test::serverDescription(m_coreController->m_serversRepository,
ServerConfig remainingServer2 = m_coreController->m_serversRepository->server(1); m_coreController->m_serversRepository->serverIdAt(0));
QString desc1 = remainingServer1.description(); QString desc2 = amnezia::test::serverDescription(m_coreController->m_serversRepository,
QString desc2 = remainingServer2.description(); m_coreController->m_serversRepository->serverIdAt(1));
QVERIFY2(desc1 == "Xray Server", "First remaining server should be Xray"); QVERIFY2(desc1 == "Xray Server", "First remaining server should be Xray");
QVERIFY2(desc2 == "WireGuard Server", "Second remaining server should be WireGuard"); QVERIFY2(desc2 == "WireGuard Server", "Second remaining server should be WireGuard");
defaultServerChangedSpy.clear(); defaultServerChangedSpy.clear();
serverRemovedSpy.clear(); serverRemovedSpy.clear();
m_coreController->m_serversController->removeServer(0); m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(0));
QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted"); QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted");
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 1, "Should have 1 server"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 1, "Should have 1 server");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default should be index 0 (was 1, removed 0)"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default should be index 0 (was 1, removed 0)");
ServerConfig lastServer = m_coreController->m_serversRepository->server(0); QString lastDesc = amnezia::test::serverDescription(m_coreController->m_serversRepository,
QString lastDesc = lastServer.description(); m_coreController->m_serversRepository->serverIdAt(0));
QVERIFY2(lastDesc == "WireGuard Server", "Last server should be WireGuard"); QVERIFY2(lastDesc == "WireGuard Server", "Last server should be WireGuard");
} }
}; };
-75
View File
@@ -1,75 +0,0 @@
#include <QTest>
#include <QJsonDocument>
#include <QJsonObject>
#include <QUuid>
#include <QSignalSpy>
#include "core/controllers/coreController.h"
#include "core/models/serverConfig.h"
#include "vpnConnection.h"
#include "secureQSettings.h"
using namespace amnezia;
class TestGatewayStacks : public QObject
{
Q_OBJECT
private:
CoreController* m_coreController;
SecureQSettings* m_settings;
private slots:
void initTestCase() {
QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString();
m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false);
auto vpnConnection = QSharedPointer<VpnConnection>::create(nullptr, nullptr);
m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this);
}
void cleanupTestCase() {
m_settings->clearSettings();
delete m_coreController;
delete m_settings;
}
void init() {
m_settings->clearSettings();
if (m_coreController->m_serversModel) {
m_coreController->m_serversModel->updateModel(QVector<ServerConfig>(), -1, false);
}
}
void testGatewayStacksRecomputeOnServerOperations() {
QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA";
QSignalSpy gatewayStacksExpandedSpy(m_coreController->m_serversController, &ServersController::gatewayStacksExpanded);
QSignalSpy serverAddedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverAdded);
QSignalSpy serverEditedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverEdited);
QSignalSpy serverRemovedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverRemoved);
auto importResult = m_coreController->m_importCoreController->extractConfigFromData(awgKey);
m_coreController->m_importCoreController->importConfig(importResult.config);
QVERIFY2(serverAddedSpy.count() == 1, "serverAdded signal should be emitted");
QVERIFY2(m_coreController->m_serversController->gatewayStacks().isEmpty(), "Gateway stacks should be empty for self-hosted servers");
ServerConfig serverConfig = m_coreController->m_serversController->getServerConfig(0);
serverConfig.visit([](auto& arg) {
arg.description = "Edited Server";
});
m_coreController->m_serversController->editServer(0, serverConfig);
QVERIFY2(serverEditedSpy.count() == 1, "serverEdited signal should be emitted");
m_coreController->m_serversController->removeServer(0);
QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted");
QVERIFY2(m_coreController->m_serversController->gatewayStacks().isEmpty(), "Gateway stacks should remain empty");
}
};
QTEST_MAIN(TestGatewayStacks)
#include "testGatewayStacks.moc"
+19 -18
View File
@@ -6,7 +6,8 @@
#include <QSignalSpy> #include <QSignalSpy>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h" #include "core/models/serverDescription.h"
#include "tests/testServerRepositoryHelpers.h"
#include "vpnConnection.h" #include "vpnConnection.h"
#include "secureQSettings.h" #include "secureQSettings.h"
@@ -40,7 +41,7 @@ private slots:
m_settings->clearSettings(); m_settings->clearSettings();
m_coreController->m_serversRepository->invalidateCache(); m_coreController->m_serversRepository->invalidateCache();
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
m_coreController->m_serversModel->updateModel(QVector<ServerConfig>(), -1, false); m_coreController->m_serversModel->updateModel(QVector<ServerDescription>(), -1);
} }
} }
@@ -70,8 +71,8 @@ private slots:
} }
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "First server should be default"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "First server should be default");
ServerConfig server1 = m_coreController->m_serversRepository->server(0); QString desc1 = amnezia::test::serverDescription(m_coreController->m_serversRepository,
QString desc1 = server1.description(); m_coreController->m_serversRepository->serverIdAt(0));
QVERIFY2(desc1 == "AWG Server", "First server description should match"); QVERIFY2(desc1 == "AWG Server", "First server description should match");
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
@@ -92,8 +93,8 @@ private slots:
} }
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Second server should be default"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Second server should be default");
ServerConfig server2 = m_coreController->m_serversRepository->server(1); QString desc2 = amnezia::test::serverDescription(m_coreController->m_serversRepository,
QString desc2 = server2.description(); m_coreController->m_serversRepository->serverIdAt(1));
QVERIFY2(desc2 == "Xray Server", "Second server description should match"); QVERIFY2(desc2 == "Xray Server", "Second server description should match");
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
@@ -114,8 +115,8 @@ private slots:
} }
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 2, "Third server should be default"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 2, "Third server should be default");
ServerConfig server3 = m_coreController->m_serversRepository->server(2); QString desc3 = amnezia::test::serverDescription(m_coreController->m_serversRepository,
QString desc3 = server3.description(); m_coreController->m_serversRepository->serverIdAt(2));
QVERIFY2(desc3 == "WireGuard Server", "Third server description should match"); QVERIFY2(desc3 == "WireGuard Server", "Third server description should match");
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
@@ -147,25 +148,25 @@ private slots:
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 2, "After two imports servers count should be 2"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 2, "After two imports servers count should be 2");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Second server should be default"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Second server should be default");
ServerConfig server0 = m_coreController->m_serversRepository->server(0); QString desc0 = amnezia::test::serverDescription(m_coreController->m_serversRepository,
ServerConfig server1 = m_coreController->m_serversRepository->server(1); m_coreController->m_serversRepository->serverIdAt(0));
QString desc0 = server0.description(); QString desc1 = amnezia::test::serverDescription(m_coreController->m_serversRepository,
QString desc1 = server1.description(); m_coreController->m_serversRepository->serverIdAt(1));
QVERIFY2(desc0 == "AWG Server", "First server description should match"); QVERIFY2(desc0 == "AWG Server", "First server description should match");
QVERIFY2(desc1 == "Xray Server", "Second server description should match"); QVERIFY2(desc1 == "Xray Server", "Second server description should match");
defaultServerChangedSpy.clear(); defaultServerChangedSpy.clear();
serverRemovedSpy.clear(); serverRemovedSpy.clear();
m_coreController->m_serversController->removeServer(0); m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(0));
QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted"); QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted");
QVERIFY2(serverRemovedSpy.at(0).at(0).toInt() == 0, "serverRemoved should emit index 0"); QVERIFY2(serverRemovedSpy.at(0).at(1).toInt() == 0, "serverRemoved should emit removed index 0");
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 1, "After removing first server, servers count should be 1"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 1, "After removing first server, servers count should be 1");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "After removing first server, default index should be 0"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "After removing first server, default index should be 0");
ServerConfig remainingServer = m_coreController->m_serversRepository->server(0); QString remainingDesc = amnezia::test::serverDescription(m_coreController->m_serversRepository,
QString remainingDesc = remainingServer.description(); m_coreController->m_serversRepository->serverIdAt(0));
QVERIFY2(remainingDesc == "Xray Server", "Remaining server should be Xray Server"); QVERIFY2(remainingDesc == "Xray Server", "Remaining server should be Xray Server");
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
@@ -177,10 +178,10 @@ private slots:
defaultServerChangedSpy.clear(); defaultServerChangedSpy.clear();
serverRemovedSpy.clear(); serverRemovedSpy.clear();
m_coreController->m_serversController->removeServer(0); m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(0));
QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted"); QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted");
QVERIFY2(serverRemovedSpy.at(0).at(0).toInt() == 0, "serverRemoved should emit index 0"); QVERIFY2(serverRemovedSpy.at(0).at(1).toInt() == 0, "serverRemoved should emit removed index 0");
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 0, "After removing last server, servers count should be 0"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 0, "After removing last server, servers count should be 0");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "After removing last server, default index should be 0"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "After removing last server, default index should be 0");
+48 -36
View File
@@ -7,8 +7,8 @@
#include <QDebug> #include <QDebug>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h" #include "core/models/serverDescription.h"
#include "core/models/selfhosted/selfHostedServerConfig.h" #include "core/models/selfhosted/selfHostedAdminServerConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/models/protocols/awgProtocolConfig.h" #include "core/models/protocols/awgProtocolConfig.h"
#include "core/models/protocols/dnsProtocolConfig.h" #include "core/models/protocols/dnsProtocolConfig.h"
@@ -60,21 +60,24 @@ private:
qDebug() << "SSH connection successful. Output:" << sshOutput; qDebug() << "SSH connection successful. Output:" << sshOutput;
} }
void verifyAdminAccess(int serverIndex) { void verifyAdminAccess(int serverIndex)
ServerConfig server = m_coreController->m_serversRepository->server(serverIndex); {
const SelfHostedServerConfig* selfHosted = server.as<SelfHostedServerConfig>(); const QString serverId = m_coreController->m_serversRepository->serverIdAt(serverIndex);
QVERIFY2(selfHosted != nullptr, "Server config should be SelfHostedServerConfig"); const auto adminCfg = m_coreController->m_serversRepository->selfHostedAdminConfig(serverId);
QVERIFY2(adminCfg.has_value(), "Server config should be SelfHostedAdminServerConfig");
const SelfHostedAdminServerConfig &selfHosted = *adminCfg;
QVERIFY2(selfHosted->hasCredentials(), QVERIFY2(selfHosted.hasCredentials(),
"Server should have credentials (admin access)"); "Server should have credentials (admin access)");
QVERIFY2(selfHosted->userName.has_value() && !selfHosted->userName.value().isEmpty(), QVERIFY2(!selfHosted.userName.isEmpty(),
"Server should have userName for admin access"); "Server should have userName for admin access");
QVERIFY2(selfHosted->password.has_value() && !selfHosted->password.value().isEmpty(), QVERIFY2(!selfHosted.password.isEmpty(),
"Server should have password for admin access"); "Server should have password for admin access");
QVERIFY2(!selfHosted->isReadOnly(), QVERIFY2(!selfHosted.isReadOnly(),
"Server should not be read-only (should have admin access)"); "Server should not be read-only (should have admin access)");
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
@@ -143,7 +146,7 @@ private slots:
void init() { void init() {
m_settings->clearSettings(); m_settings->clearSettings();
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
m_coreController->m_serversModel->updateModel(QVector<ServerConfig>(), -1, false); m_coreController->m_serversModel->updateModel(QVector<ServerDescription>(), -1);
} }
} }
@@ -177,10 +180,10 @@ private slots:
int serverIndex = m_coreController->m_serversRepository->serversCount() - 1; int serverIndex = m_coreController->m_serversRepository->serversCount() - 1;
qDebug() << "Server with Awg container added at index:" << serverIndex; qDebug() << "Server with Awg container added at index:" << serverIndex;
ServerConfig serverAfterAwg = m_coreController->m_serversRepository->server(serverIndex); const auto adminAfterAwg = m_coreController->m_serversRepository->selfHostedAdminConfig(
QVERIFY2(serverAfterAwg.isSelfHosted(), "Server should be self-hosted"); m_coreController->m_serversRepository->serverIdAt(serverIndex));
const SelfHostedServerConfig* selfHostedAfterAwg = serverAfterAwg.as<SelfHostedServerConfig>(); QVERIFY2(adminAfterAwg.has_value(), "Server should be self-hosted (admin)");
QVERIFY2(selfHostedAfterAwg != nullptr, "Server config should be SelfHostedServerConfig"); const SelfHostedAdminServerConfig *selfHostedAfterAwg = &(*adminAfterAwg);
QVERIFY2(selfHostedAfterAwg->defaultContainer == DockerContainer::Awg, "Default container should be Awg"); QVERIFY2(selfHostedAfterAwg->defaultContainer == DockerContainer::Awg, "Default container should be Awg");
QVERIFY2(selfHostedAfterAwg->containers.contains(DockerContainer::Awg), "Server should have Awg container"); QVERIFY2(selfHostedAfterAwg->containers.contains(DockerContainer::Awg), "Server should have Awg container");
@@ -198,8 +201,9 @@ private slots:
TransportProto dnsTransportProto = TransportProto::Udp; TransportProto dnsTransportProto = TransportProto::Udp;
bool wasDnsInstalled = false; bool wasDnsInstalled = false;
const QString serverIdForOps = m_coreController->m_serversRepository->serverIdAt(serverIndex);
ErrorCode installContainerError = m_coreController->m_installController->installContainer( ErrorCode installContainerError = m_coreController->m_installController->installContainer(
serverIndex, DockerContainer::Dns, dnsPort, dnsTransportProto, wasDnsInstalled); serverIdForOps, DockerContainer::Dns, dnsPort, dnsTransportProto, wasDnsInstalled);
QVERIFY2(installContainerError == ErrorCode::NoError, QVERIFY2(installContainerError == ErrorCode::NoError,
QString("installContainer for Dns should succeed. Error: %1") QString("installContainer for Dns should succeed. Error: %1")
@@ -207,9 +211,10 @@ private slots:
.toUtf8().constData()); .toUtf8().constData());
qDebug() << "Dns container installed:" << wasDnsInstalled; qDebug() << "Dns container installed:" << wasDnsInstalled;
ServerConfig serverAfterDns = m_coreController->m_serversRepository->server(serverIndex); const auto adminAfterDns = m_coreController->m_serversRepository->selfHostedAdminConfig(
const SelfHostedServerConfig* selfHostedAfterDns = serverAfterDns.as<SelfHostedServerConfig>(); m_coreController->m_serversRepository->serverIdAt(serverIndex));
QVERIFY2(selfHostedAfterDns != nullptr, "Server config should be SelfHostedServerConfig"); QVERIFY2(adminAfterDns.has_value(), "Server config should be SelfHostedAdminServerConfig");
const SelfHostedAdminServerConfig *selfHostedAfterDns = &(*adminAfterDns);
QVERIFY2(selfHostedAfterDns->containers.contains(DockerContainer::Awg), "Server should still have Awg container"); QVERIFY2(selfHostedAfterDns->containers.contains(DockerContainer::Awg), "Server should still have Awg container");
QVERIFY2(selfHostedAfterDns->containers.contains(DockerContainer::Dns), "Server should have Dns container"); QVERIFY2(selfHostedAfterDns->containers.contains(DockerContainer::Dns), "Server should have Dns container");
QVERIFY2(selfHostedAfterDns->containers.size() == 2, QVERIFY2(selfHostedAfterDns->containers.size() == 2,
@@ -242,16 +247,18 @@ private slots:
verifySshConnection(credentials); verifySshConnection(credentials);
SelfHostedServerConfig serverConfig; SelfHostedAdminServerConfig serverConfig;
serverConfig.hostName = credentials.hostName; serverConfig.hostName = credentials.hostName;
serverConfig.userName = credentials.userName; serverConfig.userName = credentials.userName;
serverConfig.password = credentials.secretData; serverConfig.password = credentials.secretData;
serverConfig.port = credentials.port; serverConfig.port = credentials.port;
serverConfig.description = m_coreController->m_appSettingsRepository->nextAvailableServerName(); serverConfig.description = m_coreController->m_appSettingsRepository->nextAvailableServerName();
serverConfig.displayName = serverConfig.description.isEmpty() ? serverConfig.hostName : serverConfig.description;
serverConfig.defaultContainer = DockerContainer::None; serverConfig.defaultContainer = DockerContainer::None;
QSignalSpy serverAddedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverAdded); QSignalSpy serverAddedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverAdded);
m_coreController->m_serversController->addServer(ServerConfig(serverConfig)); m_coreController->m_serversRepository->addServer(QString(), serverConfig.toJson(),
serverConfigUtils::ConfigType::SelfHostedAdmin);
QVERIFY2(serverAddedSpy.count() == 1, "serverAdded signal should be emitted"); QVERIFY2(serverAddedSpy.count() == 1, "serverAdded signal should be emitted");
QVERIFY2(m_coreController->m_serversRepository->serversCount() > 0, "Server should be added"); QVERIFY2(m_coreController->m_serversRepository->serversCount() > 0, "Server should be added");
@@ -259,23 +266,25 @@ private slots:
int serverIndex = m_coreController->m_serversRepository->serversCount() - 1; int serverIndex = m_coreController->m_serversRepository->serversCount() - 1;
qDebug() << "Empty server added at index:" << serverIndex; qDebug() << "Empty server added at index:" << serverIndex;
ServerConfig addedServer = m_coreController->m_serversRepository->server(serverIndex); const auto addedAdmin = m_coreController->m_serversRepository->selfHostedAdminConfig(
QVERIFY2(addedServer.isSelfHosted(), "Added server should be self-hosted"); m_coreController->m_serversRepository->serverIdAt(serverIndex));
const SelfHostedServerConfig* selfHosted = addedServer.as<SelfHostedServerConfig>(); QVERIFY2(addedAdmin.has_value(), "Added server should be self-hosted admin");
QVERIFY2(selfHosted != nullptr, "Server config should be SelfHostedServerConfig"); const SelfHostedAdminServerConfig *selfHosted = &(*addedAdmin);
QVERIFY2(selfHosted->containers.isEmpty(), "Server should have no containers initially"); QVERIFY2(selfHosted->containers.isEmpty(), "Server should have no containers initially");
QVERIFY2(selfHosted->defaultContainer == DockerContainer::None, "Default container should be None"); QVERIFY2(selfHosted->defaultContainer == DockerContainer::None, "Default container should be None");
ErrorCode scanError = m_coreController->m_installController->scanServerForInstalledContainers(serverIndex); const QString scanServerId = m_coreController->m_serversRepository->serverIdAt(serverIndex);
ErrorCode scanError = m_coreController->m_installController->scanServerForInstalledContainers(scanServerId);
QVERIFY2(scanError == ErrorCode::NoError, QVERIFY2(scanError == ErrorCode::NoError,
QString("Server scan should succeed. Error: %1") QString("Server scan should succeed. Error: %1")
.arg(static_cast<int>(scanError)) .arg(static_cast<int>(scanError))
.toUtf8().constData()); .toUtf8().constData());
qDebug() << "Server scan completed successfully"; qDebug() << "Server scan completed successfully";
ServerConfig scannedServer = m_coreController->m_serversRepository->server(serverIndex); const auto scannedAdmin = m_coreController->m_serversRepository->selfHostedAdminConfig(
const SelfHostedServerConfig* scannedSelfHosted = scannedServer.as<SelfHostedServerConfig>(); m_coreController->m_serversRepository->serverIdAt(serverIndex));
QVERIFY2(scannedSelfHosted != nullptr, "Scanned server config should be SelfHostedServerConfig"); QVERIFY2(scannedAdmin.has_value(), "Scanned server config should be SelfHostedAdminServerConfig");
const SelfHostedAdminServerConfig *scannedSelfHosted = &(*scannedAdmin);
QMap<DockerContainer, ContainerConfig> containers = scannedSelfHosted->containers; QMap<DockerContainer, ContainerConfig> containers = scannedSelfHosted->containers;
int containersCount = containers.size(); int containersCount = containers.size();
@@ -336,24 +345,27 @@ private slots:
int serverIndex = m_coreController->m_serversRepository->serversCount() - 1; int serverIndex = m_coreController->m_serversRepository->serversCount() - 1;
qDebug() << "Server with Awg container added at index:" << serverIndex; qDebug() << "Server with Awg container added at index:" << serverIndex;
ServerConfig serverBeforeRemoval = m_coreController->m_serversRepository->server(serverIndex); const auto adminBeforeRemoval = m_coreController->m_serversRepository->selfHostedAdminConfig(
const SelfHostedServerConfig* selfHostedBeforeRemoval = serverBeforeRemoval.as<SelfHostedServerConfig>(); m_coreController->m_serversRepository->serverIdAt(serverIndex));
QVERIFY2(selfHostedBeforeRemoval != nullptr, "Server config should be SelfHostedServerConfig"); QVERIFY2(adminBeforeRemoval.has_value(), "Server config should be SelfHostedAdminServerConfig");
const SelfHostedAdminServerConfig *selfHostedBeforeRemoval = &(*adminBeforeRemoval);
QVERIFY2(!selfHostedBeforeRemoval->containers.isEmpty(), "Server should have containers before removal"); QVERIFY2(!selfHostedBeforeRemoval->containers.isEmpty(), "Server should have containers before removal");
QVERIFY2(selfHostedBeforeRemoval->defaultContainer != DockerContainer::None, "Server should have default container before removal"); QVERIFY2(selfHostedBeforeRemoval->defaultContainer != DockerContainer::None, "Server should have default container before removal");
qDebug() << "Containers before removal:" << selfHostedBeforeRemoval->containers.size(); qDebug() << "Containers before removal:" << selfHostedBeforeRemoval->containers.size();
ErrorCode removeError = m_coreController->m_installController->removeAllContainers(serverIndex); const QString removeServerId = m_coreController->m_serversRepository->serverIdAt(serverIndex);
ErrorCode removeError = m_coreController->m_installController->removeAllContainers(removeServerId);
QVERIFY2(removeError == ErrorCode::NoError, QVERIFY2(removeError == ErrorCode::NoError,
QString("removeAllContainers should succeed. Error: %1") QString("removeAllContainers should succeed. Error: %1")
.arg(static_cast<int>(removeError)) .arg(static_cast<int>(removeError))
.toUtf8().constData()); .toUtf8().constData());
qDebug() << "All containers removed successfully"; qDebug() << "All containers removed successfully";
ServerConfig serverAfterRemoval = m_coreController->m_serversRepository->server(serverIndex); const auto adminAfterRemoval = m_coreController->m_serversRepository->selfHostedAdminConfig(
const SelfHostedServerConfig* selfHostedAfterRemoval = serverAfterRemoval.as<SelfHostedServerConfig>(); m_coreController->m_serversRepository->serverIdAt(serverIndex));
QVERIFY2(selfHostedAfterRemoval != nullptr, "Server config should be SelfHostedServerConfig"); QVERIFY2(adminAfterRemoval.has_value(), "Server config should be SelfHostedAdminServerConfig");
const SelfHostedAdminServerConfig *selfHostedAfterRemoval = &(*adminAfterRemoval);
QVERIFY2(selfHostedAfterRemoval->containers.isEmpty(), QVERIFY2(selfHostedAfterRemoval->containers.isEmpty(),
"Server should have no containers after removal"); "Server should have no containers after removal");
+23 -15
View File
@@ -1,13 +1,15 @@
#include <QTest> #include <QTest>
#include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QUuid> #include <QUuid>
#include <QSignalSpy> #include <QSignalSpy>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h" #include "core/repositories/secureServersRepository.h"
#include "core/models/serverDescription.h"
#include "core/models/selfhosted/selfHostedAdminServerConfig.h"
#include "vpnConnection.h" #include "vpnConnection.h"
#include "secureQSettings.h" #include "secureQSettings.h"
#include "core/utils/serverConfigUtils.h"
using namespace amnezia; using namespace amnezia;
@@ -38,7 +40,7 @@ private slots:
m_settings->clearSettings(); m_settings->clearSettings();
m_coreController->m_serversRepository->invalidateCache(); m_coreController->m_serversRepository->invalidateCache();
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
m_coreController->m_serversModel->updateModel(QVector<ServerConfig>(), -1, false); m_coreController->m_serversModel->updateModel(QVector<ServerDescription>(), -1);
} }
} }
@@ -54,27 +56,32 @@ private slots:
QSignalSpy serverEditedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverEdited); QSignalSpy serverEditedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverEdited);
QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged); QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged);
m_coreController->m_serversController->removeServer(-1); m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(-1));
QVERIFY2(serverRemovedSpy.count() == 0, "serverRemoved should NOT be emitted for invalid index"); QVERIFY2(serverRemovedSpy.count() == 0, "serverRemoved should NOT be emitted for invalid index");
m_coreController->m_serversController->removeServer(10); m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(10));
QVERIFY2(serverRemovedSpy.count() == 0, "serverRemoved should NOT be emitted for invalid index"); QVERIFY2(serverRemovedSpy.count() == 0, "serverRemoved should NOT be emitted for invalid index");
m_coreController->m_serversController->removeServer(100); m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(100));
QVERIFY2(serverRemovedSpy.count() == 0, "serverRemoved should NOT be emitted for invalid index"); QVERIFY2(serverRemovedSpy.count() == 0, "serverRemoved should NOT be emitted for invalid index");
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 1, "Server count should remain 1"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 1, "Server count should remain 1");
ServerConfig serverConfig = m_coreController->m_serversController->getServerConfig(0); const QString validServerId = m_coreController->m_serversController->getServerId(0);
m_coreController->m_serversController->editServer(-1, serverConfig); const serverConfigUtils::ConfigType editKind =
m_coreController->m_serversRepository->serverKind(validServerId);
m_coreController->m_serversRepository->editServer(m_coreController->m_serversController->getServerId(-1),
QJsonObject(), editKind);
QVERIFY2(serverEditedSpy.count() == 0, "serverEdited should NOT be emitted for invalid index"); QVERIFY2(serverEditedSpy.count() == 0, "serverEdited should NOT be emitted for invalid index");
m_coreController->m_serversController->editServer(10, serverConfig); m_coreController->m_serversRepository->editServer(m_coreController->m_serversController->getServerId(10),
QJsonObject(), editKind);
QVERIFY2(serverEditedSpy.count() == 0, "serverEdited should NOT be emitted for invalid index"); QVERIFY2(serverEditedSpy.count() == 0, "serverEdited should NOT be emitted for invalid index");
m_coreController->m_serversController->setDefaultServerIndex(-1); m_coreController->m_serversController->setDefaultServer(m_coreController->m_serversController->getServerId(-1));
QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged should NOT be emitted for invalid index"); QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged should NOT be emitted for invalid index");
m_coreController->m_serversController->setDefaultServerIndex(10); m_coreController->m_serversController->setDefaultServer(m_coreController->m_serversController->getServerId(10));
QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged should NOT be emitted for invalid index"); QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged should NOT be emitted for invalid index");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default server index should remain 0"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default server index should remain 0");
} }
@@ -86,14 +93,15 @@ private slots:
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 0, "Should start with 0 servers"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 0, "Should start with 0 servers");
ServerConfig emptyConfig = SelfHostedServerConfig{}; m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(0));
m_coreController->m_serversController->removeServer(0);
QVERIFY2(serverRemovedSpy.count() == 0, "serverRemoved should NOT be emitted for empty repository"); QVERIFY2(serverRemovedSpy.count() == 0, "serverRemoved should NOT be emitted for empty repository");
m_coreController->m_serversController->editServer(0, emptyConfig); m_coreController->m_serversRepository->editServer(m_coreController->m_serversController->getServerId(0),
SelfHostedAdminServerConfig {}.toJson(),
serverConfigUtils::ConfigType::SelfHostedAdmin);
QVERIFY2(serverEditedSpy.count() == 0, "serverEdited should NOT be emitted for empty repository"); QVERIFY2(serverEditedSpy.count() == 0, "serverEdited should NOT be emitted for empty repository");
m_coreController->m_serversController->setDefaultServerIndex(0); m_coreController->m_serversController->setDefaultServer(m_coreController->m_serversController->getServerId(0));
QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged should NOT be emitted for empty repository"); QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged should NOT be emitted for empty repository");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default server index should be 0 for empty repository"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default server index should be 0 for empty repository");
+16 -22
View File
@@ -5,7 +5,8 @@
#include <QSignalSpy> #include <QSignalSpy>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h" #include "core/models/serverDescription.h"
#include "tests/testServerRepositoryHelpers.h"
#include "ui/models/serversModel.h" #include "ui/models/serversModel.h"
#include "vpnConnection.h" #include "vpnConnection.h"
#include "secureQSettings.h" #include "secureQSettings.h"
@@ -39,7 +40,7 @@ private slots:
m_settings->clearSettings(); m_settings->clearSettings();
m_coreController->m_serversRepository->invalidateCache(); m_coreController->m_serversRepository->invalidateCache();
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
m_coreController->m_serversModel->updateModel(QVector<ServerConfig>(), -1, false); m_coreController->m_serversModel->updateModel(QVector<ServerDescription>(), -1);
} }
} }
@@ -52,20 +53,17 @@ private slots:
QVERIFY2(importFinishedSpy.count() == 1, "Import should succeed"); QVERIFY2(importFinishedSpy.count() == 1, "Import should succeed");
QSignalSpy serverEditedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverEdited); QSignalSpy serverEditedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverEdited);
QSignalSpy gatewayStacksExpandedSpy(m_coreController->m_serversController, &ServersController::gatewayStacksExpanded);
ServerConfig serverConfig = m_coreController->m_serversController->getServerConfig(0); amnezia::test::setServerDescription(m_coreController->m_serversRepository,
serverConfig.visit([](auto& arg) { m_coreController->m_serversController->getServerId(0),
arg.description = "Edited AWG Server"; QStringLiteral("Edited AWG Server"));
});
m_coreController->m_serversController->editServer(0, serverConfig);
QVERIFY2(serverEditedSpy.count() == 1, "serverEdited signal should be emitted"); QVERIFY2(serverEditedSpy.count() == 1, "serverEdited signal should be emitted");
QVERIFY2(serverEditedSpy.at(0).at(0).toInt() == 0, "serverEdited should emit index 0"); QVERIFY2(serverEditedSpy.at(0).at(0).toString() == m_coreController->m_serversRepository->serverIdAt(0),
"serverEdited should emit edited server id");
ServerConfig editedServer = m_coreController->m_serversRepository->server(0); const QString editedDesc = amnezia::test::serverDescription(m_coreController->m_serversRepository,
QString editedDesc = editedServer.description(); m_coreController->m_serversRepository->serverIdAt(0));
QVERIFY2(editedDesc == "Edited AWG Server", "Server description should be updated"); QVERIFY2(editedDesc == "Edited AWG Server", "Server description should be updated");
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
@@ -87,20 +85,16 @@ private slots:
QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged); QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged);
ServerConfig defaultServerConfig = m_coreController->m_serversController->getServerConfig(1); amnezia::test::setServerDescription(m_coreController->m_serversRepository,
defaultServerConfig.visit([](auto& arg) { m_coreController->m_serversController->getServerId(1),
arg.description = "Edited Default Server"; QStringLiteral("Edited Default Server"));
});
m_coreController->m_serversController->editServer(1, defaultServerConfig);
QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged should NOT be emitted when editing default server"); QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged should NOT be emitted when editing default server");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Default server index should remain 1"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Default server index should remain 1");
ServerConfig nonDefaultServerConfig = m_coreController->m_serversController->getServerConfig(0); amnezia::test::setServerDescription(m_coreController->m_serversRepository,
nonDefaultServerConfig.visit([](auto& arg) { m_coreController->m_serversController->getServerId(0),
arg.description = "Edited Non-Default Server"; QStringLiteral("Edited Non-Default Server"));
});
m_coreController->m_serversController->editServer(0, nonDefaultServerConfig);
QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged should NOT be emitted when editing non-default server"); QVERIFY2(defaultServerChangedSpy.count() == 0, "defaultServerChanged should NOT be emitted when editing non-default server");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Default server index should remain 1"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 1, "Default server index should remain 1");
@@ -0,0 +1,93 @@
#ifndef TESTSERVERREPOSITORYHELPERS_H
#define TESTSERVERREPOSITORYHELPERS_H
#include <QString>
#include <QJsonObject>
#include "core/repositories/secureServersRepository.h"
#include "core/utils/serverConfigUtils.h"
namespace amnezia::test
{
inline QString serverDescription(SecureServersRepository *repo, const QString &serverId)
{
switch (repo->serverKind(serverId)) {
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
const auto cfg = repo->selfHostedAdminConfig(serverId);
return cfg.has_value() ? cfg->description : QString();
}
case serverConfigUtils::ConfigType::SelfHostedUser: {
const auto cfg = repo->selfHostedUserConfig(serverId);
return cfg.has_value() ? cfg->description : QString();
}
case serverConfigUtils::ConfigType::Native: {
const auto cfg = repo->nativeConfig(serverId);
return cfg.has_value() ? cfg->description : QString();
}
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
case serverConfigUtils::ConfigType::AmneziaFreeV3:
case serverConfigUtils::ConfigType::ExternalPremium: {
const auto cfg = repo->apiV2Config(serverId);
return cfg.has_value() ? cfg->description : QString();
}
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
case serverConfigUtils::ConfigType::AmneziaFreeV2: {
const auto cfg = repo->legacyApiConfig(serverId);
return cfg.has_value() ? cfg->description : QString();
}
case serverConfigUtils::ConfigType::Invalid:
default:
return {};
}
}
inline void setServerDescription(SecureServersRepository *repo, const QString &serverId, const QString &description)
{
const serverConfigUtils::ConfigType kind = repo->serverKind(serverId);
switch (kind) {
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
auto cfg = repo->selfHostedAdminConfig(serverId);
if (!cfg.has_value()) return;
cfg->description = description;
cfg->displayName = description;
repo->editServer(serverId, cfg->toJson(), kind);
return;
}
case serverConfigUtils::ConfigType::SelfHostedUser: {
auto cfg = repo->selfHostedUserConfig(serverId);
if (!cfg.has_value()) return;
cfg->description = description;
cfg->displayName = description;
repo->editServer(serverId, cfg->toJson(), kind);
return;
}
case serverConfigUtils::ConfigType::Native: {
auto cfg = repo->nativeConfig(serverId);
if (!cfg.has_value()) return;
cfg->description = description;
cfg->displayName = description;
repo->editServer(serverId, cfg->toJson(), kind);
return;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
case serverConfigUtils::ConfigType::AmneziaFreeV3:
case serverConfigUtils::ConfigType::ExternalPremium: {
auto cfg = repo->apiV2Config(serverId);
if (!cfg.has_value()) return;
cfg->description = description;
cfg->displayName = description;
repo->editServer(serverId, cfg->toJson(), kind);
return;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
case serverConfigUtils::ConfigType::AmneziaFreeV2:
case serverConfigUtils::ConfigType::Invalid:
default:
return;
}
}
} // namespace amnezia::test
#endif
+8 -9
View File
@@ -5,7 +5,8 @@
#include <QSignalSpy> #include <QSignalSpy>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h" #include "core/models/serverDescription.h"
#include "tests/testServerRepositoryHelpers.h"
#include "ui/models/serversModel.h" #include "ui/models/serversModel.h"
#include "vpnConnection.h" #include "vpnConnection.h"
#include "secureQSettings.h" #include "secureQSettings.h"
@@ -38,7 +39,7 @@ private slots:
void init() { void init() {
m_settings->clearSettings(); m_settings->clearSettings();
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
m_coreController->m_serversModel->updateModel(QVector<ServerConfig>(), -1, false); m_coreController->m_serversModel->updateModel(QVector<ServerDescription>(), -1);
} }
} }
@@ -58,16 +59,14 @@ private slots:
QString modelDesc1 = m_coreController->m_serversModel->data(m_coreController->m_serversModel->index(0, 0), ServersModel::NameRole).toString(); QString modelDesc1 = m_coreController->m_serversModel->data(m_coreController->m_serversModel->index(0, 0), ServersModel::NameRole).toString();
QVERIFY2(modelDesc1 == "AWG Server", "Model should have correct server name"); QVERIFY2(modelDesc1 == "AWG Server", "Model should have correct server name");
ServerConfig serverConfig = m_coreController->m_serversController->getServerConfig(0); amnezia::test::setServerDescription(m_coreController->m_serversRepository,
serverConfig.visit([](auto& arg) { m_coreController->m_serversController->getServerId(0),
arg.description = "Edited AWG Server"; QStringLiteral("Edited AWG Server"));
});
m_coreController->m_serversController->editServer(0, serverConfig);
QString modelDesc2 = m_coreController->m_serversModel->data(m_coreController->m_serversModel->index(0, 0), ServersModel::NameRole).toString(); QString modelDesc2 = m_coreController->m_serversModel->data(m_coreController->m_serversModel->index(0, 0), ServersModel::NameRole).toString();
QVERIFY2(modelDesc2 == "Edited AWG Server", "Model should be updated after edit"); QVERIFY2(modelDesc2 == "Edited AWG Server", "Model should be updated after edit");
m_coreController->m_serversController->removeServer(0); m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(0));
QVERIFY2(m_coreController->m_serversModel->rowCount() == 0, "Model should have 0 rows after removal"); QVERIFY2(m_coreController->m_serversModel->rowCount() == 0, "Model should have 0 rows after removal");
} }
@@ -98,7 +97,7 @@ private slots:
QVERIFY2(!isDefault1, "Server 1 should not be default"); QVERIFY2(!isDefault1, "Server 1 should not be default");
QVERIFY2(isDefault2, "Server 2 should be default"); QVERIFY2(isDefault2, "Server 2 should be default");
m_coreController->m_serversController->setDefaultServerIndex(0); m_coreController->m_serversController->setDefaultServer(m_coreController->m_serversController->getServerId(0));
isDefault0 = m_coreController->m_serversModel->data(m_coreController->m_serversModel->index(0, 0), ServersModel::IsDefaultRole).toBool(); isDefault0 = m_coreController->m_serversModel->data(m_coreController->m_serversModel->index(0, 0), ServersModel::IsDefaultRole).toBool();
isDefault2 = m_coreController->m_serversModel->data(m_coreController->m_serversModel->index(2, 0), ServersModel::IsDefaultRole).toBool(); isDefault2 = m_coreController->m_serversModel->data(m_coreController->m_serversModel->index(2, 0), ServersModel::IsDefaultRole).toBool();
-1
View File
@@ -6,7 +6,6 @@
#include <QLocale> #include <QLocale>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h"
#include "ui/controllers/settingsUiController.h" #include "ui/controllers/settingsUiController.h"
#include "ui/controllers/languageUiController.h" #include "ui/controllers/languageUiController.h"
#include "ui/models/allowedDnsModel.h" #include "ui/models/allowedDnsModel.h"
+5 -4
View File
@@ -5,7 +5,7 @@
#include <QSignalSpy> #include <QSignalSpy>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h" #include "core/models/serverDescription.h"
#include "vpnConnection.h" #include "vpnConnection.h"
#include "secureQSettings.h" #include "secureQSettings.h"
@@ -38,7 +38,7 @@ private slots:
m_settings->clearSettings(); m_settings->clearSettings();
m_coreController->m_serversRepository->invalidateCache(); m_coreController->m_serversRepository->invalidateCache();
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
m_coreController->m_serversModel->updateModel(QVector<ServerConfig>(), -1, false); m_coreController->m_serversModel->updateModel(QVector<ServerDescription>(), -1);
} }
} }
@@ -73,11 +73,12 @@ private slots:
QSignalSpy serverRemovedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverRemoved); QSignalSpy serverRemovedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverRemoved);
QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged); QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged);
m_coreController->m_serversController->removeServer(1); m_coreController->m_serversController->removeServer(m_coreController->m_serversController->getServerId(1));
QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted"); QVERIFY2(serverRemovedSpy.count() == 1, "serverRemoved signal should be emitted");
QVERIFY2(defaultServerChangedSpy.count() == 1, "defaultServerChanged signal should be emitted when removing default server"); QVERIFY2(defaultServerChangedSpy.count() == 1, "defaultServerChanged signal should be emitted when removing default server");
QVERIFY2(defaultServerChangedSpy.at(0).at(0).toInt() == 0, "defaultServerChanged should emit new default index 0"); QVERIFY2(defaultServerChangedSpy.at(0).at(0).toString() == m_coreController->m_serversRepository->defaultServerId(),
"defaultServerChanged should emit new default server id");
QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default server index should be 0"); QVERIFY2(m_coreController->m_serversRepository->defaultServerIndex() == 0, "Default server index should be 0");
} }
}; };
@@ -8,7 +8,7 @@
#include <QModelIndex> #include <QModelIndex>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "core/models/serverConfig.h" #include "core/models/serverDescription.h"
#include "core/controllers/selfhosted/importController.h" #include "core/controllers/selfhosted/importController.h"
#include "ui/models/serversModel.h" #include "ui/models/serversModel.h"
#include "ui/models/containersModel.h" #include "ui/models/containersModel.h"
@@ -23,6 +23,18 @@ using namespace amnezia;
using namespace amnezia; using namespace amnezia;
namespace {
int defaultServerRow(const QVector<ServerDescription> &descriptions, const QString &defaultServerId)
{
for (int i = 0; i < descriptions.size(); ++i) {
if (descriptions.at(i).serverId == defaultServerId) {
return i;
}
}
return -1;
}
} // namespace
class TestUiServersModelAndController : public QObject class TestUiServersModelAndController : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -119,7 +131,7 @@ private slots:
void init() { void init() {
m_settings->clearSettings(); m_settings->clearSettings();
if (m_coreController->m_serversModel) { if (m_coreController->m_serversModel) {
m_coreController->m_serversModel->updateModel(QVector<ServerConfig>(), -1, false); m_coreController->m_serversModel->updateModel(QVector<ServerDescription>(), -1);
} }
} }
@@ -166,11 +178,9 @@ private slots:
} }
if (m_coreController->m_serversUiController) { if (m_coreController->m_serversUiController) {
m_coreController->m_serversUiController->setProcessedServerIndex(serverIndex); m_coreController->m_serversUiController->setProcessedServerId(
m_coreController->m_serversUiController->getServerId(0));
ServerConfig serverConfig = m_coreController->m_serversRepository->server(serverIndex);
QString actualServerName = serverConfig.description();
QString containerName = ContainerUtils::containerHumanNames().value(DockerContainer::Awg);
QString hostName = "test.example.com"; QString hostName = "test.example.com";
QString collapsedDescription = m_coreController->m_serversUiController->getDefaultServerDescriptionCollapsed(); QString collapsedDescription = m_coreController->m_serversUiController->getDefaultServerDescriptionCollapsed();
@@ -261,27 +271,29 @@ private slots:
m_coreController->m_importCoreController->importConfig(configNoDns); m_coreController->m_importCoreController->importConfig(configNoDns);
QVERIFY2(importFinishedSpy.count() == 1, "importFinished should be emitted"); QVERIFY2(importFinishedSpy.count() == 1, "importFinished should be emitted");
m_coreController->m_appSettingsRepository->setUseAmneziaDns(false); m_coreController->m_appSettingsRepository->setUseAmneziaDns(false);
m_coreController->m_serversModel->updateModel( QVector<ServerDescription> descriptionsNoDns = m_coreController->m_serversController->buildServerDescriptions(
m_coreController->m_serversRepository->servers(),
m_coreController->m_serversRepository->defaultServerIndex(),
m_coreController->m_appSettingsRepository->useAmneziaDns()); m_coreController->m_appSettingsRepository->useAmneziaDns());
const QString defIdNoDns = m_coreController->m_serversRepository->defaultServerId();
m_coreController->m_serversModel->updateModel(descriptionsNoDns, defaultServerRow(descriptionsNoDns, defIdNoDns));
QString descNoDns = m_coreController->m_serversModel->data( QString descNoDns = m_coreController->m_serversModel->data(
m_coreController->m_serversModel->index(0, 0), ServersModel::ServerDescriptionRole).toString(); m_coreController->m_serversModel->index(0, 0), ServersModel::ServerDescriptionRole).toString();
QVERIFY2(descNoDns == "test.example.com", QVERIFY2(descNoDns == "test.example.com",
QString("Without Amnezia DNS expected 'test.example.com', got '%1'").arg(descNoDns).toUtf8().constData()); QString("Without Amnezia DNS expected 'test.example.com', got '%1'").arg(descNoDns).toUtf8().constData());
m_coreController->m_serversRepository->setServersArray(QJsonArray()); m_coreController->m_serversRepository->clearServers();
m_coreController->m_serversRepository->setDefaultServer(0); if (m_coreController->m_serversRepository->serversCount() > 0) {
m_coreController->m_serversRepository->setDefaultServer(m_coreController->m_serversRepository->serverIdAt(0));
}
QJsonObject configWithDns = createServerDescriptionTestConfig(true); QJsonObject configWithDns = createServerDescriptionTestConfig(true);
m_coreController->m_importCoreController->importConfig(configWithDns); m_coreController->m_importCoreController->importConfig(configWithDns);
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 1, "Server should be imported"); QVERIFY2(m_coreController->m_serversRepository->serversCount() == 1, "Server should be imported");
m_coreController->m_appSettingsRepository->setUseAmneziaDns(true); m_coreController->m_appSettingsRepository->setUseAmneziaDns(true);
m_coreController->m_serversModel->updateModel( QVector<ServerDescription> descriptionsWithDns = m_coreController->m_serversController->buildServerDescriptions(
m_coreController->m_serversRepository->servers(),
m_coreController->m_serversRepository->defaultServerIndex(),
m_coreController->m_appSettingsRepository->useAmneziaDns()); m_coreController->m_appSettingsRepository->useAmneziaDns());
const QString defIdWithDns = m_coreController->m_serversRepository->defaultServerId();
m_coreController->m_serversModel->updateModel(descriptionsWithDns, defaultServerRow(descriptionsWithDns, defIdWithDns));
QString descWithDns = m_coreController->m_serversModel->data( QString descWithDns = m_coreController->m_serversModel->data(
m_coreController->m_serversModel->index(0, 0), ServersModel::ServerDescriptionRole).toString(); m_coreController->m_serversModel->index(0, 0), ServersModel::ServerDescriptionRole).toString();
@@ -2,14 +2,13 @@
#include "amneziaApplication.h" #include "amneziaApplication.h"
#include "core/configurators/wireguardConfigurator.h" #include "core/configurators/wireguardConfigurator.h"
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
#include "core/utils/api/apiUtils.h" #include "core/utils/api/apiUtils.h"
#include "core/utils/qrCodeUtils.h" #include "core/utils/qrCodeUtils.h"
#include "ui/controllers/systemController.h" #include "ui/controllers/systemController.h"
#include "version.h" #include "version.h"
#include "core/models/serverConfig.h"
#include <QClipboard> #include <QClipboard>
#include <QDebug> #include <QDebug>
#include <QSet> #include <QSet>
@@ -67,7 +66,17 @@ SubscriptionUiController::SubscriptionUiController(ServersController* serversCon
ApiDevicesModel* apiDevicesModel, ApiDevicesModel* apiDevicesModel,
SettingsController* settingsController, SettingsController* settingsController,
QObject *parent) QObject *parent)
: QObject(parent), m_serversController(serversController), m_apiServicesModel(apiServicesModel), m_servicesCatalogController(servicesCatalogController), m_subscriptionController(subscriptionController), m_apiSubscriptionPlansModel(apiSubscriptionPlansModel), m_apiBenefitsModel(apiBenefitsModel), m_apiAccountInfoModel(apiAccountInfoModel), m_apiCountryModel(apiCountryModel), m_apiDevicesModel(apiDevicesModel), m_settingsController(settingsController) : QObject(parent),
m_serversController(serversController),
m_apiServicesModel(apiServicesModel),
m_servicesCatalogController(servicesCatalogController),
m_subscriptionController(subscriptionController),
m_apiSubscriptionPlansModel(apiSubscriptionPlansModel),
m_apiBenefitsModel(apiBenefitsModel),
m_apiAccountInfoModel(apiAccountInfoModel),
m_apiCountryModel(apiCountryModel),
m_apiDevicesModel(apiDevicesModel),
m_settingsController(settingsController)
{ {
connect(m_apiServicesModel, &ApiServicesModel::serviceSelectionChanged, this, [this]() { connect(m_apiServicesModel, &ApiServicesModel::serviceSelectionChanged, this, [this]() {
ApiServicesModel::ApiServicesData selectedServiceData = m_apiServicesModel->selectedServiceData(); ApiServicesModel::ApiServicesData selectedServiceData = m_apiServicesModel->selectedServiceData();
@@ -76,14 +85,14 @@ SubscriptionUiController::SubscriptionUiController(ServersController* serversCon
}); });
} }
bool SubscriptionUiController::exportVpnKey(int serverIndex, const QString &fileName) bool SubscriptionUiController::exportVpnKey(const QString &serverId, const QString &fileName)
{ {
if (fileName.isEmpty()) { if (fileName.isEmpty()) {
emit errorOccurred(ErrorCode::PermissionsError); emit errorOccurred(ErrorCode::PermissionsError);
return false; return false;
} }
prepareVpnKeyExport(serverIndex); prepareVpnKeyExport(serverId);
if (m_vpnKey.isEmpty()) { if (m_vpnKey.isEmpty()) {
emit errorOccurred(ErrorCode::ApiConfigEmptyError); emit errorOccurred(ErrorCode::ApiConfigEmptyError);
return false; return false;
@@ -93,7 +102,8 @@ bool SubscriptionUiController::exportVpnKey(int serverIndex, const QString &file
return true; return true;
} }
bool SubscriptionUiController::exportNativeConfig(int serverIndex, const QString &serverCountryCode, const QString &fileName)
bool SubscriptionUiController::exportNativeConfig(const QString &serverId, const QString &serverCountryCode, const QString &fileName)
{ {
if (fileName.isEmpty()) { if (fileName.isEmpty()) {
emit errorOccurred(ErrorCode::PermissionsError); emit errorOccurred(ErrorCode::PermissionsError);
@@ -101,7 +111,7 @@ bool SubscriptionUiController::exportNativeConfig(int serverIndex, const QString
} }
QString nativeConfig; QString nativeConfig;
ErrorCode errorCode = m_subscriptionController->exportNativeConfig(serverIndex, serverCountryCode, nativeConfig); ErrorCode errorCode = m_subscriptionController->exportNativeConfig(serverId, serverCountryCode, nativeConfig);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
emit errorOccurred(errorCode); emit errorOccurred(errorCode);
return false; return false;
@@ -111,9 +121,10 @@ bool SubscriptionUiController::exportNativeConfig(int serverIndex, const QString
return true; return true;
} }
bool SubscriptionUiController::revokeNativeConfig(int serverIndex, const QString &serverCountryCode)
bool SubscriptionUiController::revokeNativeConfig(const QString &serverId, const QString &serverCountryCode)
{ {
ErrorCode errorCode = m_subscriptionController->revokeNativeConfig(serverIndex, serverCountryCode); ErrorCode errorCode = m_subscriptionController->revokeNativeConfig(serverId, serverCountryCode);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
emit errorOccurred(errorCode); emit errorOccurred(errorCode);
return false; return false;
@@ -121,10 +132,11 @@ bool SubscriptionUiController::revokeNativeConfig(int serverIndex, const QString
return true; return true;
} }
void SubscriptionUiController::prepareVpnKeyExport(int serverIndex)
void SubscriptionUiController::prepareVpnKeyExport(const QString &serverId)
{ {
QString vpnKey; QString vpnKey;
ErrorCode errorCode = m_subscriptionController->prepareVpnKeyExport(serverIndex, vpnKey); ErrorCode errorCode = m_subscriptionController->prepareVpnKeyExport(serverId, vpnKey);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
emit errorOccurred(errorCode); emit errorOccurred(errorCode);
return; return;
@@ -140,6 +152,7 @@ void SubscriptionUiController::prepareVpnKeyExport(int serverIndex)
emit vpnKeyExportReady(); emit vpnKeyExportReady();
} }
void SubscriptionUiController::copyVpnKeyToClipboard() void SubscriptionUiController::copyVpnKeyToClipboard()
{ {
auto clipboard = amnApp->getClipboard(); auto clipboard = amnApp->getClipboard();
@@ -170,14 +183,12 @@ bool SubscriptionUiController::importPremiumFromAppStore(const QString &storePro
productId = QStringLiteral("amnezia_premium_6_month"); productId = QStringLiteral("amnezia_premium_6_month");
} }
ServerConfig serverConfig;
int duplicateServerIndex = -1; int duplicateServerIndex = -1;
ErrorCode errorCode = m_subscriptionController->processAppStorePurchase( ErrorCode errorCode = m_subscriptionController->processAppStorePurchase(
m_apiServicesModel->getCountryCode(), m_apiServicesModel->getCountryCode(),
m_apiServicesModel->getSelectedServiceType(), m_apiServicesModel->getSelectedServiceType(),
m_apiServicesModel->getSelectedServiceProtocol(), m_apiServicesModel->getSelectedServiceProtocol(),
productId, productId,
serverConfig,
&duplicateServerIndex); &duplicateServerIndex);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
@@ -260,11 +271,8 @@ bool SubscriptionUiController::importFreeFromGateway()
} }
SubscriptionController::ProtocolData protocolData = m_subscriptionController->generateProtocolData(serviceProtocol); SubscriptionController::ProtocolData protocolData = m_subscriptionController->generateProtocolData(serviceProtocol);
ServerConfig serverConfig;
ErrorCode errorCode = m_subscriptionController->importServiceFromGateway(userCountryCode, serviceType, ErrorCode errorCode = m_subscriptionController->importServiceFromGateway(userCountryCode, serviceType,
serviceProtocol, protocolData, serviceProtocol, protocolData);
serverConfig);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
emit installServerFromApiFinished(tr("%1 installed successfully.").arg(m_apiServicesModel->getSelectedServiceName())); emit installServerFromApiFinished(tr("%1 installed successfully.").arg(m_apiServicesModel->getSelectedServiceName()));
@@ -278,12 +286,10 @@ bool SubscriptionUiController::importFreeFromGateway()
bool SubscriptionUiController::importTrialFromGateway(const QString &email) bool SubscriptionUiController::importTrialFromGateway(const QString &email)
{ {
emit trialEmailError(QString()); emit trialEmailError(QString());
ServerConfig serverConfig;
ErrorCode errorCode = m_subscriptionController->importTrialFromGateway(m_apiServicesModel->getCountryCode(), ErrorCode errorCode = m_subscriptionController->importTrialFromGateway(m_apiServicesModel->getCountryCode(),
m_apiServicesModel->getSelectedServiceType(), m_apiServicesModel->getSelectedServiceType(),
m_apiServicesModel->getSelectedServiceProtocol(), m_apiServicesModel->getSelectedServiceProtocol(),
email, email);
serverConfig);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
if (errorCode == ErrorCode::ApiTrialAlreadyUsedError) { if (errorCode == ErrorCode::ApiTrialAlreadyUsedError) {
emit trialEmailError( emit trialEmailError(
@@ -298,21 +304,17 @@ bool SubscriptionUiController::importTrialFromGateway(const QString &email)
return true; return true;
} }
bool SubscriptionUiController::updateServiceFromGateway(const int serverIndex, const QString &newCountryCode, const QString &newCountryName, bool SubscriptionUiController::updateServiceFromGateway(const QString &serverId, const QString &newCountryCode, const QString &newCountryName,
bool reloadServiceConfig) bool reloadServiceConfig)
{ {
bool isConnectEvent = newCountryCode.isEmpty() && newCountryName.isEmpty() && !reloadServiceConfig; bool isConnectEvent = newCountryCode.isEmpty() && newCountryName.isEmpty() && !reloadServiceConfig;
bool wasSubscriptionExpired = false; bool wasSubscriptionExpired = false;
ServerConfig oldServerConfig = m_serversController->getServerConfig(serverIndex); if (const auto oldApiV2 = m_serversController->apiV2Config(serverId)) {
if (oldServerConfig.isApiV2()) { wasSubscriptionExpired = oldApiV2->apiConfig.subscriptionExpiredByServer
const ApiV2ServerConfig *oldApiV2 = oldServerConfig.as<ApiV2ServerConfig>(); || oldApiV2->apiConfig.isSubscriptionExpired();
if (oldApiV2) {
wasSubscriptionExpired = oldApiV2->apiConfig.subscriptionExpiredByServer
|| oldApiV2->apiConfig.isSubscriptionExpired();
}
} }
ErrorCode errorCode = m_subscriptionController->updateServiceFromGateway(serverIndex, newCountryCode, isConnectEvent); ErrorCode errorCode = m_subscriptionController->updateServiceFromGateway(serverId, newCountryCode, isConnectEvent);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
if (wasSubscriptionExpired) { if (wasSubscriptionExpired) {
@@ -336,27 +338,10 @@ bool SubscriptionUiController::updateServiceFromGateway(const int serverIndex, c
} }
} }
bool SubscriptionUiController::updateServiceFromTelegram(const int serverIndex)
bool SubscriptionUiController::deactivateDevice(const QString &serverId)
{ {
#ifdef Q_OS_IOS ErrorCode errorCode = m_subscriptionController->deactivateDevice(serverId);
IosController::Instance()->requestInetAccess();
QThread::msleep(10);
#endif
ErrorCode errorCode = m_subscriptionController->updateServiceFromTelegram(serverIndex);
if (errorCode == ErrorCode::NoError) {
emit updateServerFromApiFinished();
return true;
} else {
emit errorOccurred(errorCode);
return false;
}
}
bool SubscriptionUiController::deactivateDevice(int serverIndex)
{
ErrorCode errorCode = m_subscriptionController->deactivateDevice(serverIndex);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
emit errorOccurred(errorCode); emit errorOccurred(errorCode);
return false; return false;
@@ -365,9 +350,10 @@ bool SubscriptionUiController::deactivateDevice(int serverIndex)
return true; return true;
} }
bool SubscriptionUiController::deactivateExternalDevice(int serverIndex, const QString &uuid, const QString &serverCountryCode)
bool SubscriptionUiController::deactivateExternalDevice(const QString &serverId, const QString &uuid, const QString &serverCountryCode)
{ {
ErrorCode errorCode = m_subscriptionController->deactivateExternalDevice(serverIndex, uuid, serverCountryCode); ErrorCode errorCode = m_subscriptionController->deactivateExternalDevice(serverId, uuid, serverCountryCode);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
emit errorOccurred(errorCode); emit errorOccurred(errorCode);
return false; return false;
@@ -376,12 +362,19 @@ bool SubscriptionUiController::deactivateExternalDevice(int serverIndex, const Q
return true; return true;
} }
void SubscriptionUiController::validateConfig() void SubscriptionUiController::validateConfig()
{ {
int serverIndex = m_serversController->getDefaultServerIndex(); const QString serverId = m_serversController->getDefaultServerId();
bool hasInstalledContainers = m_serversController->hasInstalledContainers(serverIndex); if (!serverId.isEmpty() && m_serversController->isLegacyApiV1Server(serverId)) {
emit unsupportedConnectDrawerRequested();
emit configValidated(false);
return;
}
ErrorCode errorCode = m_subscriptionController->validateAndUpdateConfig(serverIndex, hasInstalledContainers); bool hasInstalledContainers = m_serversController->hasInstalledContainers(serverId);
ErrorCode errorCode = m_subscriptionController->validateAndUpdateConfig(serverId, hasInstalledContainers);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
if (errorCode == ErrorCode::ApiSubscriptionExpiredError) { if (errorCode == ErrorCode::ApiSubscriptionExpiredError) {
@@ -395,22 +388,25 @@ void SubscriptionUiController::validateConfig()
emit configValidated(true); emit configValidated(true);
} }
void SubscriptionUiController::setCurrentProtocol(int serverIndex, const QString &protocolName) void SubscriptionUiController::setCurrentProtocol(const QString &serverId, const QString &protocolName)
{ {
m_subscriptionController->setCurrentProtocol(serverIndex, protocolName); m_subscriptionController->setCurrentProtocol(serverId, protocolName);
} }
bool SubscriptionUiController::isVlessProtocol(int serverIndex)
bool SubscriptionUiController::isVlessProtocol(const QString &serverId)
{ {
return m_subscriptionController->isVlessProtocol(serverIndex); return m_subscriptionController->isVlessProtocol(serverId);
} }
void SubscriptionUiController::removeApiConfig(int serverIndex)
void SubscriptionUiController::removeApiConfig(const QString &serverId)
{ {
m_subscriptionController->removeApiConfig(serverIndex); m_subscriptionController->removeApiConfig(serverId);
emit apiConfigRemoved(tr("Api config removed")); emit apiConfigRemoved(tr("Api config removed"));
} }
QList<QString> SubscriptionUiController::getQrCodes() QList<QString> SubscriptionUiController::getQrCodes()
{ {
return m_qrCodes; return m_qrCodes;
@@ -426,7 +422,7 @@ QString SubscriptionUiController::getVpnKey()
return m_vpnKey; return m_vpnKey;
} }
bool SubscriptionUiController::getAccountInfo(int serverIndex, bool reload) bool SubscriptionUiController::getAccountInfo(const QString &serverId, bool reload)
{ {
if (reload) { if (reload) {
QEventLoop wait; QEventLoop wait;
@@ -434,15 +430,18 @@ bool SubscriptionUiController::getAccountInfo(int serverIndex, bool reload)
wait.exec(QEventLoop::ExcludeUserInputEvents); wait.exec(QEventLoop::ExcludeUserInputEvents);
} }
QJsonObject accountInfo; QJsonObject accountInfo;
ErrorCode errorCode = m_subscriptionController->getAccountInfo(serverIndex, accountInfo); ErrorCode errorCode = m_subscriptionController->getAccountInfo(serverId, accountInfo);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
emit errorOccurred(errorCode); emit errorOccurred(errorCode);
return false; return false;
} }
ServerConfig serverConfig = m_serversController->getServerConfig(serverIndex); const auto apiV2 = m_serversController->apiV2Config(serverId);
QJsonObject serverConfigJson = serverConfig.toJson(); if (!apiV2.has_value()) {
m_apiAccountInfoModel->updateModel(accountInfo, serverConfigJson); emit errorOccurred(ErrorCode::InternalError);
return false;
}
m_apiAccountInfoModel->updateModel(accountInfo, apiV2->toJson());
if (reload) { if (reload) {
updateApiCountryModel(); updateApiCountryModel();
@@ -463,9 +462,9 @@ void SubscriptionUiController::updateApiDevicesModel()
m_apiDevicesModel->updateModel(m_apiAccountInfoModel->getIssuedConfigsInfo(), m_settingsController->getInstallationUuid(false)); m_apiDevicesModel->updateModel(m_apiAccountInfoModel->getIssuedConfigsInfo(), m_settingsController->getInstallationUuid(false));
} }
void SubscriptionUiController::getRenewalLink(int serverIndex) void SubscriptionUiController::getRenewalLink(const QString &serverId)
{ {
if (serverIndex < 0) { if (serverId.isEmpty()) {
emit errorOccurred(ErrorCode::InternalError); emit errorOccurred(ErrorCode::InternalError);
return; return;
} }
@@ -483,6 +482,6 @@ void SubscriptionUiController::getRenewalLink(int serverIndex)
} }
emit renewalLinkReceived(url); emit renewalLinkReceived(url);
}); });
watcher->setFuture(m_subscriptionController->getRenewalLink(serverIndex)); watcher->setFuture(m_subscriptionController->getRenewalLink(serverId));
} }
@@ -13,6 +13,7 @@
#include "ui/models/api/apiAccountInfoModel.h" #include "ui/models/api/apiAccountInfoModel.h"
#include "ui/models/api/apiCountryModel.h" #include "ui/models/api/apiCountryModel.h"
#include "ui/models/api/apiDevicesModel.h" #include "ui/models/api/apiDevicesModel.h"
class SubscriptionUiController : public QObject class SubscriptionUiController : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -34,10 +35,10 @@ public:
Q_PROPERTY(QString vpnKey READ getVpnKey NOTIFY vpnKeyExportReady) Q_PROPERTY(QString vpnKey READ getVpnKey NOTIFY vpnKeyExportReady)
public slots: public slots:
bool exportNativeConfig(int serverIndex, const QString &serverCountryCode, const QString &fileName); bool exportNativeConfig(const QString &serverId, const QString &serverCountryCode, const QString &fileName);
bool revokeNativeConfig(int serverIndex, const QString &serverCountryCode); bool revokeNativeConfig(const QString &serverId, const QString &serverCountryCode);
bool exportVpnKey(int serverIndex, const QString &fileName); bool exportVpnKey(const QString &serverId, const QString &fileName);
void prepareVpnKeyExport(int serverIndex); void prepareVpnKeyExport(const QString &serverId);
void copyVpnKeyToClipboard(); void copyVpnKeyToClipboard();
bool fillAvailableServices(); bool fillAvailableServices();
@@ -45,21 +46,21 @@ public slots:
bool importFreeFromGateway(); bool importFreeFromGateway();
bool restoreServiceFromAppStore(); bool restoreServiceFromAppStore();
bool importTrialFromGateway(const QString &email); bool importTrialFromGateway(const QString &email);
bool updateServiceFromGateway(const int serverIndex, const QString &newCountryCode, const QString &newCountryName, bool updateServiceFromGateway(const QString &serverId, const QString &newCountryCode, const QString &newCountryName,
bool reloadServiceConfig = false); bool reloadServiceConfig = false);
bool updateServiceFromTelegram(const int serverIndex); bool deactivateDevice(const QString &serverId);
bool deactivateDevice(int serverIndex); bool deactivateExternalDevice(const QString &serverId, const QString &uuid, const QString &serverCountryCode);
bool deactivateExternalDevice(int serverIndex, const QString &uuid, const QString &serverCountryCode);
void validateConfig(); void validateConfig();
void setCurrentProtocol(int serverIndex, const QString &protocolName); void setCurrentProtocol(const QString &serverId, const QString &protocolName);
bool isVlessProtocol(int serverIndex); bool isVlessProtocol(const QString &serverId);
void removeApiConfig(int serverIndex); void removeApiConfig(const QString &serverId);
bool getAccountInfo(const QString &serverId, bool reload);
void getRenewalLink(const QString &serverId);
bool getAccountInfo(int serverIndex, bool reload);
void getRenewalLink(int serverIndex);
void updateApiCountryModel(); void updateApiCountryModel();
void updateApiDevicesModel(); void updateApiDevicesModel();
@@ -80,6 +81,8 @@ signals:
void vpnKeyExportReady(); void vpnKeyExportReady();
void unsupportedConnectDrawerRequested();
private: private:
QList<QString> getQrCodes(); QList<QString> getQrCodes();
int getQrCodesCount(); int getQrCodesCount();
@@ -25,9 +25,12 @@ ConnectionUiController::ConnectionUiController(ConnectionController* connectionC
void ConnectionUiController::openConnection() void ConnectionUiController::openConnection()
{ {
int serverIndex = m_serversController->getDefaultServerIndex(); const QString serverId = m_serversController->getDefaultServerId();
if (serverId.isEmpty()) {
return;
}
ErrorCode errorCode = m_connectionController->openConnection(serverIndex); ErrorCode errorCode = m_connectionController->openConnection(serverId);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
emit connectionErrorOccurred(errorCode); emit connectionErrorOccurred(errorCode);
@@ -100,16 +103,6 @@ void ConnectionUiController::onConnectionStateChanged(Vpn::ConnectionState state
emit connectionStateChanged(); emit connectionStateChanged();
} }
void ConnectionUiController::onCurrentContainerUpdated()
{
if (m_isConnected || m_isConnectionInProgress) {
emit reconnectWithUpdatedContainer(tr("Settings updated successfully, reconnection..."));
openConnection();
} else {
emit reconnectWithUpdatedContainer(tr("Settings updated successfully"));
}
}
void ConnectionUiController::onTranslationsUpdated() void ConnectionUiController::onTranslationsUpdated()
{ {
onConnectionStateChanged(getCurrentConnectionState()); onConnectionStateChanged(getCurrentConnectionState());
@@ -38,8 +38,6 @@ public slots:
ErrorCode getLastConnectionError(); ErrorCode getLastConnectionError();
void onConnectionStateChanged(Vpn::ConnectionState state); void onConnectionStateChanged(Vpn::ConnectionState state);
void onCurrentContainerUpdated();
void onTranslationsUpdated(); void onTranslationsUpdated();
signals: signals:
+2 -10
View File
@@ -19,8 +19,7 @@
#include "ui/utils/macosUtil.h" #include "ui/utils/macosUtil.h"
#endif #endif
PageController::PageController(ServersController* serversController, PageController::PageController(ServersController* serversController, SettingsController* settingsController,
SettingsController* settingsController,
QObject *parent) QObject *parent)
: QObject(parent), m_serversController(serversController), m_settingsController(settingsController) : QObject(parent), m_serversController(serversController), m_settingsController(settingsController)
{ {
@@ -57,14 +56,7 @@ PageController::PageController(ServersController* serversController,
bool PageController::isStartPageVisible() bool PageController::isStartPageVisible()
{ {
if (m_serversController->getServersCount()) { return m_serversController->getServersCount() == 0;
if (m_serversController->getDefaultServerIndex() < 0) {
m_serversController->setDefaultServerIndex(0);
}
return false;
} else {
return true;
}
} }
QString PageController::getPagePath(PageLoader::PageEnum page) QString PageController::getPagePath(PageLoader::PageEnum page)
+3 -2
View File
@@ -94,8 +94,7 @@ class PageController : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit PageController(ServersController* serversController, explicit PageController(ServersController* serversController, SettingsController* settingsController,
SettingsController* settingsController,
QObject *parent = nullptr); QObject *parent = nullptr);
Q_PROPERTY(int safeAreaTopMargin READ getSafeAreaTopMargin NOTIFY safeAreaTopMarginChanged) Q_PROPERTY(int safeAreaTopMargin READ getSafeAreaTopMargin NOTIFY safeAreaTopMarginChanged)
@@ -164,6 +163,8 @@ signals:
void showPassphraseRequestDrawer(); void showPassphraseRequestDrawer();
void passphraseRequestDrawerClosed(QString passphrase); void passphraseRequestDrawerClosed(QString passphrase);
void unsupportedConnectDrawerRequested();
void escapePressed(); void escapePressed();
void closeTopDrawer(); void closeTopDrawer();
@@ -8,46 +8,46 @@ ExportUiController::ExportUiController(ExportController* exportController, QObje
{ {
} }
void ExportUiController::generateFullAccessConfig(int serverIndex) void ExportUiController::generateFullAccessConfig(const QString &serverId)
{ {
clearPreviousConfig(); clearPreviousConfig();
auto result = m_exportController->generateFullAccessConfig(serverIndex); auto result = m_exportController->generateFullAccessConfig(serverId);
applyExportResult(result); applyExportResult(result);
} }
void ExportUiController::generateConnectionConfig(int serverIndex, int containerIndex, const QString &clientName) void ExportUiController::generateConnectionConfig(const QString &serverId, int containerIndex, const QString &clientName)
{ {
clearPreviousConfig(); clearPreviousConfig();
auto result = m_exportController->generateConnectionConfig(serverIndex, containerIndex, clientName); auto result = m_exportController->generateConnectionConfig(serverId, containerIndex, clientName);
applyExportResult(result); applyExportResult(result);
} }
void ExportUiController::generateOpenVpnConfig(int serverIndex, const QString &clientName) void ExportUiController::generateOpenVpnConfig(const QString &serverId, const QString &clientName)
{ {
clearPreviousConfig(); clearPreviousConfig();
auto result = m_exportController->generateOpenVpnConfig(serverIndex, clientName); auto result = m_exportController->generateOpenVpnConfig(serverId, clientName);
applyExportResult(result); applyExportResult(result);
} }
void ExportUiController::generateWireGuardConfig(int serverIndex, const QString &clientName) void ExportUiController::generateWireGuardConfig(const QString &serverId, const QString &clientName)
{ {
clearPreviousConfig(); clearPreviousConfig();
auto result = m_exportController->generateWireGuardConfig(serverIndex, clientName); auto result = m_exportController->generateWireGuardConfig(serverId, clientName);
applyExportResult(result); applyExportResult(result);
} }
void ExportUiController::generateAwgConfig(int serverIndex, int containerIndex, const QString &clientName) void ExportUiController::generateAwgConfig(const QString &serverId, int containerIndex, const QString &clientName)
{ {
clearPreviousConfig(); clearPreviousConfig();
auto result = m_exportController->generateAwgConfig(serverIndex, containerIndex, clientName); auto result = m_exportController->generateAwgConfig(serverId, containerIndex, clientName);
applyExportResult(result); applyExportResult(result);
} }
void ExportUiController::generateXrayConfig(int serverIndex, const QString &clientName) void ExportUiController::generateXrayConfig(const QString &serverId, const QString &clientName)
{ {
clearPreviousConfig(); clearPreviousConfig();
auto result = m_exportController->generateXrayConfig(serverIndex, clientName); auto result = m_exportController->generateXrayConfig(serverId, clientName);
applyExportResult(result); applyExportResult(result);
} }
@@ -71,20 +71,20 @@ void ExportUiController::exportConfig(const QString &fileName)
SystemController::saveFile(fileName, m_config); SystemController::saveFile(fileName, m_config);
} }
void ExportUiController::updateClientManagementModel(int serverIndex, int containerIndex) void ExportUiController::updateClientManagementModel(const QString &serverId, int containerIndex)
{ {
m_exportController->updateClientManagementModel(serverIndex, containerIndex); m_exportController->updateClientManagementModel(serverId, containerIndex);
} }
void ExportUiController::revokeConfig(int row, int serverIndex, int containerIndex) void ExportUiController::revokeConfig(int row, const QString &serverId, int containerIndex)
{ {
m_exportController->revokeConfig(row, serverIndex, containerIndex); m_exportController->revokeConfig(row, serverId, containerIndex);
emit revokeConfigFinished(); emit revokeConfigFinished();
} }
void ExportUiController::renameClient(int row, const QString &clientName, int serverIndex, int containerIndex) void ExportUiController::renameClient(int row, const QString &clientName, const QString &serverId, int containerIndex)
{ {
m_exportController->renameClient(row, clientName, serverIndex, containerIndex); m_exportController->renameClient(row, clientName, serverId, containerIndex);
} }
int ExportUiController::getQrCodesCount() int ExportUiController::getQrCodesCount()
@@ -4,6 +4,7 @@
#include <QObject> #include <QObject>
#include "core/controllers/selfhosted/exportController.h" #include "core/controllers/selfhosted/exportController.h"
#include "core/utils/errorCodes.h"
class ExportUiController : public QObject class ExportUiController : public QObject
{ {
@@ -17,12 +18,13 @@ public:
Q_PROPERTY(QString nativeConfigString READ getNativeConfigString NOTIFY exportConfigChanged) Q_PROPERTY(QString nativeConfigString READ getNativeConfigString NOTIFY exportConfigChanged)
public slots: public slots:
void generateFullAccessConfig(int serverIndex); void generateFullAccessConfig(const QString &serverId);
void generateConnectionConfig(int serverIndex, int containerIndex, const QString &clientName);
void generateOpenVpnConfig(int serverIndex, const QString &clientName); void generateConnectionConfig(const QString &serverId, int containerIndex, const QString &clientName);
void generateWireGuardConfig(int serverIndex, const QString &clientName); void generateOpenVpnConfig(const QString &serverId, const QString &clientName);
void generateAwgConfig(int serverIndex, int containerIndex, const QString &clientName); void generateWireGuardConfig(const QString &serverId, const QString &clientName);
void generateXrayConfig(int serverIndex, const QString &clientName); void generateAwgConfig(const QString &serverId, int containerIndex, const QString &clientName);
void generateXrayConfig(const QString &serverId, const QString &clientName);
QString getConfig(); QString getConfig();
QString getNativeConfigString(); QString getNativeConfigString();
@@ -30,9 +32,11 @@ public slots:
void exportConfig(const QString &fileName); void exportConfig(const QString &fileName);
void updateClientManagementModel(int serverIndex, int containerIndex); void updateClientManagementModel(const QString &serverId, int containerIndex);
void revokeConfig(int row, int serverIndex, int containerIndex);
void renameClient(int row, const QString &clientName, int serverIndex, int containerIndex); void revokeConfig(int row, const QString &serverId, int containerIndex);
void renameClient(int row, const QString &clientName, const QString &serverId, int containerIndex);
signals: signals:
void generateConfig(int type); void generateConfig(int type);
@@ -11,7 +11,6 @@
#include "core/controllers/selfhosted/installController.h" #include "core/controllers/selfhosted/installController.h"
#include "core/utils/selfhosted/sshSession.h" #include "core/utils/selfhosted/sshSession.h"
#include "core/utils/networkUtilities.h" #include "core/utils/networkUtilities.h"
#include "logger.h"
#include "core/utils/protocolEnum.h" #include "core/utils/protocolEnum.h"
#include "core/protocols/protocolUtils.h" #include "core/protocols/protocolUtils.h"
#include "core/utils/constants/configKeys.h" #include "core/utils/constants/configKeys.h"
@@ -27,33 +26,12 @@
#include "ui/models/services/socks5ProxyConfigModel.h" #include "ui/models/services/socks5ProxyConfigModel.h"
#include "ui/models/services/torConfigModel.h" #include "ui/models/services/torConfigModel.h"
#include "core/utils/utilities.h" #include "core/utils/utilities.h"
#include "core/models/serverConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/models/protocols/awgProtocolConfig.h" #include "core/models/protocols/awgProtocolConfig.h"
#include "core/models/protocols/wireGuardProtocolConfig.h" #include "core/models/protocols/wireGuardProtocolConfig.h"
#include "core/models/protocols/openVpnProtocolConfig.h" #include "core/models/protocols/openVpnProtocolConfig.h"
#include "core/models/protocols/xrayProtocolConfig.h" #include "core/models/protocols/xrayProtocolConfig.h"
namespace
{
Logger logger("InstallUiController");
namespace configKey
{
constexpr char serviceInfo[] = "service_info";
constexpr char serviceType[] = "service_type";
constexpr char serviceProtocol[] = "service_protocol";
constexpr char userCountryCode[] = "user_country_code";
constexpr char serverCountryCode[] = "server_country_code";
constexpr char serverCountryName[] = "server_country_name";
constexpr char availableCountries[] = "available_countries";
constexpr char apiConfig[] = "api_config";
constexpr char authData[] = "auth_data";
}
}
InstallUiController::InstallUiController(InstallController *installController, InstallUiController::InstallUiController(InstallController *installController,
ServersController *serversController, ServersController *serversController,
SettingsController *settingsController, SettingsController *settingsController,
@@ -101,19 +79,18 @@ InstallUiController::~InstallUiController()
{ {
} }
void InstallUiController::install(DockerContainer container, int port, TransportProto transportProto, int serverIndex) void InstallUiController::install(DockerContainer container, int port, TransportProto transportProto, const QString &serverId)
{ {
const bool isNewServer = serverIndex < 0; const bool isNewServer = serverId.isEmpty();
ServerCredentials serverCredentials; ServerCredentials serverCredentials;
if (isNewServer) { if (isNewServer) {
serverCredentials = m_processedServerCredentials; serverCredentials = m_processedServerCredentials;
} else { } else {
serverCredentials = m_serversController->getServerCredentials(serverIndex); serverCredentials = m_serversController->getServerCredentials(serverId);
m_processedServerCredentials = ServerCredentials(); m_processedServerCredentials = ServerCredentials();
} }
QMap<DockerContainer, QJsonObject> preparedContainers;
QString finishMessage; QString finishMessage;
ErrorCode errorCode; ErrorCode errorCode;
@@ -131,9 +108,13 @@ void InstallUiController::install(DockerContainer container, int port, Transport
return; return;
} }
int serverIndex = m_serversController->getServersCount() - 1; const QString newServerId = m_serversController->getServerId(m_serversController->getServersCount() - 1);
ServerConfig serverConfig = m_serversController->getServerConfig(serverIndex); const auto admin = m_serversController->selfHostedAdminConfig(newServerId);
QMap<DockerContainer, ContainerConfig> containers = serverConfig.containers(); if (!admin.has_value()) {
emit installationErrorOccurred(ErrorCode::InternalError);
return;
}
QMap<DockerContainer, ContainerConfig> containers = admin->containers;
int containersCount = containers.size(); int containersCount = containers.size();
if (wasContainerInstalled) { if (wasContainerInstalled) {
@@ -148,20 +129,28 @@ void InstallUiController::install(DockerContainer container, int port, Transport
emit installServerFinished(finishMessage); emit installServerFinished(finishMessage);
} else { } else {
ServerConfig serverConfig = m_serversController->getServerConfig(serverIndex); const auto adminBefore = m_serversController->selfHostedAdminConfig(serverId);
QMap<DockerContainer, ContainerConfig> containers = serverConfig.containers(); if (!adminBefore.has_value()) {
emit installationErrorOccurred(ErrorCode::InternalError);
return;
}
QMap<DockerContainer, ContainerConfig> containers = adminBefore->containers;
int containersCount = containers.size(); int containersCount = containers.size();
bool wasContainerInstalled = false; bool wasContainerInstalled = false;
errorCode = m_installController->installContainer(serverIndex, container, port, transportProto, errorCode = m_installController->installContainer(serverId, container, port, transportProto,
wasContainerInstalled); wasContainerInstalled);
if (errorCode) { if (errorCode) {
emit installationErrorOccurred(errorCode); emit installationErrorOccurred(errorCode);
return; return;
} }
ServerConfig newServerConfig = m_serversController->getServerConfig(serverIndex); const auto adminAfter = m_serversController->selfHostedAdminConfig(serverId);
QMap<DockerContainer, ContainerConfig> newContainers = newServerConfig.containers(); if (!adminAfter.has_value()) {
emit installationErrorOccurred(ErrorCode::InternalError);
return;
}
QMap<DockerContainer, ContainerConfig> newContainers = adminAfter->containers;
int newContainersCount = newContainers.size(); int newContainersCount = newContainers.size();
bool hasNewContainers = (newContainersCount - containersCount) > (wasContainerInstalled ? 1 : 0); bool hasNewContainers = (newContainersCount - containersCount) > (wasContainerInstalled ? 1 : 0);
@@ -181,17 +170,25 @@ void InstallUiController::install(DockerContainer container, int port, Transport
} }
} }
void InstallUiController::scanServerForInstalledContainers(int serverIndex) void InstallUiController::scanServerForInstalledContainers(const QString &serverId)
{ {
ServerConfig serverBefore = m_serversController->getServerConfig(serverIndex); const auto serverBefore = m_serversController->selfHostedAdminConfig(serverId);
QMap<DockerContainer, ContainerConfig> containersBefore = serverBefore.containers(); if (!serverBefore.has_value()) {
emit installationErrorOccurred(ErrorCode::InternalError);
return;
}
QMap<DockerContainer, ContainerConfig> containersBefore = serverBefore->containers;
int containersCountBefore = containersBefore.size(); int containersCountBefore = containersBefore.size();
ErrorCode errorCode = m_installController->scanServerForInstalledContainers(serverIndex); ErrorCode errorCode = m_installController->scanServerForInstalledContainers(serverId);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
ServerConfig serverAfter = m_serversController->getServerConfig(serverIndex); const auto serverAfter = m_serversController->selfHostedAdminConfig(serverId);
QMap<DockerContainer, ContainerConfig> containersAfter = serverAfter.containers(); if (!serverAfter.has_value()) {
emit installationErrorOccurred(ErrorCode::InternalError);
return;
}
QMap<DockerContainer, ContainerConfig> containersAfter = serverAfter->containers;
int containersCountAfter = containersAfter.size(); int containersCountAfter = containersAfter.size();
bool isInstalledContainerAdded = containersCountAfter > containersCountBefore; bool isInstalledContainerAdded = containersCountAfter > containersCountBefore;
@@ -202,7 +199,7 @@ void InstallUiController::scanServerForInstalledContainers(int serverIndex)
emit installationErrorOccurred(errorCode); emit installationErrorOccurred(errorCode);
} }
void InstallUiController::updateContainer(int serverIndex, int containerIndex, int protocolIndex) void InstallUiController::updateContainer(const QString &serverId, int containerIndex, int protocolIndex)
{ {
DockerContainer container = static_cast<DockerContainer>(containerIndex); DockerContainer container = static_cast<DockerContainer>(containerIndex);
@@ -250,32 +247,26 @@ void InstallUiController::updateContainer(int serverIndex, int containerIndex, i
default: default:
return; return;
} }
ContainerConfig oldContainerConfig = m_serversController->getContainerConfig(serverIndex, container); ContainerConfig oldContainerConfig = m_serversController->getContainerConfig(serverId, container);
ErrorCode errorCode = m_installController->updateContainer(serverIndex, container, oldContainerConfig, containerConfig); ErrorCode errorCode = m_installController->updateContainer(serverId, container, oldContainerConfig, containerConfig);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
ContainerConfig updatedConfig = m_serversController->getContainerConfig(serverIndex, container); ContainerConfig updatedConfig = m_serversController->getContainerConfig(serverId, container);
m_protocolModel->updateModel(updatedConfig); m_protocolModel->updateModel(updatedConfig);
auto defaultContainer = m_serversController->getServerConfig(serverIndex).defaultContainer(); emit updateContainerFinished(tr("Settings updated successfully"));
if ((serverIndex == m_serversController->getDefaultServerIndex()) && (container == defaultContainer)) {
emit currentContainerUpdated();
} else {
emit updateContainerFinished(tr("Settings updated successfully"));
}
return; return;
} }
emit installationErrorOccurred(errorCode); emit installationErrorOccurred(errorCode);
} }
void InstallUiController::rebootServer(int serverIndex) void InstallUiController::rebootServer(const QString &serverId)
{ {
QString serverName = m_serversController->getServerConfig(serverIndex).displayName(); const QString serverName = m_serversController->notificationDisplayName(serverId);
const auto errorCode = m_installController->rebootServer(serverIndex); const auto errorCode = m_installController->rebootServer(serverId);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
emit rebootServerFinished(tr("Server '%1' was rebooted").arg(serverName)); emit rebootServerFinished(tr("Server '%1' was rebooted").arg(serverName));
} else { } else {
@@ -283,19 +274,22 @@ void InstallUiController::rebootServer(int serverIndex)
} }
} }
void InstallUiController::removeServer(int serverIndex) void InstallUiController::removeServer(const QString &serverId)
{ {
QString serverName = m_serversController->getServerConfig(serverIndex).displayName(); if (serverId.isEmpty()) {
return;
}
const QString serverName = m_serversController->notificationDisplayName(serverId);
m_serversController->removeServer(serverIndex); m_serversController->removeServer(serverId);
emit removeServerFinished(tr("Server '%1' was removed").arg(serverName)); emit removeServerFinished(tr("Server '%1' was removed").arg(serverName));
} }
void InstallUiController::removeAllContainers(int serverIndex) void InstallUiController::removeAllContainers(const QString &serverId)
{ {
QString serverName = m_serversController->getServerConfig(serverIndex).displayName(); const QString serverName = m_serversController->notificationDisplayName(serverId);
ErrorCode errorCode = m_installController->removeAllContainers(serverIndex); ErrorCode errorCode = m_installController->removeAllContainers(serverId);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
emit removeAllContainersFinished(tr("All containers from server '%1' have been removed").arg(serverName)); emit removeAllContainersFinished(tr("All containers from server '%1' have been removed").arg(serverName));
return; return;
@@ -303,14 +297,14 @@ void InstallUiController::removeAllContainers(int serverIndex)
emit installationErrorOccurred(errorCode); emit installationErrorOccurred(errorCode);
} }
void InstallUiController::removeContainer(int serverIndex, int containerIndex) void InstallUiController::removeContainer(const QString &serverId, int containerIndex)
{ {
QString serverName = m_serversController->getServerConfig(serverIndex).displayName(); const QString serverName = m_serversController->notificationDisplayName(serverId);
DockerContainer container = static_cast<DockerContainer>(containerIndex); DockerContainer container = static_cast<DockerContainer>(containerIndex);
QString containerName = ContainerUtils::containerHumanNames().value(container); QString containerName = ContainerUtils::containerHumanNames().value(container);
ErrorCode errorCode = m_installController->removeContainer(serverIndex, container); ErrorCode errorCode = m_installController->removeContainer(serverId, container);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
emit removeContainerFinished(tr("%1 has been removed from the server '%2'").arg(containerName, serverName)); emit removeContainerFinished(tr("%1 has been removed from the server '%2'").arg(containerName, serverName));
@@ -319,17 +313,17 @@ void InstallUiController::removeContainer(int serverIndex, int containerIndex)
emit installationErrorOccurred(errorCode); emit installationErrorOccurred(errorCode);
} }
void InstallUiController::clearCachedProfile(int serverIndex, int containerIndex) void InstallUiController::clearCachedProfile(const QString &serverId, int containerIndex)
{ {
DockerContainer container = static_cast<DockerContainer>(containerIndex); DockerContainer container = static_cast<DockerContainer>(containerIndex);
if (ContainerUtils::containerService(container) == ServiceType::Other) { if (ContainerUtils::containerService(container) == ServiceType::Other) {
return; return;
} }
m_installController->clearCachedProfile(serverIndex, container); m_installController->clearCachedProfile(serverId, container);
emit cachedProfileCleared(tr("%1 cached profile cleared").arg(ContainerUtils::containerHumanNames().value(container))); emit cachedProfileCleared(tr("%1 cached profile cleared").arg(ContainerUtils::containerHumanNames().value(container)));
ContainerConfig updatedConfig = m_serversController->getContainerConfig(serverIndex, container); ContainerConfig updatedConfig = m_serversController->getContainerConfig(serverId, container);
m_protocolModel->updateModel(updatedConfig); m_protocolModel->updateModel(updatedConfig);
} }
@@ -354,9 +348,9 @@ void InstallUiController::setProcessedServerCredentials(const QString &hostName,
m_processedServerCredentials.secretData = secretData; m_processedServerCredentials.secretData = secretData;
} }
void InstallUiController::mountSftpDrive(int serverIndex, const QString &port, const QString &password, const QString &username) void InstallUiController::mountSftpDrive(const QString &serverId, const QString &port, const QString &password, const QString &username)
{ {
ServerCredentials serverCredentials = m_serversController->getServerCredentials(serverIndex); ServerCredentials serverCredentials = m_serversController->getServerCredentials(serverId);
ErrorCode errorCode = m_installController->mountSftpDrive(serverCredentials, port, password, username); ErrorCode errorCode = m_installController->mountSftpDrive(serverCredentials, port, password, username);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
emit installationErrorOccurred(errorCode); emit installationErrorOccurred(errorCode);
@@ -399,40 +393,35 @@ void InstallUiController::setEncryptedPassphrase(QString passphrase)
void InstallUiController::addEmptyServer() void InstallUiController::addEmptyServer()
{ {
SelfHostedServerConfig serverConfig; m_installController->addEmptyServer(m_processedServerCredentials);
serverConfig.hostName = m_processedServerCredentials.hostName;
serverConfig.userName = m_processedServerCredentials.userName;
serverConfig.password = m_processedServerCredentials.secretData;
serverConfig.port = m_processedServerCredentials.port;
serverConfig.description = m_settingsController->nextAvailableServerName();
serverConfig.defaultContainer = DockerContainer::None;
m_serversController->addServer(ServerConfig(serverConfig));
emit installServerFinished(tr("Server added successfully")); emit installServerFinished(tr("Server added successfully"));
} }
void InstallUiController::validateConfig() void InstallUiController::validateConfig()
{ {
int serverIndex = m_serversController->getDefaultServerIndex(); const QString serverId = m_serversController->getDefaultServerId();
m_installController->validateConfig(serverIndex); if (serverId.isEmpty()) {
return;
}
m_installController->validateConfig(serverId);
} }
void InstallUiController::updateProtocols(int serverIndex, int containerIndex) void InstallUiController::updateProtocols(const QString &serverId, int containerIndex)
{ {
DockerContainer container = static_cast<DockerContainer>(containerIndex); DockerContainer container = static_cast<DockerContainer>(containerIndex);
ContainerConfig containerConfig = m_serversController->getContainerConfig(serverIndex, container); ContainerConfig containerConfig = m_serversController->getContainerConfig(serverId, container);
containerConfig.container = container; containerConfig.container = container;
m_protocolModel->updateModel(containerConfig); m_protocolModel->updateModel(containerConfig);
} }
void InstallUiController::openServerSettings(int serverIndex, int containerIndex, int protocolIndex) void InstallUiController::openServerSettings(const QString &serverId, int containerIndex, int protocolIndex)
{ {
updateProtocolConfigModel(serverIndex, containerIndex, protocolIndex); updateProtocolConfigModel(serverId, containerIndex, protocolIndex);
} }
void InstallUiController::openClientSettings(int serverIndex, int containerIndex, int protocolIndex) void InstallUiController::openClientSettings(const QString &serverId, int containerIndex, int protocolIndex)
{ {
updateProtocolConfigModel(serverIndex, containerIndex, protocolIndex); updateProtocolConfigModel(serverId, containerIndex, protocolIndex);
} }
int InstallUiController::defaultPort(int protocolIndex) int InstallUiController::defaultPort(int protocolIndex)
@@ -465,10 +454,10 @@ bool InstallUiController::defaultTransportProtoChangeable(int protocolIndex)
return ProtocolUtils::defaultTransportProtoChangeable(proto); return ProtocolUtils::defaultTransportProtoChangeable(proto);
} }
void InstallUiController::updateProtocolConfigModel(int serverIndex, int containerIndex, int protocolIndex) void InstallUiController::updateProtocolConfigModel(const QString &serverId, int containerIndex, int protocolIndex)
{ {
DockerContainer container = static_cast<DockerContainer>(containerIndex); DockerContainer container = static_cast<DockerContainer>(containerIndex);
ContainerConfig containerConfig = m_serversController->getContainerConfig(serverIndex, container); ContainerConfig containerConfig = m_serversController->getContainerConfig(serverId, container);
containerConfig.container = container; containerConfig.container = container;
Proto protocolType = static_cast<Proto>(protocolIndex); Proto protocolType = static_cast<Proto>(protocolIndex);
@@ -490,4 +479,3 @@ void InstallUiController::updateProtocolConfigModel(int serverIndex, int contain
default: break; default: break;
} }
} }
@@ -52,24 +52,24 @@ public:
~InstallUiController(); ~InstallUiController();
public slots: public slots:
void install(DockerContainer container, int port, TransportProto transportProto, int serverIndex); void install(DockerContainer container, int port, TransportProto transportProto, const QString &serverId);
void setProcessedServerCredentials(const QString &hostName, const QString &userName, const QString &secretData); void setProcessedServerCredentials(const QString &hostName, const QString &userName, const QString &secretData);
void clearProcessedServerCredentials(); void clearProcessedServerCredentials();
void scanServerForInstalledContainers(int serverIndex); void scanServerForInstalledContainers(const QString &serverId);
void updateContainer(int serverIndex, int containerIndex, int protocolIndex); void updateContainer(const QString &serverId, int containerIndex, int protocolIndex);
void removeServer(int serverIndex); void removeServer(const QString &serverId);
void rebootServer(int serverIndex); void rebootServer(const QString &serverId);
void removeAllContainers(int serverIndex); void removeAllContainers(const QString &serverId);
void removeContainer(int serverIndex, int containerIndex); void removeContainer(const QString &serverId, int containerIndex);
void clearCachedProfile(int serverIndex, int containerIndex); void clearCachedProfile(const QString &serverId, int containerIndex);
QRegularExpression ipAddressRegExp(); QRegularExpression ipAddressRegExp();
void mountSftpDrive(int serverIndex, const QString &port, const QString &password, const QString &username); void mountSftpDrive(const QString &serverId, const QString &port, const QString &password, const QString &username);
bool checkSshConnection(); bool checkSshConnection();
@@ -78,12 +78,12 @@ public slots:
void addEmptyServer(); void addEmptyServer();
void validateConfig(); void validateConfig();
Q_INVOKABLE void updateProtocols(int serverIndex, int containerIndex); Q_INVOKABLE void updateProtocols(const QString &serverId, int containerIndex);
void openServerSettings(int serverIndex, int containerIndex, int protocolIndex); void openServerSettings(const QString &serverId, int containerIndex, int protocolIndex);
void openClientSettings(int serverIndex, int containerIndex, int protocolIndex); void openClientSettings(const QString &serverId, int containerIndex, int protocolIndex);
int defaultPort(int protocolIndex); int defaultPort(int protocolIndex);
int getPortForInstall(int protocolIndex); int getPortForInstall(int protocolIndex);
int defaultTransportProto(int protocolIndex); int defaultTransportProto(int protocolIndex);
@@ -114,8 +114,6 @@ signals:
void serverIsBusy(const bool isBusy); void serverIsBusy(const bool isBusy);
void cancelInstallation(); void cancelInstallation();
void currentContainerUpdated();
void cachedProfileCleared(const QString &message); void cachedProfileCleared(const QString &message);
void apiConfigRemoved(const QString &message); void apiConfigRemoved(const QString &message);
@@ -145,7 +143,7 @@ private:
QString m_privateKeyPassphrase; QString m_privateKeyPassphrase;
void updateProtocolConfigModel(int serverIndex, int containerIndex, int protocolIndex); void updateProtocolConfigModel(const QString &serverId, int containerIndex, int protocolIndex);
}; };
#endif // INSTALLUICONTROLLER_H #endif // INSTALLUICONTROLLER_H
+266 -233
View File
@@ -1,37 +1,37 @@
#include "serversUiController.h" #include "serversUiController.h"
#include "core/utils/api/apiEnums.h"
#include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h"
#include "core/utils/api/apiUtils.h"
#include "core/utils/containerEnum.h" #include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h" #include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h" #include "core/utils/protocolEnum.h"
#include "core/utils/protocolEnum.h"
#include "core/protocols/protocolUtils.h"
#include "core/utils/constants/configKeys.h"
#include "core/utils/constants/protocolConstants.h"
#include <QJsonDocument>
#include <QJsonArray>
#include "core/models/serverConfig.h"
#include "core/models/protocolConfig.h" #include "core/models/protocolConfig.h"
#include "core/models/containerConfig.h" #include "core/models/containerConfig.h"
#include "core/models/protocols/awgProtocolConfig.h"
using namespace amnezia; using namespace amnezia;
namespace namespace {
int rowForServerId(const QVector<ServerDescription> &list, const QString &serverId)
{ {
namespace configKey if (serverId.isEmpty()) {
{ return -1;
constexpr char apiConfig[] = "api_config";
constexpr char serverCountryCode[] = "server_country_code";
constexpr char serverCountryName[] = "server_country_name";
constexpr char userCountryCode[] = "user_country_code";
constexpr char serviceType[] = "service_type";
} }
for (int i = 0; i < list.size(); ++i) {
if (list.at(i).serverId == serverId) {
return i;
}
}
return -1;
} }
bool descriptionsHaveGatewayServers(const QVector<ServerDescription> &list)
{
for (const auto &d : list) {
if (d.isServerFromGatewayApi) {
return true;
}
}
return false;
}
} // namespace
ServersUiController::ServersUiController(ServersController* serversController, ServersUiController::ServersUiController(ServersController* serversController,
SettingsController* settingsController, SettingsController* settingsController,
ServersModel* serversModel, ServersModel* serversModel,
@@ -47,48 +47,70 @@ ServersUiController::ServersUiController(ServersController* serversController,
{ {
} }
void ServersUiController::removeServer(int index) void ServersUiController::removeServer(const QString &serverId)
{ {
m_serversController->removeServer(index); if (serverId.isEmpty()) {
updateModel(); return;
}
void ServersUiController::editServerName(int index, const QString &name)
{
ServerConfig serverConfig = m_serversController->getServerConfig(index);
if (serverConfig.isApiV1()) {
ApiV1ServerConfig* apiV1 = serverConfig.as<ApiV1ServerConfig>();
if (apiV1) {
apiV1->name = name;
}
} else if (serverConfig.isApiV2()) {
ApiV2ServerConfig* apiV2 = serverConfig.as<ApiV2ServerConfig>();
if (apiV2) {
apiV2->name = name;
apiV2->nameOverriddenByUser = true;
}
} else {
serverConfig.visit([&name](auto& arg) {
arg.description = name;
});
} }
m_serversController->removeServer(serverId);
m_serversController->editServer(index, serverConfig);
updateModel(); updateModel();
} }
void ServersUiController::setDefaultServerIndex(int index) void ServersUiController::removeServerAtIndex(int index)
{ {
m_serversController->setDefaultServerIndex(index); const QString serverId = getServerId(index);
updateModel(); if (!serverId.isEmpty()) {
emit defaultServerIndexChanged(index); removeServer(serverId);
}
} }
void ServersUiController::setDefaultContainer(int serverIndex, int containerIndex) void ServersUiController::setDefaultServerAtIndex(int index)
{ {
const QString serverId = getServerId(index);
if (!serverId.isEmpty()) {
setDefaultServer(serverId);
}
}
void ServersUiController::setDefaultContainerAtIndex(int index, int containerIndex)
{
const QString serverId = getServerId(index);
if (!serverId.isEmpty()) {
setDefaultContainer(serverId, containerIndex);
}
}
void ServersUiController::editServerName(const QString &serverId, const QString &name)
{
if (serverId.isEmpty()) {
return;
}
if (!m_serversController->renameServer(serverId, name)) {
emit errorOccurred(tr("Legacy API v1 configs are no longer supported. Remove this server to continue."));
emit finished(tr("Use the remove action to delete this legacy config."));
return;
}
updateModel();
}
void ServersUiController::setDefaultServer(const QString &serverId)
{
if (serverId.isEmpty()) {
return;
}
m_serversController->setDefaultServer(serverId);
updateModel();
emit defaultServerIdChanged(serverId);
}
void ServersUiController::setDefaultContainer(const QString &serverId, int containerIndex)
{
if (serverId.isEmpty()) {
return;
}
auto container = static_cast<DockerContainer>(containerIndex); auto container = static_cast<DockerContainer>(containerIndex);
m_serversController->setDefaultContainer(serverIndex, container); m_serversController->setDefaultContainer(serverId, container);
updateModel(); updateModel();
} }
@@ -98,129 +120,123 @@ void ServersUiController::toggleAmneziaDns(bool enabled)
updateModel(); updateModel();
} }
void ServersUiController::onDefaultServerChanged(int index) void ServersUiController::onDefaultServerChanged(const QString &/*defaultServerId*/)
{ {
setProcessedServerIndex(index);
updateModel(); updateModel();
setProcessedServerId(m_serversController->getDefaultServerId());
updateDefaultServerContainersModel(); updateDefaultServerContainersModel();
emit defaultServerIndexChanged(index); emit defaultServerIdChanged(m_serversController->getDefaultServerId());
} }
void ServersUiController::updateModel() void ServersUiController::updateModel()
{ {
int defaultIndex = m_serversController->getDefaultServerIndex(); QVector<ServerDescription> descriptions =
bool wasEmpty = !hasServersFromGatewayApi(); m_serversController->buildServerDescriptions(m_settingsController->isAmneziaDnsEnabled());
int serversCount = m_serversController->getServersCount();
if (m_processedServerIndex >= serversCount) { const QString defaultServerId = m_serversController->getDefaultServerId();
setProcessedServerIndex(defaultIndex); const bool hadServersFromGatewayBefore = descriptionsHaveGatewayServers(m_orderedServerDescriptions);
} else if (m_processedServerIndex >= 0) { const bool hasServersFromGatewayNow = descriptionsHaveGatewayServers(descriptions);
setProcessedServerIndex(m_processedServerIndex); const int listCount = descriptions.size();
const int defaultRowInDescriptions = rowForServerId(descriptions, defaultServerId);
m_orderedServerDescriptions = descriptions;
if (listCount == 0) {
setProcessedServerId(QString());
} else if (m_processedServerIndex >= listCount) {
setProcessedServerId(defaultServerId);
} else if (!m_processedServerId.isEmpty()) {
const int row = rowForServerId(m_orderedServerDescriptions, m_processedServerId);
if (row < 0) {
setProcessedServerId(defaultServerId);
} else {
setProcessedServerId(m_processedServerId);
}
} else if (defaultRowInDescriptions >= 0) {
setProcessedServerId(defaultServerId);
} }
m_serversModel->updateModel(m_serversController->getServers(), defaultIndex, m_settingsController->isAmneziaDnsEnabled()); m_serversModel->updateModel(m_orderedServerDescriptions, defaultRowInDescriptions);
updateContainersModel(); updateContainersModel();
updateDefaultServerContainersModel(); updateDefaultServerContainersModel();
bool isEmpty = !hasServersFromGatewayApi(); if (hadServersFromGatewayBefore != hasServersFromGatewayNow) {
if (wasEmpty != isEmpty) {
emit hasServersFromGatewayApiChanged(); emit hasServersFromGatewayApiChanged();
} }
emit defaultServerIndexChanged(defaultIndex); emit defaultServerIdChanged(defaultServerId);
emit defaultServerIndexChanged(defaultServerIndex());
} }
int ServersUiController::getDefaultServerIndex() const QString ServersUiController::getDefaultServerId() const
{ {
return m_serversController->getDefaultServerIndex(); return m_serversController->getDefaultServerId();
} }
QString ServersUiController::getDefaultServerName() const QString ServersUiController::getDefaultServerName() const
{ {
int defaultIndex = getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
return m_serversController->getServerConfig(defaultIndex).displayName(); for (const auto &description : m_orderedServerDescriptions) {
if (description.serverId == defaultServerId) {
return description.serverName;
}
}
return QString();
} }
QString ServersUiController::getDefaultServerDefaultContainerName() const QString ServersUiController::getDefaultServerDefaultContainerName() const
{ {
int defaultIndex = getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
const ServerConfig server = m_serversController->getServerConfig(defaultIndex); for (const auto &description : m_orderedServerDescriptions) {
return ContainerUtils::containerHumanNames().value(server.defaultContainer()); if (description.serverId == defaultServerId) {
return ContainerUtils::containerHumanNames().value(description.defaultContainer);
}
}
return QString();
} }
QString ServersUiController::getDefaultServerDescriptionCollapsed() const QString ServersUiController::getDefaultServerDescriptionCollapsed() const
{ {
int defaultIndex = getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
const ServerConfig server = m_serversController->getServerConfig(defaultIndex); for (const auto &description : m_orderedServerDescriptions) {
QString description = getDefaultServerDescription(server, defaultIndex); if (description.serverId == defaultServerId) {
return description.collapsedServerDescription;
if (server.isApiConfig()) {
return description;
}
DockerContainer container = server.defaultContainer();
QString containerName = ContainerUtils::containerHumanNames().value(container);
QString protocolVersion;
QString hostName = server.hostName();
if (ContainerUtils::isAwgContainer(container)) {
ContainerConfig containerConfig = server.containerConfig(container);
if (auto* awgProtocolConfig = containerConfig.getAwgProtocolConfig()) {
QString version = awgProtocolConfig->serverConfig.protocolVersion;
if (version == protocols::awg::awgV2) {
protocolVersion = QObject::tr(" (version 2)");
} else if (version == protocols::awg::awgV1_5) {
protocolVersion = QObject::tr(" (version 1.5)");
}
if (container == DockerContainer::Awg && !awgProtocolConfig->serverConfig.isThirdPartyConfig) {
containerName = "AmneziaWG Legacy";
}
} }
} }
return QString();
return description + containerName + protocolVersion + " | " + hostName;
} }
QString ServersUiController::getDefaultServerImagePathCollapsed() const QString ServersUiController::getDefaultServerImagePathCollapsed() const
{ {
int defaultIndex = getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
const ServerConfig server = m_serversController->getServerConfig(defaultIndex); for (const auto &description : m_orderedServerDescriptions) {
if (description.serverId == defaultServerId) {
if (server.isApiV2()) { if (!description.isApiV2 || description.apiServerCountryCode.isEmpty()) {
const ApiV2ServerConfig* apiV2 = server.as<ApiV2ServerConfig>(); return "";
if (!apiV2) return QString(); }
const QString countryCode = apiV2->apiConfig.serverCountryCode; return QString("qrc:/countriesFlags/images/flagKit/%1.svg").arg(description.apiServerCountryCode.toUpper());
if (countryCode.isEmpty()) {
return "";
} }
return QString("qrc:/countriesFlags/images/flagKit/%1.svg").arg(countryCode.toUpper());
} }
return ""; return "";
} }
QString ServersUiController::getDefaultServerDescriptionExpanded() const QString ServersUiController::getDefaultServerDescriptionExpanded() const
{ {
int defaultIndex = getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
const ServerConfig server = m_serversController->getServerConfig(defaultIndex); for (const auto &description : m_orderedServerDescriptions) {
QString description = getDefaultServerDescription(server, defaultIndex); if (description.serverId == defaultServerId) {
return description.expandedServerDescription;
if (server.isApiConfig()) { }
return description;
} }
return QString();
return description + server.hostName();
} }
bool ServersUiController::isDefaultServerDefaultContainerHasSplitTunneling() const bool ServersUiController::isDefaultServerDefaultContainerHasSplitTunneling() const
{ {
int defaultIndex = getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
const ServerConfig server = m_serversController->getServerConfig(defaultIndex); const DockerContainer defaultContainer = m_serversController->getDefaultContainer(defaultServerId);
DockerContainer defaultContainer = server.defaultContainer(); const ContainerConfig containerConfig = m_serversController->getContainerConfig(defaultServerId, defaultContainer);
ContainerConfig containerConfig = server.containerConfig(defaultContainer);
if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::WireGuard) { if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::WireGuard) {
auto hasSplitTunnelingFromAllowedIps = [](const QStringList& allowedIps, const QString& nativeConfig) -> bool { auto hasSplitTunnelingFromAllowedIps = [](const QStringList& allowedIps, const QString& nativeConfig) -> bool {
@@ -265,16 +281,13 @@ bool ServersUiController::isDefaultServerDefaultContainerHasSplitTunneling() con
bool ServersUiController::isDefaultServerFromApi() const bool ServersUiController::isDefaultServerFromApi() const
{ {
int defaultIndex = getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
const ServerConfig server = m_serversController->getServerConfig(defaultIndex); for (const auto &description : m_orderedServerDescriptions) {
const int configVersion = server.configVersion(); if (description.serverId == defaultServerId) {
return configVersion == apiDefs::ConfigSource::Telegram return description.isApiV2;
|| configVersion == apiDefs::ConfigSource::AmneziaGateway; }
} }
return false;
int ServersUiController::getProcessedServerIndex() const
{
return m_processedServerIndex;
} }
int ServersUiController::getProcessedContainerIndex() const int ServersUiController::getProcessedContainerIndex() const
@@ -291,186 +304,196 @@ void ServersUiController::setProcessedContainerIndex(int index)
} }
} }
void ServersUiController::setProcessedServerIndex(int index) QString ServersUiController::getProcessedServerId() const
{ {
if (index >= m_serversController->getServersCount()) { return m_processedServerId;
}
void ServersUiController::setProcessedServerId(const QString &serverId)
{
const int index = serverId.isEmpty() ? -1 : serverIndexForId(serverId);
if (!serverId.isEmpty() && index < 0) {
return; return;
} }
if (m_processedServerIndex != index) { if (m_processedServerIndex != index || m_processedServerId != serverId) {
m_processedServerIndex = index; m_processedServerIndex = index;
m_processedServerId = serverId;
m_serversModel->setProcessedServerIndex(index); m_serversModel->setProcessedServerIndex(index);
if (index >= 0) { if (index >= 0) {
updateContainersModel(); updateContainersModel();
for (const auto &description : m_orderedServerDescriptions) {
ServerConfig server = m_serversController->getServerConfig(index); if (description.serverId == serverId) {
setProcessedContainerIndex(static_cast<int>(server.defaultContainer())); setProcessedContainerIndex(static_cast<int>(description.defaultContainer));
break;
if (server.isApiV2()) {
const ApiV2ServerConfig* apiV2 = server.as<ApiV2ServerConfig>();
if (apiV2 && !apiV2->apiConfig.availableCountries.isEmpty()) {
emit updateApiCountryModel();
} }
emit updateApiServicesModel(); }
for (const auto &description : m_orderedServerDescriptions) {
if (description.serverId != serverId) {
continue;
}
if (description.isApiV2) {
if (description.isCountrySelectionAvailable && !description.apiAvailableCountries.isEmpty()) {
emit updateApiCountryModel();
}
emit updateApiServicesModel();
}
break;
} }
} }
emit processedServerIdChanged(m_processedServerId);
emit processedServerIndexChanged(m_processedServerIndex); emit processedServerIndexChanged(m_processedServerIndex);
} }
} }
int ServersUiController::getProcessedServerIndex() const
{
return m_processedServerIndex;
}
void ServersUiController::setProcessedServerIndex(int index)
{
if (index < 0) {
setProcessedServerId(QString());
return;
}
const QString id = getServerId(index);
if (!id.isEmpty()) {
setProcessedServerId(id);
}
}
int ServersUiController::defaultServerIndex() const
{
return rowForServerId(m_orderedServerDescriptions, getDefaultServerId());
}
bool ServersUiController::processedServerIsPremium() const bool ServersUiController::processedServerIsPremium() const
{ {
ServerConfig server = m_serversController->getServerConfig(m_processedServerIndex); for (const auto &description : m_orderedServerDescriptions) {
if (server.isApiV1()) { if (description.serverId == m_processedServerId) {
const ApiV1ServerConfig* apiV1 = server.as<ApiV1ServerConfig>(); return description.isPremium;
return apiV1 ? apiV1->isPremium() : false; }
} else if (server.isApiV2()) {
const ApiV2ServerConfig* apiV2 = server.as<ApiV2ServerConfig>();
return apiV2 ? (apiV2->isPremium() || apiV2->isExternalPremium()) : false;
} }
return false; return false;
} }
const ServerCredentials ServersUiController::getProcessedServerCredentials() const const ServerCredentials ServersUiController::getProcessedServerCredentials() const
{ {
return m_serversController->getServerCredentials(m_processedServerIndex); return m_serversController->getServerCredentials(m_processedServerId);
} }
bool ServersUiController::isDefaultServerCurrentlyProcessed() const bool ServersUiController::isDefaultServerCurrentlyProcessed() const
{ {
return m_serversController->getDefaultServerIndex() == m_processedServerIndex; return m_serversController->getDefaultServerId() == m_processedServerId;
} }
bool ServersUiController::isProcessedServerHasWriteAccess() const bool ServersUiController::isProcessedServerHasWriteAccess() const
{ {
ServerCredentials credentials = m_serversController->getServerCredentials(m_processedServerIndex); ServerCredentials credentials = m_serversController->getServerCredentials(m_processedServerId);
return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty()); return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty());
} }
QString ServersUiController::getDefaultServerDescription(const QString &serverId) const
QString ServersUiController::getDefaultServerDescription(const ServerConfig& server, int index) const
{ {
QString description; for (const auto &description : m_orderedServerDescriptions) {
if (description.serverId == serverId) {
if (server.isApiV2()) { return description.baseDescription;
const ApiV2ServerConfig* apiV2 = server.as<ApiV2ServerConfig>();
if (!apiV2) return QString();
if (!apiV2->apiConfig.serverCountryCode.isEmpty()) {
return apiV2->apiConfig.serverCountryName;
} }
return apiV2->description;
} else if (server.isApiV1()) {
const ApiV1ServerConfig* apiV1 = server.as<ApiV1ServerConfig>();
return apiV1 ? apiV1->description : QString();
} else {
ServerCredentials credentials = m_serversController->getServerCredentials(index);
if (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty()) {
bool isAmneziaDnsEnabled = m_settingsController->isAmneziaDnsEnabled();
if (isAmneziaDnsEnabled && isAmneziaDnsContainerInstalled(index)) {
description += "Amnezia DNS | ";
}
} else {
if (server.dns1() == protocols::dns::amneziaDnsIp) {
description += "Amnezia DNS | ";
}
}
return description;
} }
} return QString();
bool ServersUiController::isAmneziaDnsContainerInstalled(int serverIndex) const
{
const ServerConfig server = m_serversController->getServerConfig(serverIndex);
QMap<DockerContainer, ContainerConfig> containers = server.containers();
return containers.contains(DockerContainer::Dns);
} }
bool ServersUiController::hasServersFromGatewayApi() const bool ServersUiController::hasServersFromGatewayApi() const
{ {
QVector<ServerConfig> servers = m_serversController->getServers(); return listHasServersFromGatewayApi();
for (const ServerConfig &server : servers) {
if (server.isApiV2()) {
return true;
}
}
return false;
} }
bool ServersUiController::isAdVisible() const bool ServersUiController::isAdVisible() const
{ {
int defaultIndex = getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
if (defaultIndex < 0) { if (defaultServerId.isEmpty()) {
return false; return false;
} }
ServerConfig server = m_serversController->getServerConfig(defaultIndex); for (const auto &description : m_orderedServerDescriptions) {
if (server.isApiV2()) { if (description.serverId == defaultServerId) {
const ApiV2ServerConfig* apiV2 = server.as<ApiV2ServerConfig>(); return description.isAdVisible;
if (!apiV2) return false; }
return apiV2->apiConfig.serviceInfo.isAdVisible;
} }
return false; return false;
} }
QString ServersUiController::adHeader() const QString ServersUiController::adHeader() const
{ {
int defaultIndex = getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
if (defaultIndex < 0) { if (defaultServerId.isEmpty()) {
return QString(); return QString();
} }
ServerConfig server = m_serversController->getServerConfig(defaultIndex); for (const auto &description : m_orderedServerDescriptions) {
if (server.isApiV2()) { if (description.serverId == defaultServerId) {
const ApiV2ServerConfig* apiV2 = server.as<ApiV2ServerConfig>(); return description.adHeader;
if (!apiV2) return QString(); }
return apiV2->apiConfig.serviceInfo.adHeader;
} }
return QString(); return QString();
} }
QString ServersUiController::adDescription() const QString ServersUiController::adDescription() const
{ {
int defaultIndex = getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
if (defaultIndex < 0) { if (defaultServerId.isEmpty()) {
return QString(); return QString();
} }
ServerConfig server = m_serversController->getServerConfig(defaultIndex); for (const auto &description : m_orderedServerDescriptions) {
if (server.isApiV2()) { if (description.serverId == defaultServerId) {
const ApiV2ServerConfig* apiV2 = server.as<ApiV2ServerConfig>(); return description.adDescription;
if (!apiV2) return QString(); }
return apiV2->apiConfig.serviceInfo.adDescription;
} }
return QString(); return QString();
} }
QString ServersUiController::getServerId(int index) const
{
if (index < 0 || index >= m_orderedServerDescriptions.size()) {
return QString();
}
return m_orderedServerDescriptions.at(index).serverId;
}
int ServersUiController::getServerIndexById(const QString &serverId) const
{
return rowForServerId(m_orderedServerDescriptions, serverId);
}
void ServersUiController::updateContainersModel() void ServersUiController::updateContainersModel()
{ {
if (m_processedServerIndex < 0 || m_processedServerIndex >= m_serversController->getServersCount()) { if (m_processedServerId.isEmpty()) {
return; return;
} }
ServerConfig server = m_serversController->getServerConfig(m_processedServerIndex); const QMap<DockerContainer, ContainerConfig> containers =
QMap<DockerContainer, ContainerConfig> containers = server.containers(); m_serversController->getServerContainersMap(m_processedServerId);
m_containersModel->updateModel(containers); m_containersModel->updateModel(containers);
} }
void ServersUiController::updateDefaultServerContainersModel() void ServersUiController::updateDefaultServerContainersModel()
{ {
int defaultIndex = m_serversController->getDefaultServerIndex(); const QString defaultServerId = m_serversController->getDefaultServerId();
if (defaultIndex < 0 || defaultIndex >= m_serversController->getServersCount()) { if (defaultServerId.isEmpty()) {
return; return;
} }
ServerConfig server = m_serversController->getServerConfig(defaultIndex); const QMap<DockerContainer, ContainerConfig> containers =
QMap<DockerContainer, ContainerConfig> containers = server.containers(); m_serversController->getServerContainersMap(defaultServerId);
m_defaultServerContainersModel->updateModel(containers); m_defaultServerContainersModel->updateModel(containers);
} }
QStringList ServersUiController::getAllInstalledServicesName(int serverIndex) const QStringList ServersUiController::getAllInstalledServicesName(int serverIndex) const
{ {
QStringList servicesName; QStringList servicesName;
ServerConfig server = m_serversController->getServerConfig(serverIndex); const QString serverId = getServerId(serverIndex);
QMap<DockerContainer, ContainerConfig> containers = server.containers(); const QMap<DockerContainer, ContainerConfig> containers = m_serversController->getServerContainersMap(serverId);
for (auto it = containers.begin(); it != containers.end(); ++it) { for (auto it = containers.begin(); it != containers.end(); ++it) {
DockerContainer container = it.key(); DockerContainer container = it.key();
if (ContainerUtils::containerService(container) == ServiceType::Other) { if (ContainerUtils::containerService(container) == ServiceType::Other) {
@@ -489,3 +512,13 @@ QStringList ServersUiController::getAllInstalledServicesName(int serverIndex) co
return servicesName; return servicesName;
} }
int ServersUiController::serverIndexForId(const QString &serverId) const
{
return rowForServerId(m_orderedServerDescriptions, serverId);
}
bool ServersUiController::listHasServersFromGatewayApi() const
{
return descriptionsHaveGatewayServers(m_orderedServerDescriptions);
}
+47 -23
View File
@@ -6,35 +6,39 @@
#include <QSet> #include <QSet>
#include <QJsonObject> #include <QJsonObject>
#include <QStringList> #include <QStringList>
#include <QVector>
#include "core/controllers/serversController.h" #include "core/controllers/serversController.h"
#include "core/models/serverDescription.h"
#include "core/controllers/settingsController.h" #include "core/controllers/settingsController.h"
#include "ui/models/serversModel.h" #include "ui/models/serversModel.h"
#include "ui/models/containersModel.h" #include "ui/models/containersModel.h"
#include "core/models/serverConfig.h"
class ServersUiController : public QObject class ServersUiController : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int defaultIndex READ getDefaultServerIndex NOTIFY defaultServerIndexChanged) Q_PROPERTY(QString defaultServerId READ getDefaultServerId NOTIFY defaultServerIdChanged)
Q_PROPERTY(QString defaultServerName READ getDefaultServerName NOTIFY defaultServerIndexChanged) Q_PROPERTY(int defaultServerIndex READ defaultServerIndex NOTIFY defaultServerIndexChanged)
Q_PROPERTY(QString defaultServerDefaultContainerName READ getDefaultServerDefaultContainerName NOTIFY defaultServerIndexChanged)
Q_PROPERTY(QString defaultServerDescriptionCollapsed READ getDefaultServerDescriptionCollapsed NOTIFY defaultServerIndexChanged) Q_PROPERTY(QString defaultServerName READ getDefaultServerName NOTIFY defaultServerIdChanged)
Q_PROPERTY(QString defaultServerImagePathCollapsed READ getDefaultServerImagePathCollapsed NOTIFY defaultServerIndexChanged) Q_PROPERTY(QString defaultServerDefaultContainerName READ getDefaultServerDefaultContainerName NOTIFY defaultServerIdChanged)
Q_PROPERTY(QString defaultServerDescriptionExpanded READ getDefaultServerDescriptionExpanded NOTIFY defaultServerIndexChanged) Q_PROPERTY(QString defaultServerDescriptionCollapsed READ getDefaultServerDescriptionCollapsed NOTIFY defaultServerIdChanged)
Q_PROPERTY(bool isDefaultServerDefaultContainerHasSplitTunneling READ isDefaultServerDefaultContainerHasSplitTunneling NOTIFY defaultServerIndexChanged) Q_PROPERTY(QString defaultServerImagePathCollapsed READ getDefaultServerImagePathCollapsed NOTIFY defaultServerIdChanged)
Q_PROPERTY(bool isDefaultServerFromApi READ isDefaultServerFromApi NOTIFY defaultServerIndexChanged) Q_PROPERTY(QString defaultServerDescriptionExpanded READ getDefaultServerDescriptionExpanded NOTIFY defaultServerIdChanged)
Q_PROPERTY(bool isDefaultServerDefaultContainerHasSplitTunneling READ isDefaultServerDefaultContainerHasSplitTunneling NOTIFY defaultServerIdChanged)
Q_PROPERTY(bool isDefaultServerFromApi READ isDefaultServerFromApi NOTIFY defaultServerIdChanged)
Q_PROPERTY(int processedIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged) Q_PROPERTY(QString processedServerId READ getProcessedServerId WRITE setProcessedServerId NOTIFY processedServerIdChanged)
Q_PROPERTY(int processedServerIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged)
Q_PROPERTY(int processedContainerIndex READ getProcessedContainerIndex WRITE setProcessedContainerIndex NOTIFY processedContainerIndexChanged) Q_PROPERTY(int processedContainerIndex READ getProcessedContainerIndex WRITE setProcessedContainerIndex NOTIFY processedContainerIndexChanged)
Q_PROPERTY(bool processedServerIsPremium READ processedServerIsPremium NOTIFY processedServerIndexChanged) Q_PROPERTY(bool processedServerIsPremium READ processedServerIsPremium NOTIFY processedServerIndexChanged)
Q_PROPERTY(bool hasServersFromGatewayApi READ hasServersFromGatewayApi NOTIFY hasServersFromGatewayApiChanged) Q_PROPERTY(bool hasServersFromGatewayApi READ hasServersFromGatewayApi NOTIFY hasServersFromGatewayApiChanged)
Q_PROPERTY(bool isAdVisible READ isAdVisible NOTIFY defaultServerIndexChanged) Q_PROPERTY(bool isAdVisible READ isAdVisible NOTIFY defaultServerIdChanged)
Q_PROPERTY(QString adHeader READ adHeader NOTIFY defaultServerIndexChanged) Q_PROPERTY(QString adHeader READ adHeader NOTIFY defaultServerIdChanged)
Q_PROPERTY(QString adDescription READ adDescription NOTIFY defaultServerIndexChanged) Q_PROPERTY(QString adDescription READ adDescription NOTIFY defaultServerIdChanged)
public: public:
explicit ServersUiController(ServersController* serversController, explicit ServersUiController(ServersController* serversController,
@@ -45,15 +49,22 @@ public:
QObject *parent = nullptr); QObject *parent = nullptr);
public slots: public slots:
void removeServer(int index); void removeServer(const QString &serverId);
void editServerName(int index, const QString &name); void removeServerAtIndex(int index);
void setDefaultServerIndex(int index);
void setDefaultContainer(int serverIndex, int containerIndex); void editServerName(const QString &serverId, const QString &name);
void setDefaultServer(const QString &serverId);
void setDefaultServerAtIndex(int index);
void setDefaultContainer(const QString &serverId, int containerIndex);
void setDefaultContainerAtIndex(int index, int containerIndex);
void toggleAmneziaDns(bool enabled); void toggleAmneziaDns(bool enabled);
void onDefaultServerChanged(int index); void onDefaultServerChanged(const QString &defaultServerId);
// Getters for properties // Getters for properties
int getDefaultServerIndex() const; QString getDefaultServerId() const;
QString getDefaultServerName() const; QString getDefaultServerName() const;
QString getDefaultServerDefaultContainerName() const; QString getDefaultServerDefaultContainerName() const;
QString getDefaultServerDescriptionCollapsed() const; QString getDefaultServerDescriptionCollapsed() const;
@@ -62,8 +73,14 @@ public slots:
bool isDefaultServerDefaultContainerHasSplitTunneling() const; bool isDefaultServerDefaultContainerHasSplitTunneling() const;
bool isDefaultServerFromApi() const; bool isDefaultServerFromApi() const;
QString getProcessedServerId() const;
void setProcessedServerId(const QString &serverId);
int getProcessedServerIndex() const; int getProcessedServerIndex() const;
void setProcessedServerIndex(int index); void setProcessedServerIndex(int index);
int defaultServerIndex() const;
int getProcessedContainerIndex() const; int getProcessedContainerIndex() const;
void setProcessedContainerIndex(int index); void setProcessedContainerIndex(int index);
bool processedServerIsPremium() const; bool processedServerIsPremium() const;
@@ -78,12 +95,16 @@ public slots:
QString adHeader() const; QString adHeader() const;
QString adDescription() const; QString adDescription() const;
QString getServerId(int index) const;
int getServerIndexById(const QString &serverId) const;
QStringList getAllInstalledServicesName(int serverIndex) const; QStringList getAllInstalledServicesName(int serverIndex) const;
signals: signals:
void errorOccurred(const QString &errorMessage); void errorOccurred(const QString &errorMessage);
void finished(const QString &message); void finished(const QString &message);
void defaultServerIdChanged(const QString &serverId);
void defaultServerIndexChanged(int index); void defaultServerIndexChanged(int index);
void processedServerIdChanged(const QString &serverId);
void processedServerIndexChanged(int index); void processedServerIndexChanged(int index);
void processedContainerIndexChanged(int index); void processedContainerIndexChanged(int index);
void hasServersFromGatewayApiChanged(); void hasServersFromGatewayApiChanged();
@@ -94,20 +115,23 @@ public:
void updateModel(); void updateModel();
private: private:
QString getDefaultServerDescription(const ServerConfig& server, int index) const; QString getDefaultServerDescription(const QString &serverId) const;
bool isAmneziaDnsContainerInstalled(int serverIndex) const; int serverIndexForId(const QString &serverId) const;
bool listHasServersFromGatewayApi() const;
void updateContainersModel(); void updateContainersModel();
void updateDefaultServerContainersModel(); void updateDefaultServerContainersModel();
void updateApiModelsForProcessedServer();
ServersController* m_serversController; ServersController* m_serversController;
SettingsController* m_settingsController; SettingsController* m_settingsController;
ServersModel* m_serversModel; ServersModel* m_serversModel;
ContainersModel* m_containersModel; ContainersModel* m_containersModel;
ContainersModel* m_defaultServerContainersModel; ContainersModel* m_defaultServerContainersModel;
QVector<amnezia::ServerDescription> m_orderedServerDescriptions;
int m_processedServerIndex = -1; int m_processedServerIndex = -1;
QString m_processedServerId;
int m_processedContainerIndex = -1; int m_processedContainerIndex = -1;
}; };
+9 -9
View File
@@ -4,6 +4,7 @@
#include <QJsonObject> #include <QJsonObject>
#include "core/utils/api/apiUtils.h" #include "core/utils/api/apiUtils.h"
#include "core/utils/serverConfigUtils.h"
#include "logger.h" #include "logger.h"
namespace namespace
@@ -28,7 +29,7 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case SubscriptionStatusRole: { case SubscriptionStatusRole: {
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { if (m_accountInfoData.configType == serverConfigUtils::ConfigType::AmneziaFreeV3) {
return tr("Active"); return tr("Active");
} }
@@ -37,14 +38,14 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
: QStringLiteral("<p><a style=\"color: #28c840;\">%1</a>").arg(tr("Active")); : QStringLiteral("<p><a style=\"color: #28c840;\">%1</a>").arg(tr("Active"));
} }
case EndDateRole: { case EndDateRole: {
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { if (m_accountInfoData.configType == serverConfigUtils::ConfigType::AmneziaFreeV3) {
return ""; return "";
} }
return QDateTime::fromString(m_accountInfoData.subscriptionEndDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy"); return QDateTime::fromString(m_accountInfoData.subscriptionEndDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy");
} }
case ConnectedDevicesRole: { case ConnectedDevicesRole: {
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { if (m_accountInfoData.configType == serverConfigUtils::ConfigType::AmneziaFreeV3) {
return ""; return "";
} }
return tr("%1 out of %2").arg(m_accountInfoData.activeDeviceCount).arg(m_accountInfoData.maxDeviceCount); return tr("%1 out of %2").arg(m_accountInfoData.activeDeviceCount).arg(m_accountInfoData.maxDeviceCount);
@@ -53,9 +54,8 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
return m_accountInfoData.subscriptionDescription; return m_accountInfoData.subscriptionDescription;
} }
case IsComponentVisibleRole: { case IsComponentVisibleRole: {
return m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2 return m_accountInfoData.configType == serverConfigUtils::ConfigType::AmneziaPremiumV2
|| m_accountInfoData.configType == apiDefs::ConfigType::ExternalPremium || m_accountInfoData.configType == serverConfigUtils::ConfigType::ExternalPremium;
|| m_accountInfoData.configType == apiDefs::ConfigType::ExternalTrial;
} }
case IsSubscriptionRenewalAvailableRole: { case IsSubscriptionRenewalAvailableRole: {
return m_accountInfoData.isRenewalAvailable; return m_accountInfoData.isRenewalAvailable;
@@ -80,7 +80,7 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
return false; return false;
} }
case IsSubscriptionExpiredRole: { case IsSubscriptionExpiredRole: {
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { if (m_accountInfoData.configType == serverConfigUtils::ConfigType::AmneziaFreeV3) {
return false; return false;
} }
if (m_accountInfoData.isInAppPurchase) { if (m_accountInfoData.isInAppPurchase) {
@@ -92,7 +92,7 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate); return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate);
} }
case IsSubscriptionExpiringSoonRole: { case IsSubscriptionExpiringSoonRole: {
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { if (m_accountInfoData.configType == serverConfigUtils::ConfigType::AmneziaFreeV3) {
return false; return false;
} }
if (m_accountInfoData.isInAppPurchase) { if (m_accountInfoData.isInAppPurchase) {
@@ -124,7 +124,7 @@ void ApiAccountInfoModel::updateModel(const QJsonObject &accountInfoObject, cons
accountInfoData.maxDeviceCount = accountInfoObject.value(apiDefs::key::maxDeviceCount).toInt(); accountInfoData.maxDeviceCount = accountInfoObject.value(apiDefs::key::maxDeviceCount).toInt();
accountInfoData.subscriptionEndDate = accountInfoObject.value(apiDefs::key::subscriptionEndDate).toString(); accountInfoData.subscriptionEndDate = accountInfoObject.value(apiDefs::key::subscriptionEndDate).toString();
accountInfoData.configType = apiUtils::getConfigType(serverConfig); accountInfoData.configType = serverConfigUtils::configTypeFromJson(serverConfig);
const QJsonObject apiConfig = serverConfig.value(apiDefs::key::apiConfig).toObject(); const QJsonObject apiConfig = serverConfig.value(apiDefs::key::apiConfig).toObject();
accountInfoData.isInAppPurchase = apiConfig.value(apiDefs::key::isInAppPurchase).toBool(false); accountInfoData.isInAppPurchase = apiConfig.value(apiDefs::key::isInAppPurchase).toBool(false);
+2 -2
View File
@@ -5,7 +5,7 @@
#include <QJsonArray> #include <QJsonArray>
#include <QJsonObject> #include <QJsonObject>
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
@@ -56,7 +56,7 @@ private:
int activeDeviceCount; int activeDeviceCount;
int maxDeviceCount; int maxDeviceCount;
apiDefs::ConfigType configType; serverConfigUtils::ConfigType configType;
QStringList supportedProtocols; QStringList supportedProtocols;
+1 -1
View File
@@ -2,7 +2,7 @@
#include <QJsonObject> #include <QJsonObject>
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
#include "logger.h" #include "logger.h"
+1 -1
View File
@@ -2,7 +2,7 @@
#include <QJsonObject> #include <QJsonObject>
#include "core/utils/api/apiEnums.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
#include "logger.h" #include "logger.h"
+74 -227
View File
@@ -1,11 +1,12 @@
#include "serversModel.h" #include "serversModel.h"
#include "core/models/serverDescription.h"
#include <QHash> #include <QHash>
#include <QSet> #include <QSet>
#include <QJsonDocument> #include <QJsonDocument>
#include "core/models/serverConfig.h" #include "core/utils/serverConfigUtils.h"
#include "core/utils/api/apiEnums.h"
#include "core/utils/constants/apiKeys.h" #include "core/utils/constants/apiKeys.h"
#include "core/utils/constants/apiConstants.h" #include "core/utils/constants/apiConstants.h"
#include "core/utils/selfhosted/sshSession.h" #include "core/utils/selfhosted/sshSession.h"
@@ -19,42 +20,15 @@
using namespace amnezia; using namespace amnezia;
namespace
{
namespace configKey
{
constexpr char apiConfig[] = "api_config";
constexpr char serviceInfo[] = "service_info";
constexpr char availableCountries[] = "available_countries";
constexpr char serverCountryCode[] = "server_country_code";
constexpr char serverCountryName[] = "server_country_name";
constexpr char userCountryCode[] = "user_country_code";
constexpr char serviceType[] = "service_type";
constexpr char serviceProtocol[] = "service_protocol";
constexpr char publicKeyInfo[] = "public_key";
constexpr char expiresAt[] = "expires_at";
}
QString normalizeVpnKey(const QString &vpnKey)
{
QString normalized = vpnKey.trimmed();
if (normalized.startsWith(QStringLiteral("vpn://"), Qt::CaseInsensitive)) {
normalized = normalized.mid(QStringLiteral("vpn://").size());
}
return normalized;
}
}
ServersModel::ServersModel(QObject *parent) : QAbstractListModel(parent) ServersModel::ServersModel(QObject *parent) : QAbstractListModel(parent)
{ {
connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerNameChanged); connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerNameChanged);
connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) { connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) {
if (serverIndex < 0 || serverIndex >= m_servers.size()) { if (serverIndex < 0 || serverIndex >= m_descriptions.size()) {
return; return;
} }
auto defaultContainer = m_servers.at(serverIndex).defaultContainer(); auto defaultContainer = m_descriptions.at(serverIndex).defaultContainer;
emit ServersModel::defaultServerDefaultContainerChanged(defaultContainer); emit ServersModel::defaultServerDefaultContainerChanged(defaultContainer);
emit ServersModel::defaultServerNameChanged(); emit ServersModel::defaultServerNameChanged();
}); });
@@ -65,148 +39,73 @@ ServersModel::ServersModel(QObject *parent) : QAbstractListModel(parent)
int ServersModel::rowCount(const QModelIndex &parent) const int ServersModel::rowCount(const QModelIndex &parent) const
{ {
Q_UNUSED(parent); Q_UNUSED(parent);
return static_cast<int>(m_servers.size()); return static_cast<int>(m_descriptions.size());
} }
QVariant ServersModel::data(const QModelIndex &index, int role) const QVariant ServersModel::data(const QModelIndex &index, int role) const
{ {
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(m_servers.size())) { if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(m_descriptions.size())) {
return QVariant(); return QVariant();
} }
const ServerConfig &server = m_servers.at(index.row()); const ServerDescription &row = m_descriptions.at(index.row());
const int configVersion = server.configVersion(); const int configVersion = row.configVersion;
switch (role) { switch (role) {
case NameRole: { case NameRole:
if (configVersion) { return row.serverName;
if (server.isApiV1()) { case ServerDescriptionRole:
return server.as<ApiV1ServerConfig>()->name; return configVersion ? row.baseDescription : (row.baseDescription + row.hostName);
} else if (server.isApiV2()) { case CollapsedServerDescriptionRole:
return server.as<ApiV2ServerConfig>()->name; return row.collapsedServerDescription;
} case ExpandedServerDescriptionRole:
} return row.expandedServerDescription;
QString name = server.description(); case HostNameRole:
if (name.isEmpty()) { return row.hostName;
return server.hostName(); case CredentialsRole:
} return QVariant::fromValue(serverCredentials(index.row()));
return name; case CredentialsLoginRole:
} return serverCredentials(index.row()).userName;
case ServerDescriptionRole: { case IsDefaultRole:
auto description = getServerDescription(server, index.row()); return index.row() == m_defaultServerIndex;
return configVersion ? description : description + server.hostName(); case IsCurrentlyProcessedRole:
} return index.row() == m_processedServerIndex;
case HostNameRole: return server.hostName(); case HasWriteAccessRole:
case CredentialsRole: return QVariant::fromValue(serverCredentials(index.row())); return row.hasWriteAccess;
case CredentialsLoginRole: return serverCredentials(index.row()).userName; case ContainsAmneziaDnsRole:
case IsDefaultRole: return index.row() == m_defaultServerIndex; return row.primaryDnsIsAmnezia;
case IsCurrentlyProcessedRole: return index.row() == m_processedServerIndex; case DefaultContainerRole:
case HasWriteAccessRole: { return QVariant::fromValue(row.defaultContainer);
auto credentials = serverCredentials(index.row()); case HasInstalledContainers:
return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty()); return row.hasInstalledVpnContainers;
} case IsServerFromTelegramApiRole:
case ContainsAmneziaDnsRole: { return false;
QString primaryDns = server.dns1(); case IsServerFromGatewayApiRole:
return primaryDns == protocols::dns::amneziaDnsIp; return row.isServerFromGatewayApi;
} case ApiConfigRole:
case DefaultContainerRole: {
return server.defaultContainer();
}
case HasInstalledContainers: {
return serverHasInstalledContainers(index.row());
}
case IsServerFromTelegramApiRole: {
return configVersion == apiDefs::ConfigSource::Telegram;
}
case IsServerFromGatewayApiRole: {
return configVersion == apiDefs::ConfigSource::AmneziaGateway;
}
case ApiConfigRole: {
return QVariant(); return QVariant();
} case IsCountrySelectionAvailableRole:
case IsCountrySelectionAvailableRole: { return row.isCountrySelectionAvailable;
if (server.isApiV2()) { case ApiAvailableCountriesRole:
return !server.as<ApiV2ServerConfig>()->apiConfig.availableCountries.isEmpty(); return row.apiAvailableCountries;
} case ApiServerCountryCodeRole:
return false; return row.apiServerCountryCode;
} case HasAmneziaDns:
case ApiAvailableCountriesRole: { return row.primaryDnsIsAmnezia;
if (server.isApiV2()) { case IsAdVisibleRole:
return server.as<ApiV2ServerConfig>()->apiConfig.availableCountries; return row.isAdVisible;
} case AdHeaderRole:
return QJsonArray(); return row.adHeader;
} case AdDescriptionRole:
case ApiServerCountryCodeRole: { return row.adDescription;
if (server.isApiV2()) { case AdEndpointRole:
return server.as<ApiV2ServerConfig>()->apiConfig.serverCountryCode; return row.adEndpoint;
} case IsRenewalAvailableRole:
return QString(); return row.isRenewalAvailable;
} case IsSubscriptionExpiredRole:
case HasAmneziaDns: { return row.isSubscriptionExpired;
QString primaryDns = server.dns1(); case IsSubscriptionExpiringSoonRole:
return primaryDns == protocols::dns::amneziaDnsIp; return row.isSubscriptionExpiringSoon;
}
case IsAdVisibleRole: {
if (server.isApiV2()) {
return server.as<ApiV2ServerConfig>()->apiConfig.serviceInfo.isAdVisible;
}
return false;
}
case AdHeaderRole: {
if (server.isApiV2()) {
return server.as<ApiV2ServerConfig>()->apiConfig.serviceInfo.adHeader;
}
return QString();
}
case AdDescriptionRole: {
if (server.isApiV2()) {
return server.as<ApiV2ServerConfig>()->apiConfig.serviceInfo.adDescription;
}
return QString();
}
case AdEndpointRole: {
if (server.isApiV2()) {
return server.as<ApiV2ServerConfig>()->apiConfig.serviceInfo.adEndpoint;
}
return QString();
}
case IsRenewalAvailableRole: {
if (server.isApiV2()) {
return server.as<ApiV2ServerConfig>()->apiConfig.serviceInfo.isRenewalAvailable;
}
return false;
}
case IsSubscriptionExpiredRole: {
if (!server.isApiV2()) {
return false;
}
const ApiConfig &apiConfig = server.as<ApiV2ServerConfig>()->apiConfig;
if (apiConfig.isInAppPurchase) {
return false;
}
if (apiConfig.subscriptionExpiredByServer) {
return true;
}
if (apiConfig.subscription.endDate.isEmpty()) {
return false;
}
return apiUtils::isSubscriptionExpired(apiConfig.subscription.endDate);
}
case IsSubscriptionExpiringSoonRole: {
if (!server.isApiV2()) {
return false;
}
const ApiConfig &apiConfig = server.as<ApiV2ServerConfig>()->apiConfig;
if (apiConfig.isInAppPurchase) {
return false;
}
if (apiConfig.subscription.endDate.isEmpty()) {
return false;
}
return apiUtils::isSubscriptionExpiringSoon(apiConfig.subscription.endDate);
}
} }
return QVariant(); return QVariant();
@@ -218,12 +117,11 @@ QVariant ServersModel::data(const int index, int role) const
return data(modelIndex, role); return data(modelIndex, role);
} }
void ServersModel::updateModel(const QVector<ServerConfig> &servers, int defaultServerIndex, bool isAmneziaDnsEnabled) void ServersModel::updateModel(const QVector<ServerDescription> &descriptions, int defaultServerIndex)
{ {
beginResetModel(); beginResetModel();
m_servers = servers; m_descriptions = descriptions;
m_defaultServerIndex = defaultServerIndex; m_defaultServerIndex = defaultServerIndex;
m_isAmneziaDnsEnabled = isAmneziaDnsEnabled;
endResetModel(); endResetModel();
emit defaultServerIndexChanged(m_defaultServerIndex); emit defaultServerIndexChanged(m_defaultServerIndex);
emit processedServerChanged(); emit processedServerChanged();
@@ -234,43 +132,15 @@ const int ServersModel::getDefaultServerIndex()
return m_defaultServerIndex; return m_defaultServerIndex;
} }
QString ServersModel::getServerDescription(const ServerConfig &server, const int index) const
{
const int configVersion = server.configVersion();
QString description;
if (server.isApiV2()) {
const ApiV2ServerConfig *apiV2 = server.as<ApiV2ServerConfig>();
if (apiV2 && !apiV2->apiConfig.serverCountryCode.isEmpty()) {
return apiV2->apiConfig.serverCountryName;
}
return apiV2 ? apiV2->description : server.description();
} else if (server.isApiV1()) {
const ApiV1ServerConfig *apiV1 = server.as<ApiV1ServerConfig>();
return apiV1 ? apiV1->description : server.description();
} else if (data(index, HasWriteAccessRole).toBool()) {
QMap<DockerContainer, ContainerConfig> containers = server.containers();
bool isDnsInstalled = containers.contains(DockerContainer::Dns);
if (m_isAmneziaDnsEnabled && isDnsInstalled) {
description += "Amnezia DNS | ";
}
} else {
if (data(index, HasAmneziaDns).toBool()) {
description += "Amnezia DNS | ";
}
}
return description;
}
const int ServersModel::getServersCount() const int ServersModel::getServersCount()
{ {
return m_servers.size(); return m_descriptions.size();
} }
bool ServersModel::hasServerWithWriteAccess() bool ServersModel::hasServerWithWriteAccess()
{ {
for (size_t i = 0; i < getServersCount(); i++) { for (size_t i = 0; i < getServersCount(); i++) {
if (qvariant_cast<bool>(data(i, HasWriteAccessRole))) { if (qvariant_cast<bool>(data(static_cast<int>(i), HasWriteAccessRole))) {
return true; return true;
} }
} }
@@ -350,29 +220,17 @@ QHash<int, QByteArray> ServersModel::roleNames() const
roles[IsSubscriptionExpiredRole] = "isSubscriptionExpired"; roles[IsSubscriptionExpiredRole] = "isSubscriptionExpired";
roles[IsSubscriptionExpiringSoonRole] = "isSubscriptionExpiringSoon"; roles[IsSubscriptionExpiringSoonRole] = "isSubscriptionExpiringSoon";
roles[HasAmneziaDns] = "hasAmneziaDns";
return roles; return roles;
} }
ServerCredentials ServersModel::serverCredentials(int index) const ServerCredentials ServersModel::serverCredentials(int index) const
{ {
if (index < 0 || index >= m_servers.size()) { if (index < 0 || index >= m_descriptions.size()) {
return ServerCredentials(); return ServerCredentials();
} }
const ServerConfig &server = m_servers.at(index); return m_descriptions.at(index).selfHostedSshCredentials;
if (server.isSelfHosted()) {
const SelfHostedServerConfig *selfHosted = server.as<SelfHostedServerConfig>();
if (selfHosted) {
ServerCredentials credentials;
credentials.hostName = selfHosted->hostName;
credentials.userName = selfHosted->userName.value_or("");
credentials.secretData = selfHosted->password.value_or("");
credentials.port = selfHosted->port.value_or(22);
return credentials;
}
}
return ServerCredentials();
} }
bool ServersModel::isServerFromApi(const int serverIndex) bool ServersModel::isServerFromApi(const int serverIndex)
@@ -405,21 +263,10 @@ QVariant ServersModel::getProcessedServerData(const QString &roleString)
return {}; return {};
} }
bool ServersModel::serverHasInstalledContainers(const int serverIndex) const bool ServersModel::serverHasInstalledContainers(const int serverIndex) const
{ {
const ServerConfig &server = m_servers.at(serverIndex); if (serverIndex < 0 || serverIndex >= m_descriptions.size()) {
QMap<DockerContainer, ContainerConfig> containers = server.containers(); return false;
for (auto it = containers.begin(); it != containers.end(); ++it) {
DockerContainer container = it.key();
if (ContainerUtils::containerService(container) == ServiceType::Vpn) {
return true;
}
if (container == DockerContainer::SSXray) {
return true;
}
} }
return false; return m_descriptions.at(serverIndex).hasInstalledVpnContainers;
} }
+6 -11
View File
@@ -5,7 +5,7 @@
#include <QVector> #include <QVector>
#include "core/utils/selfhosted/sshSession.h" #include "core/utils/selfhosted/sshSession.h"
#include "core/models/serverConfig.h" #include "core/models/serverDescription.h"
class ServersModel : public QAbstractListModel class ServersModel : public QAbstractListModel
{ {
@@ -75,14 +75,13 @@ public slots:
bool isServerFromApi(const int serverIndex); bool isServerFromApi(const int serverIndex);
void updateModel(const QVector<ServerConfig> &servers, int defaultServerIndex, bool isAmneziaDnsEnabled = false); void updateModel(const QVector<amnezia::ServerDescription> &descriptions, int defaultServerIndex);
protected: protected:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
signals: signals:
void processedServerIndexChanged(const int index); void processedServerIndexChanged(const int index);
// emitted when the processed server index or processed server data is changed
void processedServerChanged(); void processedServerChanged();
void defaultServerIndexChanged(const int index); void defaultServerIndexChanged(const int index);
@@ -97,16 +96,12 @@ signals:
private: private:
ServerCredentials serverCredentials(int index) const; ServerCredentials serverCredentials(int index) const;
QString getServerDescription(const ServerConfig &server, const int index) const;
bool serverHasInstalledContainers(const int serverIndex) const; bool serverHasInstalledContainers(const int serverIndex) const;
QVector<ServerConfig> m_servers; QVector<amnezia::ServerDescription> m_descriptions;
int m_defaultServerIndex; int m_defaultServerIndex = -1;
int m_processedServerIndex; int m_processedServerIndex = -1;
bool m_isAmneziaDnsEnabled = false;
}; };
#endif // SERVERSMODEL_H #endif // SERVERSMODEL_H
+1 -1
View File
@@ -182,7 +182,7 @@ Button {
} }
onClicked: { onClicked: {
ServersUiController.setProcessedServerIndex(ServersUiController.defaultIndex) ServersUiController.setProcessedServerIndex(ServersUiController.defaultServerIndex)
ConnectionController.connectButtonClicked() ConnectionController.connectButtonClicked()
} }
+1 -1
View File
@@ -13,7 +13,7 @@ Item {
onButtonStartChanged: { onButtonStartChanged: {
if (buttonStart) { if (buttonStart) {
ServersUiController.setProcessedServerIndex(ServersUiController.defaultIndex) ServersUiController.setProcessedServerIndex(ServersUiController.defaultServerIndex)
ConnectionController.connectButtonClicked() ConnectionController.connectButtonClicked()
} }
} }
@@ -58,7 +58,7 @@ ListViewType {
if (checked) { if (checked) {
containersDropDown.closeTriggered() containersDropDown.closeTriggered()
ServersUiController.setDefaultContainer(ServersUiController.defaultIndex, proxyDefaultServerContainersModel.mapToSource(index)) ServersUiController.setDefaultContainer(ServersUiController.getServerId(ServersUiController.defaultServerIndex), proxyDefaultServerContainersModel.mapToSource(index))
} else { } else {
ServersUiController.processedContainerIndex = proxyDefaultServerContainersModel.mapToSource(index) ServersUiController.processedContainerIndex = proxyDefaultServerContainersModel.mapToSource(index)
PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings) PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings)
@@ -46,7 +46,7 @@ DrawerType2 {
} }
if (serverName.textField.text !== root.serverNameText) { if (serverName.textField.text !== root.serverNameText) {
ServersUiController.editServerName(ServersUiController.processedIndex, serverName.textField.text); ServersUiController.editServerName(ServersUiController.getServerId(ServersUiController.processedServerIndex), serverName.textField.text);
} }
root.closeTriggered() root.closeTriggered()
} }
+6 -6
View File
@@ -17,7 +17,7 @@ import "../Config"
ListViewType { ListViewType {
id: root id: root
property int selectedIndex: ServersUiController.defaultIndex property int selectedIndex: ServersUiController.defaultServerIndex
anchors.top: serversMenuHeader.bottom anchors.top: serversMenuHeader.bottom
anchors.right: parent.right anchors.right: parent.right
@@ -29,8 +29,8 @@ ListViewType {
Connections { Connections {
target: ServersUiController target: ServersUiController
function onDefaultServerIndexChanged(serverIndex) { function onDefaultServerIndexChanged() {
root.selectedIndex = serverIndex root.selectedIndex = ServersUiController.defaultServerIndex
} }
} }
@@ -86,7 +86,7 @@ ListViewType {
root.selectedIndex = index root.selectedIndex = index
ServersUiController.setDefaultServerIndex(index) ServersUiController.setDefaultServerAtIndex(index)
} }
Keys.onEnterPressed: serverRadioButton.clicked() Keys.onEnterPressed: serverRadioButton.clicked()
@@ -106,14 +106,14 @@ ListViewType {
z: 1 z: 1
onClicked: function() { onClicked: function() {
ServersUiController.processedIndex = index ServersUiController.processedServerIndex = index
if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) { if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) {
if (ServersModel.getProcessedServerData("isCountrySelectionAvailable")) { if (ServersModel.getProcessedServerData("isCountrySelectionAvailable")) {
PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries) PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries)
} else { } else {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
let result = SubscriptionUiController.getAccountInfo(ServersUiController.getProcessedServerIndex(), false) let result = SubscriptionUiController.getAccountInfo(ServersUiController.getServerId(ServersUiController.processedServerIndex), false)
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
if (!result) { if (!result) {
return return
@@ -34,19 +34,19 @@ ListViewType {
if (isVpnContainer) { if (isVpnContainer) {
// var isThirdPartyConfig = root.model.data(index, ContainersModel.IsThirdPartyConfigRole) // var isThirdPartyConfig = root.model.data(index, ContainersModel.IsThirdPartyConfigRole)
if (isThirdPartyConfig) { if (isThirdPartyConfig) {
InstallController.updateProtocols(ServersUiController.processedIndex, containerIndex) InstallController.updateProtocols(ServersUiController.getServerId(ServersUiController.processedServerIndex), containerIndex)
PageController.goToPage(PageEnum.PageProtocolRaw) PageController.goToPage(PageEnum.PageProtocolRaw)
return return
} }
} }
if (isIpsec) { if (isIpsec) {
InstallController.updateProtocols(ServersUiController.processedIndex, containerIndex) InstallController.updateProtocols(ServersUiController.getServerId(ServersUiController.processedServerIndex), containerIndex)
PageController.goToPage(PageEnum.PageProtocolRaw) PageController.goToPage(PageEnum.PageProtocolRaw)
} else if (isDns) { } else if (isDns) {
PageController.goToPage(PageEnum.PageServiceDnsSettings) PageController.goToPage(PageEnum.PageServiceDnsSettings)
} else { } else {
InstallController.updateProtocols(ServersUiController.processedIndex, containerIndex) InstallController.updateProtocols(ServersUiController.getServerId(ServersUiController.processedServerIndex), containerIndex)
PageController.goToPage(PageEnum.PageSettingsServerProtocol) PageController.goToPage(PageEnum.PageSettingsServerProtocol)
} }
@@ -76,7 +76,7 @@ DrawerType2 {
textColor: AmneziaStyle.color.midnightBlack textColor: AmneziaStyle.color.midnightBlack
clickedFunc: function() { clickedFunc: function() {
SubscriptionUiController.getRenewalLink(ServersUiController.defaultIndex) SubscriptionUiController.getRenewalLink(ServersUiController.getServerId(ServersUiController.defaultServerIndex))
} }
} }
@@ -96,7 +96,7 @@ DrawerType2 {
clickedFunc: function() { clickedFunc: function() {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
let result = SubscriptionUiController.getAccountInfo(ServersUiController.defaultIndex, false) let result = SubscriptionUiController.getAccountInfo(ServersUiController.getServerId(ServersUiController.defaultServerIndex), false)
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
if (result) { if (result) {
root.closeTriggered() root.closeTriggered()
+2 -2
View File
@@ -344,14 +344,14 @@ PageType {
Keys.onReturnPressed: this.clicked() Keys.onReturnPressed: this.clicked()
onClicked: { onClicked: {
ServersUiController.processedIndex = ServersUiController.defaultIndex ServersUiController.setProcessedServerIndex(ServersUiController.defaultServerIndex)
if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) { if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) {
if (ServersModel.getProcessedServerData("isCountrySelectionAvailable")) { if (ServersModel.getProcessedServerData("isCountrySelectionAvailable")) {
PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries) PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries)
} else { } else {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
let result = SubscriptionUiController.getAccountInfo(ServersUiController.getProcessedServerIndex(), false) let result = SubscriptionUiController.getAccountInfo(ServersUiController.getServerId(ServersUiController.processedServerIndex), false)
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
if (!result) { if (!result) {
return return
@@ -441,7 +441,7 @@ PageType {
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(ServersUiController.processedIndex, ServersUiController.processedContainerIndex, ProtocolEnum.Awg) InstallController.updateContainer(ServersUiController.getServerId(ServersUiController.processedServerIndex), ServersUiController.processedContainerIndex, ProtocolEnum.Awg)
} }
var noButtonFunction = function() {} var noButtonFunction = function() {}
@@ -561,7 +561,7 @@ PageType {
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(ServersUiController.processedIndex, ServersUiController.processedContainerIndex, ProtocolEnum.Awg) InstallController.updateContainer(ServersUiController.getServerId(ServersUiController.processedServerIndex), ServersUiController.processedContainerIndex, ProtocolEnum.Awg)
} }
var noButtonFunction = function() {} var noButtonFunction = function() {}
@@ -434,7 +434,7 @@ PageType {
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(ServersUiController.processedIndex, ServersUiController.processedContainerIndex, ProtocolEnum.OpenVpn) InstallController.updateContainer(ServersUiController.getServerId(ServersUiController.processedServerIndex), ServersUiController.processedContainerIndex, ProtocolEnum.OpenVpn)
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) { if (!GC.isMobile()) {
+1 -1
View File
@@ -184,7 +184,7 @@ PageType {
var yesButtonFunction = function() { var yesButtonFunction = function() {
PageController.goToPage(PageEnum.PageDeinstalling) PageController.goToPage(PageEnum.PageDeinstalling)
InstallController.removeContainer(ServersUiController.processedIndex, ServersUiController.processedContainerIndex) InstallController.removeContainer(ServersUiController.getServerId(ServersUiController.processedServerIndex), ServersUiController.processedContainerIndex)
} }
var noButtonFunction = function() {} var noButtonFunction = function() {}
@@ -129,7 +129,7 @@ PageType {
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(ServersUiController.processedIndex, ServersUiController.processedContainerIndex, ProtocolEnum.WireGuard) InstallController.updateContainer(ServersUiController.getServerId(ServersUiController.processedServerIndex), ServersUiController.processedContainerIndex, ProtocolEnum.WireGuard)
} }
var noButtonFunction = function() {} var noButtonFunction = function() {}
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
@@ -129,7 +129,7 @@ PageType {
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(ServersUiController.processedIndex, ServersUiController.processedContainerIndex, ProtocolEnum.WireGuard) InstallController.updateContainer(ServersUiController.getServerId(ServersUiController.processedServerIndex), ServersUiController.processedContainerIndex, ProtocolEnum.WireGuard)
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) { if (!GC.isMobile()) {

Some files were not shown because too many files have changed in this diff Show More