mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
refactoring: keep moving
This commit is contained in:
69
.cursorrules
Normal file
69
.cursorrules
Normal file
@@ -0,0 +1,69 @@
|
||||
# Amnezia VPN Client - MVVM Refactoring Rules
|
||||
|
||||
## Architecture Requirements
|
||||
|
||||
### MVVM Pattern
|
||||
- Follow Model-View-ViewModel architecture strictly
|
||||
- Maintain clear separation of concerns between layers
|
||||
- UI controllers should only handle user input and delegate to core controllers
|
||||
- Core controllers contain all business logic and data manipulation
|
||||
|
||||
### Dependencies Direction
|
||||
- UI layer depends on Core layer (unidirectional dependency)
|
||||
- UI controllers must not depend on each other
|
||||
- Core controllers must not depend on each other (exceptions: ServerController, VpnConfigurationsController, GatewayController can be created "on the fly")
|
||||
|
||||
### Settings Usage
|
||||
- UI classes must NOT use Settings class directly
|
||||
- Create wrapper methods in core controllers for Settings operations
|
||||
|
||||
### Server Controller Creation
|
||||
- ServerController creation must happen in Core controllers, never in UI
|
||||
- Remove direct instantiation: `new ServerController(m_settings)` from UI code
|
||||
|
||||
## Code Organization
|
||||
|
||||
### Folder Structure
|
||||
- Core controllers: `client/core/controllers/`
|
||||
- Core models: `client/core/models/`
|
||||
- UI controllers: `client/ui/controllers/`
|
||||
- UI models: `client/ui/models/`
|
||||
- Common models and controllers in root of respective folders
|
||||
|
||||
### Controller Management
|
||||
- All controllers must be instantiated in central `coreController`
|
||||
- Dependencies between core controllers resolved in `coreController`
|
||||
- UI controllers accept core controllers via constructor injection
|
||||
- UI controllers should be renamed with "UI" suffix (e.g., `exportUIController`)
|
||||
|
||||
## Code Style
|
||||
|
||||
### Comments
|
||||
- Do NOT include comments in code
|
||||
- Code should be self-documenting
|
||||
|
||||
### Models Behavior
|
||||
- Models should only display data
|
||||
- Keep core models as pure data structures without business logic
|
||||
|
||||
## Refactoring Process
|
||||
|
||||
### UI Controller Refactoring
|
||||
- Remove all business logic from UI controllers
|
||||
- Replace direct method calls with delegation to core controllers
|
||||
- Maintain only UI-specific logic (signals, model updates)
|
||||
- Remove Settings dependencies
|
||||
|
||||
### Core Controller Pattern
|
||||
- Create corresponding methods in core controllers for UI operations
|
||||
- Core controllers handle all complex logic, network operations, file I/O
|
||||
- Return structured results with error codes and data
|
||||
- Manage ServerController lifecycle internally
|
||||
|
||||
## Git Workflow
|
||||
- Use `git mv` for renaming controllers to maintain history
|
||||
|
||||
## Error Handling
|
||||
- Core controllers return structured error results
|
||||
- UI controllers only handle error presentation
|
||||
- Maintain consistent error propagation patterns
|
||||
@@ -21,7 +21,7 @@ set(HEADERS ${HEADERS}
|
||||
${CLIENT_ROOT_DIR}/core/controllers/dnsController.h
|
||||
${CLIENT_ROOT_DIR}/core/controllers/splitTunnelingController.h
|
||||
${CLIENT_ROOT_DIR}/core/controllers/settingsController.h
|
||||
${CLIENT_ROOT_DIR}/core/controllers/vpnConnectionController.h
|
||||
${CLIENT_ROOT_DIR}/core/controllers/connectionController.h
|
||||
${CLIENT_ROOT_DIR}/core/controllers/vpnConfigurationController.h
|
||||
${CLIENT_ROOT_DIR}/protocols/protocols_defs.h
|
||||
${CLIENT_ROOT_DIR}/protocols/qml_register_protocols.h
|
||||
@@ -77,7 +77,7 @@ set(SOURCES ${SOURCES}
|
||||
${CLIENT_ROOT_DIR}/core/controllers/dnsController.cpp
|
||||
${CLIENT_ROOT_DIR}/core/controllers/splitTunnelingController.cpp
|
||||
${CLIENT_ROOT_DIR}/core/controllers/settingsController.cpp
|
||||
${CLIENT_ROOT_DIR}/core/controllers/vpnConnectionController.cpp
|
||||
${CLIENT_ROOT_DIR}/core/controllers/connectionController.cpp
|
||||
${CLIENT_ROOT_DIR}/core/controllers/vpnConfigurationController.cpp
|
||||
${CLIENT_ROOT_DIR}/protocols/protocols_defs.cpp
|
||||
${CLIENT_ROOT_DIR}/ui/qautostart.cpp
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#include "awg_configurator.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
AwgConfigurator::AwgConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent)
|
||||
: WireguardConfigurator(settings, serverController, true, parent)
|
||||
{
|
||||
|
||||
@@ -1,29 +1,32 @@
|
||||
#include "configurator_base.h"
|
||||
#include "core/networkUtilities.h"
|
||||
#include "core/models/protocols/protocolConfig.h"
|
||||
#include <variant>
|
||||
|
||||
ConfiguratorBase::ConfiguratorBase(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent)
|
||||
: QObject { parent }, m_settings(settings), m_serverController(serverController)
|
||||
{
|
||||
}
|
||||
|
||||
QString ConfiguratorBase::processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString)
|
||||
void ConfiguratorBase::processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QSharedPointer<ProtocolConfig> &protocolConfig)
|
||||
{
|
||||
processConfigWithDnsSettings(dns, protocolConfigString);
|
||||
return protocolConfigString;
|
||||
processConfigWithDnsSettings(dns, protocolConfig);
|
||||
}
|
||||
|
||||
QString ConfiguratorBase::processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString)
|
||||
void ConfiguratorBase::processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QSharedPointer<ProtocolConfig> &protocolConfig)
|
||||
{
|
||||
processConfigWithDnsSettings(dns, protocolConfigString);
|
||||
return protocolConfigString;
|
||||
processConfigWithDnsSettings(dns, protocolConfig);
|
||||
}
|
||||
|
||||
void ConfiguratorBase::processConfigWithDnsSettings(const QPair<QString, QString> &dns, QString &protocolConfigString)
|
||||
void ConfiguratorBase::processConfigWithDnsSettings(const QPair<QString, QString> &dns, QSharedPointer<ProtocolConfig> &protocolConfig)
|
||||
{
|
||||
protocolConfigString.replace("$PRIMARY_DNS", dns.first);
|
||||
protocolConfigString.replace("$SECONDARY_DNS", dns.second);
|
||||
ProtocolConfigVariant variant = ProtocolConfig::getProtocolConfigVariant(protocolConfig);
|
||||
std::visit([&dns](const auto &config) -> void {
|
||||
config->clientProtocolConfig.nativeConfig.replace("$PRIMARY_DNS", dns.first);
|
||||
config->clientProtocolConfig.nativeConfig.replace("$SECONDARY_DNS", dns.second);
|
||||
}, variant);
|
||||
}
|
||||
|
||||
ConfiguratorBase::Vars ConfiguratorBase::generateProtocolVars(const ServerCredentials &credentials, DockerContainer container,
|
||||
|
||||
@@ -23,16 +23,16 @@ public:
|
||||
virtual QSharedPointer<ProtocolConfig> createConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QSharedPointer<ProtocolConfig> &protocolConfig, ErrorCode &errorCode) = 0;
|
||||
|
||||
virtual QString processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString);
|
||||
virtual QString processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString);
|
||||
virtual void processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QSharedPointer<ProtocolConfig> &protocolConfig);
|
||||
virtual void processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QSharedPointer<ProtocolConfig> &protocolConfig);
|
||||
|
||||
virtual Vars generateProtocolVars(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QSharedPointer<ProtocolConfig> &protocolConfig) const;
|
||||
|
||||
protected:
|
||||
void processConfigWithDnsSettings(const QPair<QString, QString> &dns, QString &protocolConfigString);
|
||||
void processConfigWithDnsSettings(const QPair<QString, QString> &dns, QSharedPointer<ProtocolConfig> &protocolConfig);
|
||||
|
||||
Vars generateCommonVars(const ServerCredentials &credentials, DockerContainer container) const;
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "openvpn_configurator.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QTemporaryDir>
|
||||
@@ -14,6 +13,8 @@
|
||||
#endif
|
||||
|
||||
#include "core/networkUtilities.h"
|
||||
#include "core/models/protocols/protocolConfig.h"
|
||||
#include <variant>
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "core/controllers/selfhosted/serverController.h"
|
||||
#include "core/scripts_registry.h"
|
||||
@@ -146,83 +147,93 @@ QSharedPointer<ProtocolConfig> OpenVpnConfigurator::createConfig(const ServerCre
|
||||
return openVpnConfig;
|
||||
}
|
||||
|
||||
QString OpenVpnConfigurator::processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString)
|
||||
void OpenVpnConfigurator::processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QSharedPointer<ProtocolConfig> &protocolConfig)
|
||||
{
|
||||
processConfigWithDnsSettings(dns, protocolConfigString);
|
||||
processConfigWithDnsSettings(dns, protocolConfig);
|
||||
|
||||
QJsonObject json = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
||||
QString config = json[config_key::config].toString();
|
||||
ProtocolConfigVariant variant = ProtocolConfig::getProtocolConfigVariant(protocolConfig);
|
||||
std::visit([this, &dns, isApiConfig](const auto &config) -> void {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(config)>, QSharedPointer<OpenVpnProtocolConfig>>) {
|
||||
QString &nativeConfig = config->clientProtocolConfig.nativeConfig;
|
||||
|
||||
if (!isApiConfig) {
|
||||
QRegularExpression regex("redirect-gateway.*");
|
||||
config.replace(regex, "");
|
||||
|
||||
// We don't use secondary DNS if primary DNS is AmneziaDNS
|
||||
if (dns.first.contains(protocols::dns::amneziaDnsIp)) {
|
||||
QRegularExpression dnsRegex("dhcp-option DNS " + dns.second);
|
||||
config.replace(dnsRegex, "");
|
||||
}
|
||||
if (!isApiConfig) {
|
||||
QRegularExpression regex("redirect-gateway.*");
|
||||
nativeConfig.replace(regex, "");
|
||||
|
||||
// We don't use secondary DNS if primary DNS is AmneziaDNS
|
||||
if (dns.first.contains(protocols::dns::amneziaDnsIp)) {
|
||||
QRegularExpression dnsRegex("dhcp-option DNS " + dns.second);
|
||||
nativeConfig.replace(dnsRegex, "");
|
||||
}
|
||||
|
||||
if (!m_settings->isSitesSplitTunnelingEnabled()) {
|
||||
config.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
|
||||
config.append("block-ipv6\n");
|
||||
} else if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
||||
if (!m_settings->isSitesSplitTunnelingEnabled()) {
|
||||
nativeConfig.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
|
||||
nativeConfig.append("block-ipv6\n");
|
||||
} else if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
||||
|
||||
// no redirect-gateway
|
||||
} else if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
|
||||
// no redirect-gateway
|
||||
} else if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
|
||||
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
||||
config.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n");
|
||||
// Prevent ipv6 leak
|
||||
nativeConfig.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n");
|
||||
// Prevent ipv6 leak
|
||||
#endif
|
||||
config.append("block-ipv6\n");
|
||||
}
|
||||
}
|
||||
nativeConfig.append("block-ipv6\n");
|
||||
}
|
||||
|
||||
QStringList routeList = m_settings->vpnRoutes();
|
||||
|
||||
if (!routeList.isEmpty()) {
|
||||
for (auto route : routeList) {
|
||||
nativeConfig.append("\nroute " + route + " 255.255.255.255 vpn_gateway\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MZ_WINDOWS
|
||||
config.replace("block-outside-dns", "");
|
||||
nativeConfig.replace("block-outside-dns", "");
|
||||
#endif
|
||||
|
||||
#if (defined(MZ_MACOS) || defined(MZ_LINUX))
|
||||
QString dnsConf = QString("\nscript-security 2\n"
|
||||
"up %1/update-resolv-conf.sh\n"
|
||||
"down %1/update-resolv-conf.sh\n")
|
||||
.arg(qApp->applicationDirPath());
|
||||
QString dnsConf = QString("\nscript-security 2\n"
|
||||
"up %1/update-resolv-conf.sh\n"
|
||||
"down %1/update-resolv-conf.sh\n")
|
||||
.arg(qApp->applicationDirPath());
|
||||
|
||||
config.append(dnsConf);
|
||||
nativeConfig.append(dnsConf);
|
||||
#endif
|
||||
|
||||
json[config_key::config] = config;
|
||||
return QJsonDocument(json).toJson();
|
||||
}
|
||||
}, variant);
|
||||
}
|
||||
|
||||
QString OpenVpnConfigurator::processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString)
|
||||
void OpenVpnConfigurator::processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QSharedPointer<ProtocolConfig> &protocolConfig)
|
||||
{
|
||||
processConfigWithDnsSettings(dns, protocolConfigString);
|
||||
processConfigWithDnsSettings(dns, protocolConfig);
|
||||
|
||||
QJsonObject json = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
||||
QString config = json[config_key::config].toString();
|
||||
ProtocolConfigVariant variant = ProtocolConfig::getProtocolConfigVariant(protocolConfig);
|
||||
std::visit([&dns](const auto &config) -> void {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(config)>, QSharedPointer<OpenVpnProtocolConfig>>) {
|
||||
QString &nativeConfig = config->clientProtocolConfig.nativeConfig;
|
||||
|
||||
QRegularExpression regex("redirect-gateway.*");
|
||||
config.replace(regex, "");
|
||||
QRegularExpression regex("redirect-gateway.*");
|
||||
nativeConfig.replace(regex, "");
|
||||
|
||||
// We don't use secondary DNS if primary DNS is AmneziaDNS
|
||||
if (dns.first.contains(protocols::dns::amneziaDnsIp)) {
|
||||
QRegularExpression dnsRegex("dhcp-option DNS " + dns.second);
|
||||
config.replace(dnsRegex, "");
|
||||
}
|
||||
// We don't use secondary DNS if primary DNS is AmneziaDNS
|
||||
if (dns.first.contains(protocols::dns::amneziaDnsIp)) {
|
||||
QRegularExpression dnsRegex("dhcp-option DNS " + dns.second);
|
||||
nativeConfig.replace(dnsRegex, "");
|
||||
}
|
||||
|
||||
config.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
|
||||
nativeConfig.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
|
||||
|
||||
// Prevent ipv6 leak
|
||||
config.append("block-ipv6\n");
|
||||
// Prevent ipv6 leak
|
||||
nativeConfig.append("block-ipv6\n");
|
||||
|
||||
// remove block-outside-dns for all exported configs
|
||||
config.replace("block-outside-dns", "");
|
||||
|
||||
json[config_key::config] = config;
|
||||
return QJsonDocument(json).toJson();
|
||||
// remove block-outside-dns for all exported configs
|
||||
nativeConfig.replace("block-outside-dns", "");
|
||||
}
|
||||
}, variant);
|
||||
}
|
||||
|
||||
ErrorCode OpenVpnConfigurator::signCert(DockerContainer container, const ServerCredentials &credentials, QString clientId)
|
||||
|
||||
@@ -28,10 +28,10 @@ public:
|
||||
QSharedPointer<ProtocolConfig> createConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QSharedPointer<ProtocolConfig> &protocolConfig, ErrorCode &errorCode) override;
|
||||
|
||||
QString processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString);
|
||||
QString processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString);
|
||||
void processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QSharedPointer<ProtocolConfig> &protocolConfig) override;
|
||||
void processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QSharedPointer<ProtocolConfig> &protocolConfig) override;
|
||||
|
||||
Vars generateProtocolVars(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QSharedPointer<ProtocolConfig> &protocolConfig) const override;
|
||||
|
||||
@@ -296,18 +296,14 @@ QSharedPointer<ProtocolConfig> WireguardConfigurator::createConfig(const ServerC
|
||||
return result;
|
||||
}
|
||||
|
||||
QString WireguardConfigurator::processConfigWithLocalSettings(const QPair<QString, QString> &dns,
|
||||
const bool isApiConfig, QString &protocolConfigString)
|
||||
void WireguardConfigurator::processConfigWithLocalSettings(const QPair<QString, QString> &dns,
|
||||
const bool isApiConfig, QSharedPointer<ProtocolConfig> &protocolConfig)
|
||||
{
|
||||
processConfigWithDnsSettings(dns, protocolConfigString);
|
||||
|
||||
return protocolConfigString;
|
||||
processConfigWithDnsSettings(dns, protocolConfig);
|
||||
}
|
||||
|
||||
QString WireguardConfigurator::processConfigWithExportSettings(const QPair<QString, QString> &dns,
|
||||
const bool isApiConfig, QString &protocolConfigString)
|
||||
void WireguardConfigurator::processConfigWithExportSettings(const QPair<QString, QString> &dns,
|
||||
const bool isApiConfig, QSharedPointer<ProtocolConfig> &protocolConfig)
|
||||
{
|
||||
processConfigWithDnsSettings(dns, protocolConfigString);
|
||||
|
||||
return protocolConfigString;
|
||||
processConfigWithDnsSettings(dns, protocolConfig);
|
||||
}
|
||||
|
||||
@@ -32,10 +32,10 @@ public:
|
||||
QSharedPointer<ProtocolConfig> createConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QSharedPointer<ProtocolConfig> &protocolConfig, ErrorCode &errorCode) override;
|
||||
|
||||
QString processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString);
|
||||
QString processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString);
|
||||
void processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QSharedPointer<ProtocolConfig> &protocolConfig) override;
|
||||
void processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QSharedPointer<ProtocolConfig> &protocolConfig) override;
|
||||
|
||||
Vars generateProtocolVars(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QSharedPointer<ProtocolConfig> &protocolConfig) const override;
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
#include "core/networkUtilities.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
#include "settings.h"
|
||||
#include "core/models/protocols/awgProtocolConfig.h"
|
||||
#include "core/models/protocols/wireguardProtocolConfig.h"
|
||||
#include "core/models/protocols/openvpnProtocolConfig.h"
|
||||
#include "core/models/protocols/shadowsocksProtocolConfig.h"
|
||||
#include "core/models/protocols/cloakProtocolConfig.h"
|
||||
|
||||
ConfigController::ConfigController(std::shared_ptr<Settings> settings, QObject *parent)
|
||||
: QObject(parent), m_settings(settings)
|
||||
@@ -151,3 +156,69 @@ void ConfigController::updateServerInSettings(const QSharedPointer<ServerConfig>
|
||||
{
|
||||
m_settings->editServer(serverIndex, serverConfig->toJson());
|
||||
}
|
||||
|
||||
bool ConfigController::isDefaultServerDefaultContainerHasSplitTunneling() const
|
||||
{
|
||||
int defaultServerIndex = m_settings->defaultServerIndex();
|
||||
auto servers = m_settings->serversArray();
|
||||
if (defaultServerIndex >= servers.size()) return false;
|
||||
|
||||
auto serverConfig = ServerConfig::createServerConfig(servers.at(defaultServerIndex).toObject());
|
||||
if (!serverConfig->containerConfigs.contains(serverConfig->defaultContainer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto &containerConfig = serverConfig->containerConfigs[serverConfig->defaultContainer];
|
||||
return checkSplitTunnelingInContainer(containerConfig, serverConfig->defaultContainer);
|
||||
}
|
||||
|
||||
bool ConfigController::checkSplitTunnelingInContainer(const ContainerConfig &containerConfig, const QString &defaultContainer) const
|
||||
{
|
||||
const DockerContainer containerType = ContainerProps::containerFromString(defaultContainer);
|
||||
|
||||
auto isWireguardHasSplit = [](const QString &nativeConfig, const QStringList &allowedIps) -> bool {
|
||||
if (nativeConfig.contains("AllowedIPs") && !nativeConfig.contains("AllowedIPs = 0.0.0.0/0, ::/0")) {
|
||||
return true;
|
||||
}
|
||||
if (!allowedIps.isEmpty() && !allowedIps.contains("0.0.0.0/0")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (containerType == DockerContainer::Awg || containerType == DockerContainer::WireGuard) {
|
||||
const auto protocolConfig = containerConfig.protocolConfigs.value(defaultContainer);
|
||||
if (!protocolConfig) return false;
|
||||
auto variant = ProtocolConfig::getProtocolConfigVariant(protocolConfig);
|
||||
return std::visit(
|
||||
[&](const auto &ptr) -> bool {
|
||||
using T = std::decay_t<decltype(ptr)>;
|
||||
if constexpr (std::is_same_v<T, QSharedPointer<AwgProtocolConfig>> || std::is_same_v<T, QSharedPointer<WireGuardProtocolConfig>>) {
|
||||
return isWireguardHasSplit(ptr->clientProtocolConfig.nativeConfig,
|
||||
ptr->clientProtocolConfig.wireGuardData.allowedIps);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
variant);
|
||||
}
|
||||
|
||||
if (containerType == DockerContainer::Cloak || containerType == DockerContainer::OpenVpn || containerType == DockerContainer::ShadowSocks) {
|
||||
const auto &protocolConfig = containerConfig.protocolConfigs.value(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
|
||||
if (!protocolConfig) return false;
|
||||
auto variant = ProtocolConfig::getProtocolConfigVariant(protocolConfig);
|
||||
return std::visit(
|
||||
[&](const auto &ptr) -> bool {
|
||||
using T = std::decay_t<decltype(ptr)>;
|
||||
if constexpr (std::is_same_v<T, QSharedPointer<OpenVpnProtocolConfig>> ||
|
||||
std::is_same_v<T, QSharedPointer<ShadowsocksProtocolConfig>> ||
|
||||
std::is_same_v<T, QSharedPointer<CloakProtocolConfig>>) {
|
||||
const auto nativeConfig = ptr->clientProtocolConfig.nativeConfig;
|
||||
return (!nativeConfig.isEmpty() && !nativeConfig.contains("redirect-gateway"));
|
||||
}
|
||||
return false;
|
||||
},
|
||||
variant);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -40,12 +40,17 @@ public:
|
||||
QStringList getAllInstalledServicesName(int serverIndex) const;
|
||||
void clearCachedProfile(int serverIndex, DockerContainer container);
|
||||
|
||||
// Split tunneling detection
|
||||
bool isDefaultServerDefaultContainerHasSplitTunneling() const;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
|
||||
// Protected helper methods for derived classes
|
||||
void updateServerInSettings(const QSharedPointer<ServerConfig> &serverConfig, int serverIndex);
|
||||
|
||||
bool checkSplitTunnelingInContainer(const ContainerConfig &containerConfig, const QString &defaultContainer) const;
|
||||
|
||||
signals:
|
||||
// Common server management signals
|
||||
void serverAdded(int serverIndex);
|
||||
|
||||
88
client/core/controllers/connectionController.cpp
Normal file
88
client/core/controllers/connectionController.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "connectionController.h"
|
||||
|
||||
#include <QtConcurrent>
|
||||
|
||||
#include "core/controllers/vpnConfigurationController.h"
|
||||
#include "core/controllers/selfhosted/serverController.h"
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "core/models/containers/containerConfig.h"
|
||||
#include "settings.h"
|
||||
#include "logger.h"
|
||||
#include "utilities.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
Logger logger("ConnectionController");
|
||||
}
|
||||
|
||||
ConnectionController::ConnectionController(const QSharedPointer<VpnConnection> &vpnConnection,
|
||||
std::shared_ptr<Settings> settings,
|
||||
QObject *parent)
|
||||
: QObject(parent), m_vpnConnection(vpnConnection), m_settings(settings)
|
||||
{
|
||||
}
|
||||
|
||||
QFuture<QJsonObject> ConnectionController::prepareVpnConfiguration(const QSharedPointer<ServerConfig> &serverConfig,
|
||||
DockerContainer container,
|
||||
const QPair<QString, QString> &dns) const
|
||||
{
|
||||
return QtConcurrent::run([this, serverConfig, container, dns]() -> QJsonObject {
|
||||
logger.info() << "Preparing VPN configuration for container" << ContainerProps::containerToString(container);
|
||||
|
||||
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
|
||||
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
|
||||
|
||||
QString containerName = ContainerProps::containerToString(container);
|
||||
const ContainerConfig &containerConfig = serverConfig->containerConfigs.value(containerName);
|
||||
|
||||
auto vpnConfiguration = vpnConfigurationController.createVpnConfiguration(dns,
|
||||
serverConfig,
|
||||
containerConfig,
|
||||
container);
|
||||
|
||||
emit configurationPrepared(vpnConfiguration);
|
||||
return vpnConfiguration;
|
||||
});
|
||||
}
|
||||
|
||||
QFuture<ErrorCode> ConnectionController::openConnection(const int serverIndex,
|
||||
const QSharedPointer<ServerConfig> &serverConfig,
|
||||
const DockerContainer container,
|
||||
const ServerCredentials &credentials,
|
||||
const QPair<QString, QString> &dns)
|
||||
{
|
||||
return QtConcurrent::run([this, serverIndex, serverConfig, container, credentials, dns]() -> ErrorCode {
|
||||
if (!isServerSupported(container)) {
|
||||
emit connectionError(ErrorCode::NotSupportedOnThisPlatform);
|
||||
return ErrorCode::NotSupportedOnThisPlatform;
|
||||
}
|
||||
|
||||
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
|
||||
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
|
||||
|
||||
const QString containerName = ContainerProps::containerToString(container);
|
||||
const ContainerConfig &containerConfig = serverConfig->containerConfigs.value(containerName);
|
||||
auto vpnConfiguration = vpnConfigurationController.createVpnConfiguration(dns, serverConfig, containerConfig, container);
|
||||
emit connectionProgress(QString("Connecting to %1...").arg(ContainerProps::containerToString(container)));
|
||||
|
||||
QMetaObject::invokeMethod(m_vpnConnection.get(), "connectToVpn", Qt::QueuedConnection,
|
||||
Q_ARG(int, serverIndex),
|
||||
Q_ARG(ServerCredentials, credentials),
|
||||
Q_ARG(DockerContainer, container),
|
||||
Q_ARG(QJsonObject, vpnConfiguration));
|
||||
return ErrorCode::NoError;
|
||||
});
|
||||
}
|
||||
|
||||
QFuture<ErrorCode> ConnectionController::closeConnection()
|
||||
{
|
||||
return QtConcurrent::run([this]() -> ErrorCode {
|
||||
QMetaObject::invokeMethod(m_vpnConnection.get(), "disconnectFromVpn", Qt::QueuedConnection);
|
||||
return ErrorCode::NoError;
|
||||
});
|
||||
}
|
||||
|
||||
bool ConnectionController::isServerSupported(DockerContainer container) const
|
||||
{
|
||||
return ContainerProps::isSupportedByCurrentPlatform(container);
|
||||
}
|
||||
55
client/core/controllers/connectionController.h
Normal file
55
client/core/controllers/connectionController.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef CONNECTIONCONTROLLER_H
|
||||
#define CONNECTIONCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QFuture>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "core/models/servers/serverConfig.h"
|
||||
#include "protocols/vpnprotocol.h"
|
||||
#include "vpnconnection.h"
|
||||
|
||||
class Settings;
|
||||
class ServerController;
|
||||
class VpnConfigurationsController;
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
class ConnectionController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConnectionController(const QSharedPointer<VpnConnection> &vpnConnection,
|
||||
std::shared_ptr<Settings> settings,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
QFuture<QJsonObject> prepareVpnConfiguration(const QSharedPointer<ServerConfig> &serverConfig,
|
||||
DockerContainer container,
|
||||
const QPair<QString, QString> &dns) const;
|
||||
|
||||
QFuture<ErrorCode> openConnection(const int serverIndex,
|
||||
const QSharedPointer<ServerConfig> &serverConfig,
|
||||
const DockerContainer container,
|
||||
const ServerCredentials &credentials,
|
||||
const QPair<QString, QString> &dns);
|
||||
|
||||
QFuture<ErrorCode> closeConnection();
|
||||
|
||||
signals:
|
||||
void configurationPrepared(const QJsonObject &vpnConfiguration);
|
||||
void connectionEstablished();
|
||||
void connectionTerminated();
|
||||
void connectionError(ErrorCode errorCode);
|
||||
void connectionProgress(const QString &message);
|
||||
|
||||
private:
|
||||
bool isServerSupported(DockerContainer container) const;
|
||||
|
||||
QSharedPointer<VpnConnection> m_vpnConnection;
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
};
|
||||
|
||||
#endif // CONNECTIONCONTROLLER_H
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <QDirIterator>
|
||||
#include <QTranslator>
|
||||
|
||||
#include "core/models/clientInfo.h"
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
#include "core/installedAppsImageProvider.h"
|
||||
#include "platforms/android/android_controller.h"
|
||||
@@ -123,8 +125,9 @@ void CoreController::initCoreControllers()
|
||||
|
||||
void CoreController::initUIControllers()
|
||||
{
|
||||
auto coreConnectionController = QSharedPointer<ConnectionController>::create(m_vpnConnection, m_settings, this);
|
||||
m_connectionController.reset(
|
||||
new ConnectionController(m_serversModel, m_containersModel, m_clientManagementModel, m_vpnConnection, m_settings));
|
||||
new ConnectionUIController(m_serversModel, m_containersModel, m_clientManagementModel, coreConnectionController, m_settings));
|
||||
m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get());
|
||||
|
||||
m_pageController.reset(new PageController(m_serversModel, m_settings));
|
||||
@@ -141,7 +144,7 @@ void CoreController::initUIControllers()
|
||||
m_engine->rootContext()->setContextProperty("InstallController", m_installUIController.get());
|
||||
|
||||
connect(m_installUIController.get(), &InstallUIController::currentContainerUpdated, m_connectionController.get(),
|
||||
&ConnectionController::onCurrentContainerUpdated);
|
||||
&ConnectionUIController::onCurrentContainerUpdated);
|
||||
|
||||
m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings));
|
||||
m_engine->rootContext()->setContextProperty("ImportController", m_importController.get());
|
||||
@@ -182,22 +185,22 @@ void CoreController::setupControllerSignalConnections()
|
||||
connect(m_exportController.data(), &ExportController::clientAppendRequested,
|
||||
clientManagementController.data(),
|
||||
[clientManagementController](const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig, const QString &clientName,
|
||||
const ContainerConfig &containerConfig, const QString &clientName,
|
||||
const QSharedPointer<ServerController> &serverController) {
|
||||
QJsonArray clientsTable;
|
||||
QList<ClientInfo> clientsList;
|
||||
ErrorCode result = clientManagementController->appendClient(container, credentials, containerConfig,
|
||||
clientName, serverController, clientsTable);
|
||||
clientName, serverController, clientsList);
|
||||
emit clientManagementController->clientAppendCompleted(result);
|
||||
});
|
||||
|
||||
connect(m_exportController.data(), &ExportController::nativeConfigClientAppendRequested,
|
||||
clientManagementController.data(),
|
||||
[clientManagementController](const QJsonObject &jsonNativeConfig, const QString &clientName,
|
||||
[clientManagementController](const QSharedPointer<ProtocolConfig> &protocolConfig, const QString &clientName,
|
||||
const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController) {
|
||||
QJsonArray clientsTable;
|
||||
ErrorCode result = clientManagementController->appendClient(jsonNativeConfig, clientName, container,
|
||||
credentials, serverController, clientsTable);
|
||||
QList<ClientInfo> clientsList;
|
||||
ErrorCode result = clientManagementController->appendClient(protocolConfig, clientName, container,
|
||||
credentials, serverController, clientsList);
|
||||
emit clientManagementController->nativeConfigClientAppendCompleted(result);
|
||||
});
|
||||
|
||||
@@ -210,11 +213,11 @@ void CoreController::setupControllerSignalConnections()
|
||||
connect(m_installController.data(), &InstallController::clientAppendRequested,
|
||||
clientManagementController.data(),
|
||||
[clientManagementController](const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig, const QString &clientName,
|
||||
const ContainerConfig &containerConfig, const QString &clientName,
|
||||
const QSharedPointer<ServerController> &serverController) {
|
||||
QJsonArray clientsTable;
|
||||
QList<ClientInfo> clientsList;
|
||||
clientManagementController->appendClient(container, credentials, containerConfig,
|
||||
clientName, serverController, clientsTable);
|
||||
clientName, serverController, clientsList);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -303,9 +306,9 @@ void CoreController::initNotificationHandler()
|
||||
|
||||
connect(m_notificationHandler.get(), &NotificationHandler::raiseRequested, m_pageController.get(), &PageController::raiseMainWindow);
|
||||
connect(m_notificationHandler.get(), &NotificationHandler::connectRequested, m_connectionController.get(),
|
||||
static_cast<void (ConnectionController::*)()>(&ConnectionController::openConnection));
|
||||
static_cast<void (ConnectionUIController::*)()>(&ConnectionUIController::openConnection));
|
||||
connect(m_notificationHandler.get(), &NotificationHandler::disconnectRequested, m_connectionController.get(),
|
||||
&ConnectionController::closeConnection);
|
||||
&ConnectionUIController::closeConnection);
|
||||
connect(this, &CoreController::translationsUpdated, m_notificationHandler.get(), &NotificationHandler::onTranslationsUpdated);
|
||||
#endif
|
||||
}
|
||||
@@ -347,7 +350,7 @@ void CoreController::updateTranslator(const QLocale &locale)
|
||||
|
||||
void CoreController::initErrorMessagesHandler()
|
||||
{
|
||||
connect(m_connectionController.get(), &ConnectionController::connectionErrorOccurred, this, [this](ErrorCode errorCode) {
|
||||
connect(m_connectionController.get(), &ConnectionUIController::connectionErrorOccurred, this, [this](ErrorCode errorCode) {
|
||||
emit m_pageController->showErrorMessage(errorCode);
|
||||
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
|
||||
});
|
||||
@@ -395,7 +398,7 @@ void CoreController::initTranslationsUpdatedHandler()
|
||||
{
|
||||
connect(m_languageModel.get(), &LanguageModel::updateTranslations, this, &CoreController::updateTranslator);
|
||||
connect(this, &CoreController::translationsUpdated, m_languageModel.get(), &LanguageModel::translationsUpdated);
|
||||
connect(this, &CoreController::translationsUpdated, m_connectionController.get(), &ConnectionController::onTranslationsUpdated);
|
||||
connect(this, &CoreController::translationsUpdated, m_connectionController.get(), &ConnectionUIController::onTranslationsUpdated);
|
||||
}
|
||||
|
||||
void CoreController::initAutoConnectHandler()
|
||||
@@ -412,7 +415,7 @@ void CoreController::initAmneziaDnsToggledHandler()
|
||||
|
||||
void CoreController::initPrepareConfigHandler()
|
||||
{
|
||||
connect(m_connectionController.get(), &ConnectionController::prepareConfig, this, [this]() {
|
||||
connect(m_connectionController.get(), &ConnectionUIController::prepareConfig, this, [this]() {
|
||||
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Preparing);
|
||||
|
||||
if (!m_apiConfigsController->isConfigValid()) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "core/controllers/selfhosted/clientManagementController.h"
|
||||
#include "ui/controllers/appSplitUIController.h"
|
||||
#include "ui/controllers/allowedDnsUIController.h"
|
||||
#include "ui/controllers/connectionController.h"
|
||||
#include "ui/controllers/connectionUIController.h"
|
||||
#include "core/controllers/selfhosted/exportController.h"
|
||||
#include "core/controllers/selfhosted/installController.h"
|
||||
#include "ui/controllers/selfhosted/exportUIController.h"
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "ui/controllers/systemController.h"
|
||||
#include "core/controllers/settingsController.h"
|
||||
#include "core/controllers/dnsController.h"
|
||||
#include "core/controllers/connectionController.h"
|
||||
#include "core/controllers/splitTunnelingController.h"
|
||||
|
||||
#include "ui/models/allowed_dns_model.h"
|
||||
@@ -107,7 +108,7 @@ private:
|
||||
|
||||
QMetaObject::Connection m_reloadConfigErrorOccurredConnection;
|
||||
|
||||
QScopedPointer<ConnectionController> m_connectionController;
|
||||
QScopedPointer<ConnectionUIController> m_connectionController;
|
||||
QScopedPointer<FocusController> m_focusController;
|
||||
QSharedPointer<PageController> m_pageController;
|
||||
QSharedPointer<ExportController> m_exportController;
|
||||
|
||||
@@ -4,6 +4,16 @@
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core/controllers/selfhosted/serverController.h"
|
||||
#include "core/models/protocols/openvpnProtocolConfig.h"
|
||||
#include "core/models/protocols/wireguardProtocolConfig.h"
|
||||
#include "core/models/protocols/awgProtocolConfig.h"
|
||||
#include "core/models/protocols/xrayProtocolConfig.h"
|
||||
#include "core/models/protocols/shadowsocksProtocolConfig.h"
|
||||
#include "core/models/protocols/cloakProtocolConfig.h"
|
||||
#include "core/models/protocols/ikev2ProtocolConfig.h"
|
||||
#include "core/models/protocols/protocolConfig.h"
|
||||
#include "core/models/clientInfo.h"
|
||||
#include <variant>
|
||||
#include "settings.h"
|
||||
#include "logger.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
@@ -45,43 +55,27 @@ QString ClientManagementController::getClientsTableFilePath(const DockerContaine
|
||||
return clientsTableFile;
|
||||
}
|
||||
|
||||
void ClientManagementController::migration(const QByteArray &clientsTableString, QJsonArray &clientsTable)
|
||||
void ClientManagementController::migration(const QByteArray &clientsTableString, QList<ClientInfo> &clientsList)
|
||||
{
|
||||
QJsonObject clientsTableObj = QJsonDocument::fromJson(clientsTableString).object();
|
||||
|
||||
for (auto &clientId : clientsTableObj.keys()) {
|
||||
QJsonObject client;
|
||||
client[configKey::clientId] = clientId;
|
||||
ClientInfo client;
|
||||
client.clientId = clientId;
|
||||
client.clientName = clientsTableObj.value(clientId).toObject().value(configKey::clientName).toString();
|
||||
client.creationDate = QDateTime::currentDateTime();
|
||||
|
||||
QJsonObject userData;
|
||||
userData[configKey::clientName] = clientsTableObj.value(clientId).toObject().value(configKey::clientName);
|
||||
client[configKey::userData] = userData;
|
||||
|
||||
clientsTable.push_back(client);
|
||||
clientsList.append(client);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientManagementController::isClientExists(const QString &clientId, const QJsonArray &clientsTable)
|
||||
{
|
||||
for (const auto &clientObject : clientsTable) {
|
||||
if (clientObject.toObject().value(configKey::clientId).toString() == clientId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ErrorCode ClientManagementController::updateClientsData(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController)
|
||||
const QSharedPointer<ServerController> &serverController, QList<ClientInfo> &clientsList)
|
||||
{
|
||||
QJsonArray clientsTable;
|
||||
return updateClientsData(container, credentials, serverController, clientsTable);
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::updateClientsData(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, QJsonArray &clientsTable)
|
||||
{
|
||||
clientsTable = QJsonArray();
|
||||
clientsList.clear();
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
QString clientsTableFile = getClientsTableFilePath(container);
|
||||
@@ -91,26 +85,37 @@ ErrorCode ClientManagementController::updateClientsData(const DockerContainer co
|
||||
return error;
|
||||
}
|
||||
|
||||
clientsTable = QJsonDocument::fromJson(clientsTableString).array();
|
||||
QJsonArray clientsTable = QJsonDocument::fromJson(clientsTableString).array();
|
||||
|
||||
if (clientsTable.isEmpty()) {
|
||||
migration(clientsTableString, clientsTable);
|
||||
const QByteArray newClientsTableString = QJsonDocument(clientsTable).toJson();
|
||||
migration(clientsTableString, clientsList);
|
||||
const QByteArray newClientsTableString = QJsonDocument(clientsToJsonArray(clientsList)).toJson();
|
||||
error = serverController->uploadTextFileToContainer(container, credentials, newClientsTableString, clientsTableFile);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to upload the clientsTable file to the server";
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
clientsList = clientsFromJsonArray(clientsTable);
|
||||
}
|
||||
|
||||
|
||||
int count = 0;
|
||||
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
|
||||
error = getOpenVpnClients(container, credentials, serverController, count, clientsTable);
|
||||
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
error = getWireGuardClients(container, credentials, serverController, count, clientsTable);
|
||||
} else if (container == DockerContainer::Xray) {
|
||||
error = getXrayClients(container, credentials, serverController, count, clientsTable);
|
||||
switch (container) {
|
||||
case DockerContainer::OpenVpn:
|
||||
case DockerContainer::ShadowSocks:
|
||||
case DockerContainer::Cloak:
|
||||
error = getOpenVpnClients(container, credentials, serverController, count, clientsList);
|
||||
break;
|
||||
case DockerContainer::WireGuard:
|
||||
case DockerContainer::Awg:
|
||||
error = getWireGuardClients(container, credentials, serverController, count, clientsList);
|
||||
break;
|
||||
case DockerContainer::Xray:
|
||||
error = getXrayClients(container, credentials, serverController, count, clientsList);
|
||||
break;
|
||||
default:
|
||||
error = ErrorCode::NoError;
|
||||
break;
|
||||
}
|
||||
|
||||
if (error != ErrorCode::NoError) {
|
||||
@@ -118,7 +123,7 @@ ErrorCode ClientManagementController::updateClientsData(const DockerContainer co
|
||||
return error;
|
||||
}
|
||||
|
||||
emit clientsDataUpdated(clientsTable);
|
||||
emit clientsDataUpdated(clientsList);
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
@@ -126,8 +131,8 @@ ErrorCode ClientManagementController::updateClientsData(const DockerContainer co
|
||||
ErrorCode ClientManagementController::updateClientsData(const DockerContainer container, const ServerCredentials &credentials)
|
||||
{
|
||||
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
|
||||
QJsonArray clientsTable;
|
||||
return updateClientsData(container, credentials, serverController, clientsTable);
|
||||
QList<ClientInfo> clientsList;
|
||||
return updateClientsData(container, credentials, serverController, clientsList);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,8 +140,8 @@ ErrorCode ClientManagementController::updateClientsData(const DockerContainer co
|
||||
|
||||
|
||||
ErrorCode ClientManagementController::appendClient(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig, const QString &clientName,
|
||||
const QSharedPointer<ServerController> &serverController, QJsonArray &clientsTable)
|
||||
const ContainerConfig &containerConfig, const QString &clientName,
|
||||
const QSharedPointer<ServerController> &serverController, QList<ClientInfo> &clientsList)
|
||||
{
|
||||
Proto protocol;
|
||||
switch (container) {
|
||||
@@ -154,22 +159,27 @@ ErrorCode ClientManagementController::appendClient(const DockerContainer contain
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig);
|
||||
return appendClient(protocolConfig, clientName, container, credentials, serverController, clientsTable);
|
||||
QString protocolName = ProtocolProps::protoToString(protocol);
|
||||
auto protocolConfig = containerConfig.protocolConfigs.value(protocolName);
|
||||
return appendClient(protocolConfig, clientName, container, credentials, serverController, clientsList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ErrorCode ClientManagementController::appendClient(QJsonObject &protocolConfig, const QString &clientName, const DockerContainer container,
|
||||
ErrorCode ClientManagementController::appendClient(QSharedPointer<ProtocolConfig> &protocolConfig, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable)
|
||||
QList<ClientInfo> &clientsList)
|
||||
{
|
||||
QString clientId;
|
||||
if (container == DockerContainer::Xray) {
|
||||
if (!protocolConfig.contains("outbounds")) {
|
||||
if (!protocolConfig) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray outbounds = protocolConfig.value("outbounds").toArray();
|
||||
QJsonObject protocolConfigJson = protocolConfig->toJson();
|
||||
if (!protocolConfigJson.contains("outbounds")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray outbounds = protocolConfigJson.value("outbounds").toArray();
|
||||
if (outbounds.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
@@ -199,45 +209,43 @@ ErrorCode ClientManagementController::appendClient(QJsonObject &protocolConfig,
|
||||
}
|
||||
clientId = user["id"].toString();
|
||||
} else {
|
||||
clientId = protocolConfig.value(config_key::clientId).toString();
|
||||
if (!protocolConfig) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
ProtocolConfigVariant variant = ProtocolConfig::getProtocolConfigVariant(protocolConfig);
|
||||
std::visit([&clientId](const auto &config) -> void {
|
||||
clientId = config->clientProtocolConfig.clientId;
|
||||
}, variant);
|
||||
}
|
||||
|
||||
return appendClient(clientId, clientName, container, credentials, serverController, clientsTable);
|
||||
return appendClient(clientId, clientName, container, credentials, serverController, clientsList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ErrorCode ClientManagementController::appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable)
|
||||
QList<ClientInfo> &clientsList)
|
||||
{
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
|
||||
error = updateClientsData(container, credentials, serverController, clientsTable);
|
||||
QList<ClientInfo> currentClients;
|
||||
error = updateClientsData(container, credentials, serverController, currentClients);
|
||||
if (error != ErrorCode::NoError) {
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < clientsTable.size(); i++) {
|
||||
if (clientsTable.at(i).toObject().value(configKey::clientId) == clientId) {
|
||||
return renameClient(i, clientName, container, credentials, serverController, clientsTable, true);
|
||||
for (int i = 0; i < currentClients.size(); ++i) {
|
||||
if (currentClients[i].clientId == clientId) {
|
||||
return renameClient(i, clientName, container, credentials, serverController, currentClients, true);
|
||||
}
|
||||
}
|
||||
|
||||
ClientInfo newClient(clientId, clientName);
|
||||
newClient.container = container;
|
||||
currentClients.append(newClient);
|
||||
|
||||
QJsonObject client;
|
||||
client[configKey::clientId] = clientId;
|
||||
|
||||
QJsonObject userData;
|
||||
userData[configKey::clientName] = clientName;
|
||||
userData[configKey::creationDate] = QDateTime::currentDateTime().toString();
|
||||
client[configKey::userData] = userData;
|
||||
clientsTable.push_back(client);
|
||||
|
||||
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsTable).toJson();
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsToJsonArray(currentClients)).toJson();
|
||||
QString clientsTableFile = getClientsTableFilePath(container);
|
||||
|
||||
error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||
@@ -246,6 +254,7 @@ ErrorCode ClientManagementController::appendClient(const QString &clientId, cons
|
||||
return error;
|
||||
}
|
||||
|
||||
clientsList = currentClients;
|
||||
emit clientAdded(clientId, clientName);
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
@@ -254,33 +263,28 @@ ErrorCode ClientManagementController::renameClient(const int row, const QString
|
||||
const ServerCredentials &credentials, bool addTimeStamp)
|
||||
{
|
||||
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
|
||||
QJsonArray clientsTable;
|
||||
ErrorCode errorCode = updateClientsData(container, credentials, serverController, clientsTable);
|
||||
QList<ClientInfo> clientsList;
|
||||
ErrorCode errorCode = updateClientsData(container, credentials, serverController, clientsList);
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
return errorCode;
|
||||
}
|
||||
return renameClient(row, clientName, container, credentials, serverController, clientsTable, addTimeStamp);
|
||||
return renameClient(row, clientName, container, credentials, serverController, clientsList, addTimeStamp);
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::renameClient(const int row, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable, bool addTimeStamp)
|
||||
QList<ClientInfo> &clientsList, bool addTimeStamp)
|
||||
{
|
||||
if (row < 0 || row >= clientsTable.size()) {
|
||||
if (row < 0 || row >= clientsList.size()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
auto client = clientsTable.at(row).toObject();
|
||||
auto userData = client[configKey::userData].toObject();
|
||||
userData[configKey::clientName] = clientName;
|
||||
clientsList[row].clientName = clientName;
|
||||
if (addTimeStamp) {
|
||||
userData[configKey::creationDate] = QDateTime::currentDateTime().toString();
|
||||
clientsList[row].creationDate = QDateTime::currentDateTime();
|
||||
}
|
||||
client[configKey::userData] = userData;
|
||||
|
||||
clientsTable.replace(row, client);
|
||||
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsTable).toJson();
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsToJsonArray(clientsList)).toJson();
|
||||
QString clientsTableFile = getClientsTableFilePath(container);
|
||||
|
||||
ErrorCode error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||
@@ -293,39 +297,10 @@ ErrorCode ClientManagementController::renameClient(const int row, const QString
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::renameClient(const int row, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable, bool addTimeStamp)
|
||||
{
|
||||
if (row < 0 || row >= clientsTable.size()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
auto client = clientsTable.at(row).toObject();
|
||||
auto userData = client[configKey::userData].toObject();
|
||||
userData[configKey::clientName] = clientName;
|
||||
if (addTimeStamp) {
|
||||
userData[configKey::creationDate] = QDateTime::currentDateTime().toString();
|
||||
}
|
||||
client[configKey::userData] = userData;
|
||||
|
||||
clientsTable.replace(row, client);
|
||||
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsTable).toJson();
|
||||
QString clientsTableFile = getClientsTableFilePath(container);
|
||||
|
||||
ErrorCode error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to upload the clientsTable file to the server";
|
||||
return error;
|
||||
}
|
||||
|
||||
emit clientRenamed(row, clientName);
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
|
||||
ErrorCode ClientManagementController::getWireGuardClients(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QJsonArray &clientsTable)
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QList<ClientInfo> &clientsList)
|
||||
{
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
@@ -346,15 +321,10 @@ ErrorCode ClientManagementController::getWireGuardClients(const DockerContainer
|
||||
}
|
||||
|
||||
for (auto &wireguardKey : wireguardKeys) {
|
||||
if (!isClientExists(wireguardKey, clientsTable)) {
|
||||
QJsonObject client;
|
||||
client[configKey::clientId] = wireguardKey;
|
||||
|
||||
QJsonObject userData;
|
||||
userData[configKey::clientName] = QString("Client %1").arg(count);
|
||||
client[configKey::userData] = userData;
|
||||
|
||||
clientsTable.push_back(client);
|
||||
if (!isClientExists(wireguardKey, clientsList)) {
|
||||
ClientInfo client(wireguardKey, QString("Client %1").arg(count));
|
||||
client.container = container;
|
||||
clientsList.append(client);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -362,7 +332,7 @@ ErrorCode ClientManagementController::getWireGuardClients(const DockerContainer
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::getXrayClients(const DockerContainer container, const ServerCredentials& credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QJsonArray &clientsTable)
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QList<ClientInfo> &clientsList)
|
||||
{
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
@@ -408,15 +378,10 @@ ErrorCode ClientManagementController::getXrayClients(const DockerContainer conta
|
||||
QString xrayDefaultUuid = serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::uuidPath, error);
|
||||
xrayDefaultUuid.replace("\n", "");
|
||||
|
||||
if (!isClientExists(clientId, clientsTable) && clientId != xrayDefaultUuid) {
|
||||
QJsonObject client;
|
||||
client[configKey::clientId] = clientId;
|
||||
|
||||
QJsonObject userData;
|
||||
userData[configKey::clientName] = QString("Client %1").arg(count);
|
||||
client[configKey::userData] = userData;
|
||||
|
||||
clientsTable.push_back(client);
|
||||
if (!isClientExists(clientId, clientsList) && clientId != xrayDefaultUuid) {
|
||||
ClientInfo client(clientId, QString("Client %1").arg(count));
|
||||
client.container = container;
|
||||
clientsList.append(client);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -424,6 +389,16 @@ ErrorCode ClientManagementController::getXrayClients(const DockerContainer conta
|
||||
return error;
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::getOpenVpnClients(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QList<ClientInfo> &clientsList)
|
||||
{
|
||||
Q_UNUSED(container);
|
||||
Q_UNUSED(credentials);
|
||||
Q_UNUSED(serverController);
|
||||
count = clientsList.size();
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::wgShow(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, std::vector<WgShowData> &data)
|
||||
{
|
||||
@@ -497,22 +472,34 @@ ErrorCode ClientManagementController::wgShow(const DockerContainer container, co
|
||||
ErrorCode ClientManagementController::revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const int serverIndex, const QSharedPointer<ServerController> &serverController)
|
||||
{
|
||||
QJsonArray clientsTable;
|
||||
return revokeOpenVpn(row, container, credentials, serverIndex, serverController, clientsTable);
|
||||
QList<ClientInfo> clientsList;
|
||||
ErrorCode errorCode = updateClientsData(container, credentials, serverController, clientsList);
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
return errorCode;
|
||||
}
|
||||
return revokeOpenVpn(row, container, credentials, serverIndex, serverController, clientsList);
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController)
|
||||
{
|
||||
QJsonArray clientsTable;
|
||||
return revokeWireGuard(row, container, credentials, serverController, clientsTable);
|
||||
QList<ClientInfo> clientsList;
|
||||
ErrorCode errorCode = updateClientsData(container, credentials, serverController, clientsList);
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
return errorCode;
|
||||
}
|
||||
return revokeWireGuard(row, container, credentials, serverController, clientsList);
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::revokeXray(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController)
|
||||
{
|
||||
QJsonArray clientsTable;
|
||||
return revokeXray(row, container, credentials, serverController, clientsTable);
|
||||
QList<ClientInfo> clientsList;
|
||||
ErrorCode errorCode = updateClientsData(container, credentials, serverController, clientsList);
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
return errorCode;
|
||||
}
|
||||
return revokeXray(row, container, credentials, serverController, clientsList);
|
||||
}
|
||||
|
||||
|
||||
@@ -520,25 +507,24 @@ ErrorCode ClientManagementController::revokeClient(const int row, const DockerCo
|
||||
const ServerCredentials &credentials, const int serverIndex)
|
||||
{
|
||||
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
|
||||
QJsonArray clientsTable;
|
||||
ErrorCode errorCode = updateClientsData(container, credentials, serverController, clientsTable);
|
||||
QList<ClientInfo> clientsList;
|
||||
ErrorCode errorCode = updateClientsData(container, credentials, serverController, clientsList);
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
return errorCode;
|
||||
}
|
||||
return revokeClient(row, container, credentials, serverIndex, serverController, clientsTable);
|
||||
return revokeClient(row, container, credentials, serverIndex, serverController, clientsList);
|
||||
}
|
||||
|
||||
|
||||
ErrorCode ClientManagementController::revokeClient(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const int serverIndex, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable)
|
||||
QList<ClientInfo> &clientsList)
|
||||
{
|
||||
if (row < 0 || row >= clientsTable.size()) {
|
||||
if (row < 0 || row >= clientsList.size()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
auto client = clientsTable.at(row).toObject();
|
||||
QString clientId = client.value(configKey::clientId).toString();
|
||||
QString clientId = clientsList[row].clientId;
|
||||
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
|
||||
@@ -546,16 +532,16 @@ ErrorCode ClientManagementController::revokeClient(const int row, const DockerCo
|
||||
case DockerContainer::OpenVpn:
|
||||
case DockerContainer::ShadowSocks:
|
||||
case DockerContainer::Cloak: {
|
||||
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController, clientsTable);
|
||||
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController, clientsList);
|
||||
break;
|
||||
}
|
||||
case DockerContainer::WireGuard:
|
||||
case DockerContainer::Awg: {
|
||||
errorCode = revokeWireGuard(row, container, credentials, serverController, clientsTable);
|
||||
errorCode = revokeWireGuard(row, container, credentials, serverController, clientsList);
|
||||
break;
|
||||
}
|
||||
case DockerContainer::Xray: {
|
||||
errorCode = revokeXray(row, container, credentials, serverController, clientsTable);
|
||||
errorCode = revokeXray(row, container, credentials, serverController, clientsList);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -571,9 +557,9 @@ ErrorCode ClientManagementController::revokeClient(const int row, const DockerCo
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::revokeClient(const QJsonObject &containerConfig, const DockerContainer container,
|
||||
ErrorCode ClientManagementController::revokeClient(const ContainerConfig &containerConfig, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const int serverIndex,
|
||||
const QSharedPointer<ServerController> &serverController, QJsonArray &clientsTable)
|
||||
const QSharedPointer<ServerController> &serverController, QList<ClientInfo> &clientsList)
|
||||
{
|
||||
|
||||
Proto protocol;
|
||||
@@ -601,11 +587,14 @@ ErrorCode ClientManagementController::revokeClient(const QJsonObject &containerC
|
||||
|
||||
QString clientId;
|
||||
if (container == DockerContainer::Xray) {
|
||||
|
||||
if (!protocolConfig.contains("outbounds")) {
|
||||
if (!protocolConfig) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray outbounds = protocolConfig.value("outbounds").toArray();
|
||||
QJsonObject protocolConfigJson = protocolConfig->toJson();
|
||||
if (!protocolConfigJson.contains("outbounds")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray outbounds = protocolConfigJson.value("outbounds").toArray();
|
||||
if (outbounds.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
@@ -635,14 +624,19 @@ ErrorCode ClientManagementController::revokeClient(const QJsonObject &containerC
|
||||
}
|
||||
clientId = user["id"].toString();
|
||||
} else {
|
||||
clientId = protocolConfig.value(config_key::clientId).toString();
|
||||
if (!protocolConfig) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
ProtocolConfigVariant variant = ProtocolConfig::getProtocolConfigVariant(protocolConfig);
|
||||
std::visit([&clientId](const auto &config) -> void {
|
||||
clientId = config->clientProtocolConfig.clientId;
|
||||
}, variant);
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < clientsTable.size(); i++) {
|
||||
auto client = clientsTable.at(i).toObject();
|
||||
if (client.value(configKey::clientId).toString() == clientId) {
|
||||
return revokeClient(i, container, credentials, serverIndex, serverController, clientsTable);
|
||||
for (int i = 0; i < clientsList.size(); i++) {
|
||||
if (clientsList[i].clientId == clientId) {
|
||||
return revokeClient(i, container, credentials, serverIndex, serverController, clientsList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,14 +645,12 @@ ErrorCode ClientManagementController::revokeClient(const QJsonObject &containerC
|
||||
|
||||
ErrorCode ClientManagementController::revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const int serverIndex, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable)
|
||||
QList<ClientInfo> &clientsList)
|
||||
{
|
||||
if (row < 0 || row >= clientsTable.size()) {
|
||||
if (row < 0 || row >= clientsList.size()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
auto client = clientsTable.at(row).toObject();
|
||||
QString clientId = client.value(configKey::clientId).toString();
|
||||
QString clientId = clientsList[row].clientId;
|
||||
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
QString stdOut;
|
||||
@@ -674,9 +666,8 @@ ErrorCode ClientManagementController::revokeOpenVpn(const int row, const DockerC
|
||||
return error;
|
||||
}
|
||||
|
||||
clientsTable.removeAt(row);
|
||||
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsTable).toJson();
|
||||
clientsList.removeAt(row);
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsToJsonArray(clientsList)).toJson();
|
||||
QString clientsTableFile = getClientsTableFilePath(container);
|
||||
|
||||
error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||
@@ -689,14 +680,12 @@ ErrorCode ClientManagementController::revokeOpenVpn(const int row, const DockerC
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, QJsonArray &clientsTable)
|
||||
const QSharedPointer<ServerController> &serverController, QList<ClientInfo> &clientsList)
|
||||
{
|
||||
if (row < 0 || row >= clientsTable.size()) {
|
||||
if (row < 0 || row >= clientsList.size()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
auto client = clientsTable.at(row).toObject();
|
||||
QString clientId = client.value(configKey::clientId).toString();
|
||||
QString clientId = clientsList[row].clientId;
|
||||
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
@@ -729,9 +718,8 @@ ErrorCode ClientManagementController::revokeWireGuard(const int row, const Docke
|
||||
return error;
|
||||
}
|
||||
|
||||
clientsTable.removeAt(row);
|
||||
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsTable).toJson();
|
||||
clientsList.removeAt(row);
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsToJsonArray(clientsList)).toJson();
|
||||
QString clientsTableFile = getClientsTableFilePath(container);
|
||||
|
||||
error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||
@@ -744,14 +732,12 @@ ErrorCode ClientManagementController::revokeWireGuard(const int row, const Docke
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementController::revokeXray(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, QJsonArray &clientsTable)
|
||||
const QSharedPointer<ServerController> &serverController, QList<ClientInfo> &clientsList)
|
||||
{
|
||||
if (row < 0 || row >= clientsTable.size()) {
|
||||
if (row < 0 || row >= clientsList.size()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
auto client = clientsTable.at(row).toObject();
|
||||
QString clientId = client.value(configKey::clientId).toString();
|
||||
QString clientId = clientsList[row].clientId;
|
||||
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
@@ -794,9 +780,8 @@ ErrorCode ClientManagementController::revokeXray(const int row, const DockerCont
|
||||
return error;
|
||||
}
|
||||
|
||||
clientsTable.removeAt(row);
|
||||
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsTable).toJson();
|
||||
clientsList.removeAt(row);
|
||||
const QByteArray clientsTableString = QJsonDocument(clientsToJsonArray(clientsList)).toJson();
|
||||
QString clientsTableFile = getClientsTableFilePath(container);
|
||||
|
||||
error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||
@@ -806,5 +791,32 @@ ErrorCode ClientManagementController::revokeXray(const int row, const DockerCont
|
||||
}
|
||||
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
QList<ClientInfo> ClientManagementController::clientsFromJsonArray(const QJsonArray &jsonArray)
|
||||
{
|
||||
QList<ClientInfo> clientsList;
|
||||
for (const auto &value : jsonArray) {
|
||||
clientsList.append(ClientInfo(value.toObject()));
|
||||
}
|
||||
return clientsList;
|
||||
}
|
||||
|
||||
QJsonArray ClientManagementController::clientsToJsonArray(const QList<ClientInfo> &clientsList)
|
||||
{
|
||||
QJsonArray jsonArray;
|
||||
for (const auto &client : clientsList) {
|
||||
jsonArray.append(client.toJson());
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
bool ClientManagementController::isClientExists(const QString &clientId, const QList<ClientInfo> &clientsList)
|
||||
{
|
||||
for (const auto &client : clientsList) {
|
||||
if (client.clientId == clientId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
#include <QSharedPointer>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QList>
|
||||
#include <vector>
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "core/models/containers/containerConfig.h"
|
||||
#include "core/models/protocols/protocolConfig.h"
|
||||
#include "core/models/clientInfo.h"
|
||||
|
||||
class ServerController;
|
||||
class Settings;
|
||||
@@ -42,33 +46,33 @@ public:
|
||||
ErrorCode revokeClient(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const int serverIndex);
|
||||
|
||||
// Internal methods (with clientsTable parameter for core operations)
|
||||
// Core methods using ClientInfo model
|
||||
ErrorCode updateClientsData(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, QJsonArray &clientsTable);
|
||||
const QSharedPointer<ServerController> &serverController, QList<ClientInfo> &clientsList);
|
||||
|
||||
ErrorCode appendClient(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig, const QString &clientName,
|
||||
const QSharedPointer<ServerController> &serverController, QJsonArray &clientsTable);
|
||||
const ContainerConfig &containerConfig, const QString &clientName,
|
||||
const QSharedPointer<ServerController> &serverController, QList<ClientInfo> &clientsList);
|
||||
|
||||
ErrorCode appendClient(QJsonObject &protocolConfig, const QString &clientName, const DockerContainer container,
|
||||
ErrorCode appendClient(QSharedPointer<ProtocolConfig> &protocolConfig, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable);
|
||||
QList<ClientInfo> &clientsList);
|
||||
|
||||
ErrorCode appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable);
|
||||
QList<ClientInfo> &clientsList);
|
||||
|
||||
ErrorCode renameClient(const int row, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable, bool addTimeStamp = false);
|
||||
QList<ClientInfo> &clientsList, bool addTimeStamp = false);
|
||||
|
||||
ErrorCode revokeClient(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const int serverIndex, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable);
|
||||
QList<ClientInfo> &clientsList);
|
||||
|
||||
ErrorCode revokeClient(const QJsonObject &containerConfig, const DockerContainer container,
|
||||
ErrorCode revokeClient(const ContainerConfig &containerConfig, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const int serverIndex,
|
||||
const QSharedPointer<ServerController> &serverController, QJsonArray &clientsTable);
|
||||
const QSharedPointer<ServerController> &serverController, QList<ClientInfo> &clientsList);
|
||||
|
||||
// WireGuard specific operations
|
||||
ErrorCode wgShow(const DockerContainer container, const ServerCredentials &credentials,
|
||||
@@ -76,7 +80,7 @@ public:
|
||||
|
||||
signals:
|
||||
void adminConfigRevoked(const DockerContainer container);
|
||||
void clientsDataUpdated(const QJsonArray &clientsTable);
|
||||
void clientsDataUpdated(const QList<ClientInfo> &clientsList);
|
||||
void clientAdded(const QString &clientId, const QString &clientName);
|
||||
void clientRenamed(const int row, const QString &newName);
|
||||
void clientRevoked(const int row);
|
||||
@@ -87,29 +91,33 @@ signals:
|
||||
private:
|
||||
// Protocol-specific client management
|
||||
ErrorCode getOpenVpnClients(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QJsonArray &clientsTable);
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QList<ClientInfo> &clientsList);
|
||||
|
||||
ErrorCode getWireGuardClients(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QJsonArray &clientsTable);
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QList<ClientInfo> &clientsList);
|
||||
|
||||
ErrorCode getXrayClients(const DockerContainer container, const ServerCredentials& credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QJsonArray &clientsTable);
|
||||
const QSharedPointer<ServerController> &serverController, int &count, QList<ClientInfo> &clientsList);
|
||||
|
||||
// Protocol-specific client revocation
|
||||
ErrorCode revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const int serverIndex, const QSharedPointer<ServerController> &serverController,
|
||||
QJsonArray &clientsTable);
|
||||
QList<ClientInfo> &clientsList);
|
||||
|
||||
ErrorCode revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, QJsonArray &clientsTable);
|
||||
const QSharedPointer<ServerController> &serverController, QList<ClientInfo> &clientsList);
|
||||
|
||||
ErrorCode revokeXray(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, QJsonArray &clientsTable);
|
||||
const QSharedPointer<ServerController> &serverController, QList<ClientInfo> &clientsList);
|
||||
|
||||
// Helper methods
|
||||
bool isClientExists(const QString &clientId, const QJsonArray &clientsTable);
|
||||
void migration(const QByteArray &clientsTableString, QJsonArray &clientsTable);
|
||||
bool isClientExists(const QString &clientId, const QList<ClientInfo> &clientsList);
|
||||
void migration(const QByteArray &clientsTableString, QList<ClientInfo> &clientsList);
|
||||
QString getClientsTableFilePath(const DockerContainer container);
|
||||
|
||||
// JSON serialization for persistence only
|
||||
static QList<ClientInfo> clientsFromJsonArray(const QJsonArray &jsonArray);
|
||||
static QJsonArray clientsToJsonArray(const QList<ClientInfo> &clientsList);
|
||||
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
};
|
||||
|
||||
@@ -22,29 +22,22 @@ ExportController::ExportController(std::shared_ptr<Settings> settings,
|
||||
{
|
||||
}
|
||||
|
||||
ExportConfigResult ExportController::generateFullAccessConfig(const QJsonObject &serverConfig)
|
||||
ExportConfigResult ExportController::generateFullAccessConfig(const QSharedPointer<ServerConfig> &serverConfig)
|
||||
{
|
||||
ExportConfigResult result;
|
||||
result.errorCode = ErrorCode::NoError;
|
||||
|
||||
QJsonObject modifiedServerConfig = serverConfig;
|
||||
QJsonArray containers = modifiedServerConfig.value(config_key::containers).toArray();
|
||||
// Create a copy of the ServerConfig and clean last_config from protocol configs
|
||||
auto modifiedServerConfig = QSharedPointer<ServerConfig>::create(*serverConfig);
|
||||
|
||||
for (auto i = 0; i < containers.size(); i++) {
|
||||
auto containerConfig = containers.at(i).toObject();
|
||||
auto containerType = ContainerProps::containerFromString(containerConfig.value(config_key::container).toString());
|
||||
|
||||
for (auto protocol : ContainerProps::protocolsForContainer(containerType)) {
|
||||
auto protocolConfig = containerConfig.value(ProtocolProps::protoToString(protocol)).toObject();
|
||||
protocolConfig.remove(config_key::last_config);
|
||||
containerConfig[ProtocolProps::protoToString(protocol)] = protocolConfig;
|
||||
for (auto &containerConfig : modifiedServerConfig->containerConfigs) {
|
||||
for (auto &protocolConfig : containerConfig.protocolConfigs) {
|
||||
// Protocol configs will automatically exclude last_config when serialized to JSON for export
|
||||
// No need to manually remove it here as the toJson() method handles this
|
||||
}
|
||||
|
||||
containers.replace(i, containerConfig);
|
||||
}
|
||||
modifiedServerConfig[config_key::containers] = containers;
|
||||
|
||||
QByteArray compressedConfig = QJsonDocument(modifiedServerConfig).toJson();
|
||||
QByteArray compressedConfig = QJsonDocument(modifiedServerConfig->toJson()).toJson();
|
||||
compressedConfig = qCompress(compressedConfig, 8);
|
||||
result.config = QString("vpn://%1").arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)));
|
||||
result.qrCodes = generateQrCodeSeries(compressedConfig);
|
||||
@@ -55,8 +48,8 @@ ExportConfigResult ExportController::generateFullAccessConfig(const QJsonObject
|
||||
ExportConfigResult ExportController::generateConnectionConfig(const QString &clientName,
|
||||
const ServerCredentials &credentials,
|
||||
const DockerContainer container,
|
||||
const QJsonObject &containerConfig,
|
||||
const QJsonObject &serverConfig,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QSharedPointer<ServerConfig> &serverConfig,
|
||||
const QPair<QString, QString> &dnsSettings)
|
||||
{
|
||||
ExportConfigResult result;
|
||||
@@ -64,8 +57,8 @@ ExportConfigResult ExportController::generateConnectionConfig(const QString &cli
|
||||
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
|
||||
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
|
||||
|
||||
QJsonObject modifiedContainerConfig = containerConfig;
|
||||
modifiedContainerConfig.insert(config_key::container, ContainerProps::containerToString(container));
|
||||
// Use the provided ContainerConfig directly
|
||||
ContainerConfig modifiedContainerConfig = containerConfig;
|
||||
|
||||
result.errorCode = vpnConfigurationController.createProtocolConfigForContainer(credentials, container, modifiedContainerConfig);
|
||||
if (result.errorCode != ErrorCode::NoError) {
|
||||
@@ -92,16 +85,20 @@ ExportConfigResult ExportController::generateConnectionConfig(const QString &cli
|
||||
return result;
|
||||
}
|
||||
|
||||
QJsonObject modifiedServerConfig = serverConfig;
|
||||
modifiedServerConfig.remove(config_key::userName);
|
||||
modifiedServerConfig.remove(config_key::password);
|
||||
modifiedServerConfig.remove(config_key::port);
|
||||
modifiedServerConfig.insert(config_key::containers, QJsonArray { modifiedContainerConfig });
|
||||
modifiedServerConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||
modifiedServerConfig.insert(config_key::dns1, dnsSettings.first);
|
||||
modifiedServerConfig.insert(config_key::dns2, dnsSettings.second);
|
||||
// Create a modified ServerConfig for export with only the specific container
|
||||
auto exportServerConfig = QSharedPointer<ServerConfig>::create(*serverConfig);
|
||||
|
||||
// Remove credentials (they are not needed in export)
|
||||
exportServerConfig->containerConfigs.clear();
|
||||
|
||||
// Add only the specific container being exported
|
||||
QString containerName = ContainerProps::containerToString(container);
|
||||
exportServerConfig->containerConfigs.insert(containerName, modifiedContainerConfig);
|
||||
exportServerConfig->defaultContainer = containerName;
|
||||
exportServerConfig->dns1 = dnsSettings.first;
|
||||
exportServerConfig->dns2 = dnsSettings.second;
|
||||
|
||||
QByteArray compressedConfig = QJsonDocument(modifiedServerConfig).toJson();
|
||||
QByteArray compressedConfig = QJsonDocument(exportServerConfig->toJson()).toJson();
|
||||
compressedConfig = qCompress(compressedConfig, 8);
|
||||
result.config = QString("vpn://%1").arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)));
|
||||
result.qrCodes = generateQrCodeSeries(compressedConfig);
|
||||
@@ -110,11 +107,11 @@ ExportConfigResult ExportController::generateConnectionConfig(const QString &cli
|
||||
}
|
||||
|
||||
ExportConfigResult ExportController::generateOpenVpnConfig(const QString &clientName,
|
||||
const ServerCredentials &credentials,
|
||||
const DockerContainer container,
|
||||
const QJsonObject &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
const ServerCredentials &credentials,
|
||||
const DockerContainer container,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
{
|
||||
ExportConfigResult result;
|
||||
QJsonObject nativeConfig;
|
||||
@@ -144,7 +141,7 @@ ExportConfigResult ExportController::generateOpenVpnConfig(const QString &client
|
||||
|
||||
ExportConfigResult ExportController::generateWireGuardConfig(const QString &clientName,
|
||||
const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
{
|
||||
@@ -168,10 +165,10 @@ ExportConfigResult ExportController::generateWireGuardConfig(const QString &clie
|
||||
}
|
||||
|
||||
ExportConfigResult ExportController::generateAwgConfig(const QString &clientName,
|
||||
const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
const ServerCredentials &credentials,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
{
|
||||
ExportConfigResult result;
|
||||
QJsonObject nativeConfig;
|
||||
@@ -193,10 +190,10 @@ ExportConfigResult ExportController::generateAwgConfig(const QString &clientName
|
||||
}
|
||||
|
||||
ExportConfigResult ExportController::generateShadowSocksConfig(const ServerCredentials &credentials,
|
||||
const DockerContainer container,
|
||||
const QJsonObject &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
const DockerContainer container,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
{
|
||||
ExportConfigResult result;
|
||||
QJsonObject nativeConfig;
|
||||
@@ -233,9 +230,9 @@ ExportConfigResult ExportController::generateShadowSocksConfig(const ServerCrede
|
||||
}
|
||||
|
||||
ExportConfigResult ExportController::generateCloakConfig(const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
{
|
||||
ExportConfigResult result;
|
||||
QJsonObject nativeConfig;
|
||||
@@ -259,10 +256,10 @@ ExportConfigResult ExportController::generateCloakConfig(const ServerCredentials
|
||||
}
|
||||
|
||||
ExportConfigResult ExportController::generateXrayConfig(const QString &clientName,
|
||||
const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
const ServerCredentials &credentials,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig)
|
||||
{
|
||||
ExportConfigResult result;
|
||||
QJsonObject nativeConfig;
|
||||
@@ -284,16 +281,16 @@ ExportConfigResult ExportController::generateXrayConfig(const QString &clientNam
|
||||
|
||||
|
||||
|
||||
ErrorCode ExportController::generateNativeConfig(const DockerContainer container, const QString &clientName,
|
||||
ErrorCode ExportController::generateNativeConfig(const DockerContainer container, const QString &clientName,
|
||||
const Proto &protocol, const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig, const QPair<QString, QString> &dnsSettings,
|
||||
const ContainerConfig &containerConfig, const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig, QJsonObject &jsonNativeConfig,
|
||||
const QSharedPointer<ServerController> &serverController)
|
||||
{
|
||||
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
|
||||
|
||||
QJsonObject modifiedContainerConfig = containerConfig;
|
||||
modifiedContainerConfig.insert(config_key::container, ContainerProps::containerToString(container));
|
||||
// Use the provided ContainerConfig directly
|
||||
ContainerConfig modifiedContainerConfig = containerConfig;
|
||||
|
||||
QString protocolConfigString;
|
||||
ErrorCode errorCode = vpnConfigurationController.createProtocolConfigString(isApiConfig, dnsSettings, credentials,
|
||||
@@ -306,8 +303,11 @@ ErrorCode ExportController::generateNativeConfig(const DockerContainer container
|
||||
jsonNativeConfig = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
||||
|
||||
if (protocol == Proto::OpenVpn || protocol == Proto::WireGuard || protocol == Proto::Awg || protocol == Proto::Xray) {
|
||||
QString protocolName = ProtocolProps::protoToString(protocol);
|
||||
auto protocolConfig = modifiedContainerConfig.protocolConfigs.value(protocolName);
|
||||
|
||||
m_waitingForNativeConfigAppend = true;
|
||||
emit nativeConfigClientAppendRequested(jsonNativeConfig, clientName, container, credentials, serverController);
|
||||
emit nativeConfigClientAppendRequested(protocolConfig, clientName, container, credentials, serverController);
|
||||
|
||||
QEventLoop loop;
|
||||
QTimer timer;
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "core/models/containers/containerConfig.h"
|
||||
#include "core/models/protocols/protocolConfig.h"
|
||||
#include "core/models/servers/serverConfig.h"
|
||||
|
||||
class ServerController;
|
||||
class Settings;
|
||||
@@ -34,10 +37,10 @@ public:
|
||||
|
||||
signals:
|
||||
void clientAppendRequested(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig, const QString &clientName,
|
||||
const ContainerConfig &containerConfig, const QString &clientName,
|
||||
const QSharedPointer<ServerController> &serverController);
|
||||
|
||||
void nativeConfigClientAppendRequested(const QJsonObject &jsonNativeConfig, const QString &clientName,
|
||||
void nativeConfigClientAppendRequested(const QSharedPointer<ProtocolConfig> &protocolConfig, const QString &clientName,
|
||||
const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController);
|
||||
|
||||
@@ -48,55 +51,55 @@ public slots:
|
||||
void onClientAppendCompleted(ErrorCode errorCode);
|
||||
void onNativeConfigClientAppendCompleted(ErrorCode errorCode);
|
||||
|
||||
ExportConfigResult generateFullAccessConfig(const QJsonObject &serverConfig);
|
||||
ExportConfigResult generateFullAccessConfig(const QSharedPointer<ServerConfig> &serverConfig);
|
||||
|
||||
ExportConfigResult generateConnectionConfig(const QString &clientName,
|
||||
const ServerCredentials &credentials,
|
||||
const DockerContainer container,
|
||||
const QJsonObject &containerConfig,
|
||||
const QJsonObject &serverConfig,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QSharedPointer<ServerConfig> &serverConfig,
|
||||
const QPair<QString, QString> &dnsSettings);
|
||||
|
||||
ExportConfigResult generateOpenVpnConfig(const QString &clientName,
|
||||
const ServerCredentials &credentials,
|
||||
const DockerContainer container,
|
||||
const QJsonObject &containerConfig,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig = false);
|
||||
|
||||
ExportConfigResult generateWireGuardConfig(const QString &clientName,
|
||||
const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig = false);
|
||||
|
||||
ExportConfigResult generateAwgConfig(const QString &clientName,
|
||||
const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig = false);
|
||||
|
||||
ExportConfigResult generateShadowSocksConfig(const ServerCredentials &credentials,
|
||||
const DockerContainer container,
|
||||
const QJsonObject &containerConfig,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig = false);
|
||||
|
||||
ExportConfigResult generateCloakConfig(const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig = false);
|
||||
|
||||
ExportConfigResult generateXrayConfig(const QString &clientName,
|
||||
const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig,
|
||||
const ContainerConfig &containerConfig,
|
||||
const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig = false);
|
||||
|
||||
private:
|
||||
ErrorCode generateNativeConfig(const DockerContainer container, const QString &clientName,
|
||||
const Proto &protocol, const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig, const QPair<QString, QString> &dnsSettings,
|
||||
const ContainerConfig &containerConfig, const QPair<QString, QString> &dnsSettings,
|
||||
bool isApiConfig, QJsonObject &jsonNativeConfig,
|
||||
const QSharedPointer<ServerController> &serverController);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "core/controllers/vpnConfigurationController.h"
|
||||
#include "core/models/servers/selfHostedServerConfig.h"
|
||||
#include "core/models/protocols/awgProtocolConfig.h"
|
||||
#include "core/networkUtilities.h"
|
||||
#include "logger.h"
|
||||
#include "utilities.h"
|
||||
@@ -40,21 +41,21 @@ InstallResult InstallController::installContainer(DockerContainer container, int
|
||||
|
||||
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
|
||||
|
||||
QJsonObject containerConfig = generateContainerConfig(container, port, transportProto);
|
||||
ContainerConfig containerConfig = generateContainerConfig(container, port, transportProto);
|
||||
|
||||
if (shouldCreateServer && isServerAlreadyExists(serverCredentials)) {
|
||||
result.errorCode = ErrorCode::InternalError;
|
||||
return result;
|
||||
}
|
||||
|
||||
QMap<DockerContainer, QJsonObject> installedContainers;
|
||||
QMap<DockerContainer, ContainerConfig> installedContainers;
|
||||
ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, serverController, installedContainers);
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
result.errorCode = errorCode;
|
||||
return result;
|
||||
}
|
||||
|
||||
QJsonObject serverConfig;
|
||||
QSharedPointer<ServerConfig> serverConfig;
|
||||
if (shouldCreateServer) {
|
||||
errorCode = installServer(container, installedContainers, serverCredentials,
|
||||
serverController, result.message, serverConfig);
|
||||
@@ -84,7 +85,7 @@ InstallResult InstallController::scanServerForInstalledContainers(const ServerCr
|
||||
result.isInstalledContainerFound = false;
|
||||
result.isServiceInstall = false;
|
||||
|
||||
QMap<DockerContainer, QJsonObject> installedContainers;
|
||||
QMap<DockerContainer, ContainerConfig> installedContainers;
|
||||
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
|
||||
result.errorCode = getAlreadyInstalledContainers(serverCredentials, serverController, installedContainers);
|
||||
|
||||
@@ -93,7 +94,7 @@ InstallResult InstallController::scanServerForInstalledContainers(const ServerCr
|
||||
|
||||
for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
|
||||
auto container = iterator.key();
|
||||
QJsonObject containerConfig = iterator.value();
|
||||
ContainerConfig containerConfig = iterator.value();
|
||||
|
||||
if (ContainerProps::isSupportedByCurrentPlatform(container)) {
|
||||
result.errorCode = vpnConfigurationController.createProtocolConfigForContainer(serverCredentials, container, containerConfig);
|
||||
@@ -115,7 +116,7 @@ InstallResult InstallController::scanServerForInstalledContainers(const ServerCr
|
||||
|
||||
ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController,
|
||||
QMap<DockerContainer, QJsonObject> &installedContainers)
|
||||
QMap<DockerContainer, ContainerConfig> &installedContainers)
|
||||
{
|
||||
QString stdOut;
|
||||
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
||||
@@ -148,18 +149,58 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
|
||||
|
||||
DockerContainer container = ContainerProps::containerFromString(containerName);
|
||||
if (container != DockerContainer::None) {
|
||||
QJsonObject containerConfigObject;
|
||||
containerConfigObject.insert(config_key::container, ContainerProps::containerToString(container));
|
||||
ContainerConfig containerConfig;
|
||||
containerConfig.containerName = ContainerProps::containerToString(container);
|
||||
|
||||
auto containerProto = ContainerProps::defaultProtocol(container);
|
||||
auto containerProtoString = ProtocolProps::protoToString(containerProto);
|
||||
|
||||
// Create appropriate protocol config based on container type
|
||||
QSharedPointer<ProtocolConfig> protocolConfig;
|
||||
|
||||
// Create a temporary QJsonObject to construct the protocol config
|
||||
QJsonObject protoConfigObject;
|
||||
protoConfigObject.insert(config_key::port, port);
|
||||
protoConfigObject.insert(config_key::transport_proto, transportProto);
|
||||
|
||||
containerConfigObject.insert(containerProtoString, protoConfigObject);
|
||||
installedContainers.insert(container, containerConfigObject);
|
||||
|
||||
// Create the appropriate protocol config based on type
|
||||
switch (containerProto) {
|
||||
case Proto::OpenVpn:
|
||||
protocolConfig = QSharedPointer<OpenVpnProtocolConfig>::create(protoConfigObject, containerProtoString);
|
||||
break;
|
||||
case Proto::WireGuard:
|
||||
protocolConfig = QSharedPointer<WireGuardProtocolConfig>::create(protoConfigObject, containerProtoString);
|
||||
break;
|
||||
case Proto::Awg:
|
||||
protocolConfig = QSharedPointer<AwgProtocolConfig>::create(protoConfigObject, containerProtoString);
|
||||
break;
|
||||
case Proto::Cloak:
|
||||
protocolConfig = QSharedPointer<CloakProtocolConfig>::create(protoConfigObject, containerProtoString);
|
||||
break;
|
||||
case Proto::ShadowSocks:
|
||||
protocolConfig = QSharedPointer<ShadowsocksProtocolConfig>::create(protoConfigObject, containerProtoString);
|
||||
break;
|
||||
case Proto::Xray:
|
||||
case Proto::SSXray:
|
||||
protocolConfig = QSharedPointer<XrayProtocolConfig>::create(protoConfigObject, containerProtoString);
|
||||
break;
|
||||
case Proto::Ikev2:
|
||||
protocolConfig = QSharedPointer<Ikev2ProtocolConfig>::create(protoConfigObject, containerProtoString);
|
||||
break;
|
||||
case Proto::Sftp:
|
||||
protocolConfig = QSharedPointer<SftpProtocolConfig>::create(protoConfigObject, containerProtoString);
|
||||
break;
|
||||
case Proto::Socks5Proxy:
|
||||
protocolConfig = QSharedPointer<Socks5ProtocolConfig>::create(protoConfigObject, containerProtoString);
|
||||
break;
|
||||
default:
|
||||
continue; // Skip unknown protocols
|
||||
}
|
||||
|
||||
if (protocolConfig) {
|
||||
containerConfig.protocolConfigs.insert(containerProtoString, protocolConfig);
|
||||
installedContainers.insert(container, containerConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,45 +208,45 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode InstallController::installServer(const DockerContainer container,
|
||||
const QMap<DockerContainer, QJsonObject> &installedContainers,
|
||||
const ServerCredentials &serverCredentials,
|
||||
const QSharedPointer<ServerController> &serverController,
|
||||
QString &finishMessage, QJsonObject &serverConfig)
|
||||
ErrorCode InstallController::installServer(const DockerContainer container,
|
||||
const QMap<DockerContainer, ContainerConfig> &installedContainers,
|
||||
const ServerCredentials &serverCredentials,
|
||||
const QSharedPointer<ServerController> &serverController,
|
||||
QString &finishMessage, QSharedPointer<ServerConfig> &serverConfig)
|
||||
{
|
||||
if (installedContainers.size() > 1) {
|
||||
finishMessage += tr("\nAdded containers that were already installed on the server");
|
||||
}
|
||||
|
||||
serverConfig.insert(config_key::hostName, serverCredentials.hostName);
|
||||
serverConfig.insert(config_key::userName, serverCredentials.userName);
|
||||
serverConfig.insert(config_key::password, serverCredentials.secretData);
|
||||
serverConfig.insert(config_key::port, serverCredentials.port);
|
||||
serverConfig.insert(config_key::description, m_settings->nextAvailableServerName());
|
||||
// Create a SelfHostedServerConfig and populate it properly
|
||||
serverConfig = QSharedPointer<SelfHostedServerConfig>::create(QJsonObject());
|
||||
auto selfHostedConfig = qSharedPointerCast<SelfHostedServerConfig>(serverConfig);
|
||||
|
||||
selfHostedConfig->hostName = serverCredentials.hostName;
|
||||
selfHostedConfig->serverCredentials = serverCredentials;
|
||||
selfHostedConfig->name = m_settings->nextAvailableServerName();
|
||||
selfHostedConfig->defaultContainer = ContainerProps::containerToString(container);
|
||||
selfHostedConfig->type = amnezia::ServerConfigType::SelfHosted;
|
||||
|
||||
QJsonArray containerConfigs;
|
||||
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
|
||||
|
||||
for (auto iterator = installedContainers.begin(); iterator != installedContainers.end(); iterator++) {
|
||||
auto containerConfig = iterator.value();
|
||||
QString containerName = ContainerProps::containerToString(iterator.key());
|
||||
|
||||
if (ContainerProps::isSupportedByCurrentPlatform(container)) {
|
||||
if (ContainerProps::isSupportedByCurrentPlatform(iterator.key())) {
|
||||
auto errorCode = vpnConfigurationController.createProtocolConfigForContainer(serverCredentials, iterator.key(),
|
||||
containerConfig);
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
return errorCode;
|
||||
}
|
||||
containerConfigs.append(containerConfig);
|
||||
} else {
|
||||
containerConfigs.append(containerConfig);
|
||||
}
|
||||
|
||||
selfHostedConfig->containerConfigs.insert(containerName, containerConfig);
|
||||
}
|
||||
|
||||
serverConfig.insert(config_key::containers, containerConfigs);
|
||||
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||
|
||||
int serverIndex = m_settings->nextAvailableServerIndex();
|
||||
m_settings->setServerConfig(serverIndex, serverConfig);
|
||||
m_settings->setServerConfig(serverIndex, serverConfig->toJson());
|
||||
m_settings->setDefaultServerIndex(serverIndex);
|
||||
|
||||
finishMessage = tr("Server '%1' was successfully added").arg(serverCredentials.hostName);
|
||||
@@ -213,7 +254,7 @@ ErrorCode InstallController::installServer(const DockerContainer container,
|
||||
}
|
||||
|
||||
ErrorCode InstallController::installContainer(const DockerContainer container,
|
||||
const QMap<DockerContainer, QJsonObject> &installedContainers,
|
||||
const QMap<DockerContainer, ContainerConfig> &installedContainers,
|
||||
const ServerCredentials &serverCredentials,
|
||||
const QSharedPointer<ServerController> &serverController,
|
||||
QString &finishMessage)
|
||||
@@ -263,71 +304,85 @@ bool InstallController::isServerAlreadyExists(const ServerCredentials &serverCre
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonObject InstallController::generateContainerConfig(const DockerContainer container, int port,
|
||||
const TransportProto transportProto)
|
||||
ContainerConfig InstallController::generateContainerConfig(const DockerContainer container, int port,
|
||||
const TransportProto transportProto)
|
||||
{
|
||||
QJsonObject config;
|
||||
ContainerConfig containerConfig;
|
||||
containerConfig.containerName = ContainerProps::containerToString(container);
|
||||
|
||||
auto mainProto = ContainerProps::defaultProtocol(container);
|
||||
for (auto protocol : ContainerProps::protocolsForContainer(container)) {
|
||||
QJsonObject containerConfig;
|
||||
|
||||
QSharedPointer<ProtocolConfig> protocolConfig;
|
||||
|
||||
if (protocol == mainProto) {
|
||||
containerConfig.insert(config_key::port, QString::number(port));
|
||||
containerConfig.insert(config_key::transport_proto, ProtocolProps::transportProtoToString(transportProto, protocol));
|
||||
|
||||
if (container == DockerContainer::Awg) {
|
||||
QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(2, 5));
|
||||
QString junkPacketMinSize = QString::number(10);
|
||||
QString junkPacketMaxSize = QString::number(50);
|
||||
|
||||
// Create the appropriate protocol config based on the protocol type
|
||||
if (protocol == Proto::Awg && container == DockerContainer::Awg) {
|
||||
// Use the VpnConfigurationsController to create proper AwgProtocolConfig
|
||||
// For now, create a basic protocol config and set values
|
||||
protocolConfig = QSharedPointer<AwgProtocolConfig>::create(QJsonObject(), ProtocolProps::protoToString(protocol));
|
||||
auto awgConfig = qSharedPointerCast<AwgProtocolConfig>(protocolConfig);
|
||||
|
||||
// Set server protocol config
|
||||
awgConfig->serverProtocolConfig.port = QString::number(port);
|
||||
awgConfig->serverProtocolConfig.transportProto = ProtocolProps::transportProtoToString(transportProto, protocol);
|
||||
|
||||
// Generate AWG-specific parameters
|
||||
awgConfig->serverProtocolConfig.junkPacketCount = QString::number(QRandomGenerator::global()->bounded(2, 5));
|
||||
awgConfig->serverProtocolConfig.junkPacketMinSize = QString::number(10);
|
||||
awgConfig->serverProtocolConfig.junkPacketMaxSize = QString::number(50);
|
||||
|
||||
int s1 = QRandomGenerator::global()->bounded(15, 150);
|
||||
int s2 = QRandomGenerator::global()->bounded(15, 150);
|
||||
|
||||
QSet<int> usedValues;
|
||||
usedValues.insert(s1);
|
||||
|
||||
while (usedValues.contains(s2) || s1 + AwgConstant::messageInitiationSize == s2 + AwgConstant::messageResponseSize) {
|
||||
s2 = QRandomGenerator::global()->bounded(15, 150);
|
||||
}
|
||||
usedValues.insert(s2);
|
||||
|
||||
QString initPacketJunkSize = QString::number(s1);
|
||||
QString responsePacketJunkSize = QString::number(s2);
|
||||
|
||||
|
||||
awgConfig->serverProtocolConfig.initPacketJunkSize = QString::number(s1);
|
||||
awgConfig->serverProtocolConfig.responsePacketJunkSize = QString::number(s2);
|
||||
|
||||
QSet<QString> headersValue;
|
||||
while (headersValue.size() != 4) {
|
||||
auto max = (std::numeric_limits<qint32>::max)();
|
||||
headersValue.insert(QString::number(QRandomGenerator::global()->bounded(5, max)));
|
||||
}
|
||||
|
||||
auto headersValueList = headersValue.values();
|
||||
|
||||
QString initPacketMagicHeader = headersValueList.at(0);
|
||||
QString responsePacketMagicHeader = headersValueList.at(1);
|
||||
QString underloadPacketMagicHeader = headersValueList.at(2);
|
||||
QString transportPacketMagicHeader = headersValueList.at(3);
|
||||
|
||||
containerConfig[config_key::junkPacketCount] = junkPacketCount;
|
||||
containerConfig[config_key::junkPacketMinSize] = junkPacketMinSize;
|
||||
containerConfig[config_key::junkPacketMaxSize] = junkPacketMaxSize;
|
||||
containerConfig[config_key::initPacketJunkSize] = initPacketJunkSize;
|
||||
containerConfig[config_key::responsePacketJunkSize] = responsePacketJunkSize;
|
||||
containerConfig[config_key::initPacketMagicHeader] = initPacketMagicHeader;
|
||||
containerConfig[config_key::responsePacketMagicHeader] = responsePacketMagicHeader;
|
||||
containerConfig[config_key::underloadPacketMagicHeader] = underloadPacketMagicHeader;
|
||||
containerConfig[config_key::transportPacketMagicHeader] = transportPacketMagicHeader;
|
||||
} else if (container == DockerContainer::Sftp) {
|
||||
containerConfig.insert(config_key::userName, protocols::sftp::defaultUserName);
|
||||
containerConfig.insert(config_key::password, Utils::getRandomString(16));
|
||||
} else if (container == DockerContainer::Socks5Proxy) {
|
||||
containerConfig.insert(config_key::userName, protocols::socks5Proxy::defaultUserName);
|
||||
containerConfig.insert(config_key::password, Utils::getRandomString(16));
|
||||
awgConfig->serverProtocolConfig.initPacketMagicHeader = headersValueList.at(0);
|
||||
awgConfig->serverProtocolConfig.responsePacketMagicHeader = headersValueList.at(1);
|
||||
awgConfig->serverProtocolConfig.underloadPacketMagicHeader = headersValueList.at(2);
|
||||
awgConfig->serverProtocolConfig.transportPacketMagicHeader = headersValueList.at(3);
|
||||
|
||||
} else {
|
||||
// For other protocols, create basic protocol configs
|
||||
// This will need to be expanded for each protocol type
|
||||
protocolConfig = QSharedPointer<ProtocolConfig>::create(QJsonObject(), ProtocolProps::protoToString(protocol));
|
||||
|
||||
// For now, store basic port and transport info as JSON until all protocol configs are properly structured
|
||||
QJsonObject tempConfig;
|
||||
tempConfig.insert(config_key::port, QString::number(port));
|
||||
tempConfig.insert(config_key::transport_proto, ProtocolProps::transportProtoToString(transportProto, protocol));
|
||||
|
||||
if (container == DockerContainer::Sftp) {
|
||||
tempConfig.insert(config_key::userName, protocols::sftp::defaultUserName);
|
||||
tempConfig.insert(config_key::password, Utils::getRandomString(16));
|
||||
} else if (container == DockerContainer::Socks5Proxy) {
|
||||
tempConfig.insert(config_key::userName, protocols::socks5Proxy::defaultUserName);
|
||||
tempConfig.insert(config_key::password, Utils::getRandomString(16));
|
||||
}
|
||||
|
||||
// Store this in the protocol config's internal JSON for now
|
||||
// TODO: Replace with proper protocol config structure
|
||||
protocolConfig = QSharedPointer<ProtocolConfig>::create(tempConfig, ProtocolProps::protoToString(protocol));
|
||||
}
|
||||
|
||||
config.insert(config_key::container, ContainerProps::containerToString(container));
|
||||
} else {
|
||||
// Non-main protocols get basic configs
|
||||
protocolConfig = QSharedPointer<ProtocolConfig>::create(QJsonObject(), ProtocolProps::protoToString(protocol));
|
||||
}
|
||||
config.insert(ProtocolProps::protoToString(protocol), containerConfig);
|
||||
|
||||
containerConfig.protocolConfigs.insert(ProtocolProps::protoToString(protocol), protocolConfig);
|
||||
}
|
||||
|
||||
return config;
|
||||
return containerConfig;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "core/models/containers/containerConfig.h"
|
||||
#include "core/models/servers/serverConfig.h"
|
||||
|
||||
class ServerController;
|
||||
class Settings;
|
||||
@@ -40,7 +42,7 @@ public:
|
||||
InstallResult scanServerForInstalledContainers(const ServerCredentials &serverCredentials);
|
||||
|
||||
InstallResult updateContainer(const DockerContainer container, const ServerCredentials &serverCredentials,
|
||||
const QJsonObject &containerConfig);
|
||||
const ContainerConfig &containerConfig);
|
||||
|
||||
// Server management operations
|
||||
ErrorCode removeProcessedServer(const ServerCredentials &serverCredentials);
|
||||
@@ -48,7 +50,7 @@ public:
|
||||
ErrorCode removeAllContainers(const ServerCredentials &serverCredentials);
|
||||
ErrorCode removeProcessedContainer(const DockerContainer container, const ServerCredentials &serverCredentials);
|
||||
|
||||
ErrorCode removeApiConfig(const QJsonObject &serverConfig);
|
||||
ErrorCode removeApiConfig(const QSharedPointer<ServerConfig> &serverConfig);
|
||||
ErrorCode clearCachedProfile(const ServerCredentials &serverCredentials);
|
||||
|
||||
// Utility methods
|
||||
@@ -61,7 +63,7 @@ public:
|
||||
|
||||
signals:
|
||||
void clientAppendRequested(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QJsonObject &containerConfig, const QString &clientName,
|
||||
const ContainerConfig &containerConfig, const QString &clientName,
|
||||
const QSharedPointer<ServerController> &serverController);
|
||||
|
||||
void containerInstalled(const InstallResult &result);
|
||||
@@ -81,23 +83,23 @@ signals:
|
||||
private:
|
||||
// Installation helpers
|
||||
ErrorCode installServer(const DockerContainer container,
|
||||
const QMap<DockerContainer, QJsonObject> &installedContainers,
|
||||
const QMap<DockerContainer, ContainerConfig> &installedContainers,
|
||||
const ServerCredentials &serverCredentials,
|
||||
const QSharedPointer<ServerController> &serverController,
|
||||
QString &finishMessage, QJsonObject &serverConfig);
|
||||
QString &finishMessage, QSharedPointer<ServerConfig> &serverConfig);
|
||||
|
||||
ErrorCode installContainer(const DockerContainer container,
|
||||
const QMap<DockerContainer, QJsonObject> &installedContainers,
|
||||
const QMap<DockerContainer, ContainerConfig> &installedContainers,
|
||||
const ServerCredentials &serverCredentials,
|
||||
const QSharedPointer<ServerController> &serverController,
|
||||
QString &finishMessage);
|
||||
|
||||
ErrorCode getAlreadyInstalledContainers(const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController,
|
||||
QMap<DockerContainer, QJsonObject> &installedContainers);
|
||||
QMap<DockerContainer, ContainerConfig> &installedContainers);
|
||||
|
||||
QJsonObject generateContainerConfig(const DockerContainer container, int port,
|
||||
const TransportProto transportProto);
|
||||
ContainerConfig generateContainerConfig(const DockerContainer container, int port,
|
||||
const TransportProto transportProto);
|
||||
|
||||
bool isServerAlreadyExists(const ServerCredentials &serverCredentials) const;
|
||||
|
||||
|
||||
@@ -22,22 +22,7 @@ SelfhostedConfigController::SelfhostedConfigController(std::shared_ptr<Settings>
|
||||
m_isAmneziaDnsEnabled = m_settings->useAmneziaDns();
|
||||
}
|
||||
|
||||
bool SelfhostedConfigController::isDefaultServerDefaultContainerHasSplitTunneling() const
|
||||
{
|
||||
int defaultServerIndex = m_settings->defaultServerIndex();
|
||||
auto servers = m_settings->serversArray();
|
||||
if (defaultServerIndex >= servers.size()) return false;
|
||||
|
||||
auto serverConfig = ServerConfig::createServerConfig(servers.at(defaultServerIndex).toObject());
|
||||
auto defaultContainer = ContainerProps::containerFromString(serverConfig->defaultContainer);
|
||||
|
||||
if (!serverConfig->containerConfigs.contains(serverConfig->defaultContainer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto &containerConfig = serverConfig->containerConfigs[serverConfig->defaultContainer];
|
||||
return checkSplitTunnelingInContainer(containerConfig, serverConfig->defaultContainer);
|
||||
}
|
||||
|
||||
|
||||
void SelfhostedConfigController::toggleAmneziaDns(bool enabled)
|
||||
{
|
||||
@@ -152,30 +137,4 @@ bool SelfhostedConfigController::isProtocolSupported(Proto protocol) const
|
||||
}
|
||||
}
|
||||
|
||||
bool SelfhostedConfigController::checkSplitTunnelingInContainer(const ContainerConfig &containerConfig,
|
||||
const QString &defaultContainer) const
|
||||
{
|
||||
for (const auto &protocol : containerConfig.protocolConfigs) {
|
||||
Proto protoType = ProtocolProps::protoFromString(protocol->protocolName);
|
||||
|
||||
switch (protoType) {
|
||||
case Proto::Awg: {
|
||||
auto awgConfig = protocol.dynamicCast<AwgProtocolConfig>();
|
||||
if (awgConfig && awgConfig->clientConfig.awgConfig.mtu != 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Proto::WireGuard: {
|
||||
auto wgConfig = protocol.dynamicCast<WireGuardProtocolConfig>();
|
||||
if (wgConfig && wgConfig->clientConfig.mtu != 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ public:
|
||||
explicit SelfhostedConfigController(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
||||
// Self-hosted specific functionality
|
||||
bool isDefaultServerDefaultContainerHasSplitTunneling() const;
|
||||
|
||||
// Amnezia DNS management
|
||||
void toggleAmneziaDns(bool enabled);
|
||||
|
||||
@@ -8,6 +8,15 @@
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#include "core/models/protocols/openvpnProtocolConfig.h"
|
||||
#include "core/models/protocols/wireguardProtocolConfig.h"
|
||||
#include "core/models/protocols/awgProtocolConfig.h"
|
||||
#include "core/models/protocols/xrayProtocolConfig.h"
|
||||
#include "core/models/protocols/shadowsocksProtocolConfig.h"
|
||||
#include "core/models/protocols/cloakProtocolConfig.h"
|
||||
#include "core/models/protocols/sftpProtocolConfig.h"
|
||||
#include "core/models/protocols/socks5ProtocolConfig.h"
|
||||
#include <QPointer>
|
||||
#include <QTemporaryFile>
|
||||
#include <QThread>
|
||||
@@ -247,7 +256,7 @@ ErrorCode ServerController::removeContainer(const ServerCredentials &credentials
|
||||
replaceVars(amnezia::scriptData(SharedScriptType::remove_container), generateVarsForContainer(credentials, container)));
|
||||
}
|
||||
|
||||
ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config, bool isUpdate)
|
||||
ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, DockerContainer container, ContainerConfig &config, bool isUpdate)
|
||||
{
|
||||
qDebug().noquote() << "ServerController::setupContainer" << ContainerProps::containerToString(container);
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
@@ -307,8 +316,8 @@ ErrorCode ServerController::setupContainer(const ServerCredentials &credentials,
|
||||
return startupContainerWorker(credentials, container, config);
|
||||
}
|
||||
|
||||
ErrorCode ServerController::updateContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &oldConfig,
|
||||
QJsonObject &newConfig)
|
||||
ErrorCode ServerController::updateContainer(const ServerCredentials &credentials, DockerContainer container, const ContainerConfig &oldConfig,
|
||||
ContainerConfig &newConfig)
|
||||
{
|
||||
bool reinstallRequired = isReinstallContainerRequired(container, oldConfig, newConfig);
|
||||
qDebug() << "ServerController::updateContainer for container" << container << "reinstall required is" << reinstallRequired;
|
||||
@@ -324,86 +333,20 @@ ErrorCode ServerController::updateContainer(const ServerCredentials &credentials
|
||||
}
|
||||
}
|
||||
|
||||
bool ServerController::isReinstallContainerRequired(DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig)
|
||||
bool ServerController::isReinstallContainerRequired(DockerContainer container, const ContainerConfig &oldConfig, const ContainerConfig &newConfig)
|
||||
{
|
||||
Proto mainProto = ContainerProps::defaultProtocol(container);
|
||||
const auto &mainProto = ContainerProps::defaultProtocol(container);
|
||||
const QString protocolName = ProtocolProps::protoToString(mainProto);
|
||||
|
||||
const QJsonObject &oldProtoConfig = oldConfig.value(ProtocolProps::protoToString(mainProto)).toObject();
|
||||
const QJsonObject &newProtoConfig = newConfig.value(ProtocolProps::protoToString(mainProto)).toObject();
|
||||
|
||||
if (container == DockerContainer::OpenVpn) {
|
||||
if (oldProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto)
|
||||
!= newProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto))
|
||||
return true;
|
||||
|
||||
if (oldProtoConfig.value(config_key::port).toString(protocols::openvpn::defaultPort)
|
||||
!= newProtoConfig.value(config_key::port).toString(protocols::openvpn::defaultPort))
|
||||
return true;
|
||||
const auto oldProtocolConfig = oldConfig.protocolConfigs.value(protocolName);
|
||||
const auto newProtocolConfig = newConfig.protocolConfigs.value(protocolName);
|
||||
|
||||
if (!oldProtocolConfig || !newProtocolConfig) {
|
||||
return true; // If either config is missing, reinstall is required
|
||||
}
|
||||
|
||||
if (container == DockerContainer::Cloak) {
|
||||
if (oldProtoConfig.value(config_key::port).toString(protocols::cloak::defaultPort)
|
||||
!= newProtoConfig.value(config_key::port).toString(protocols::cloak::defaultPort))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (container == DockerContainer::ShadowSocks) {
|
||||
if (oldProtoConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort)
|
||||
!= newProtoConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (container == DockerContainer::Awg) {
|
||||
if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
|
||||
!= newProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress))
|
||||
|| (oldProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort)
|
||||
!= newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort))
|
||||
|| (oldProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount)
|
||||
!= newProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount))
|
||||
|| (oldProtoConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize)
|
||||
!= newProtoConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize))
|
||||
|| (oldProtoConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize)
|
||||
!= newProtoConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize))
|
||||
|| (oldProtoConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize)
|
||||
!= newProtoConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize))
|
||||
|| (oldProtoConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize)
|
||||
!= newProtoConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize))
|
||||
|| (oldProtoConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader)
|
||||
!= newProtoConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader))
|
||||
|| (oldProtoConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader)
|
||||
!= newProtoConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader))
|
||||
|| (oldProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader)
|
||||
!= newProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader))
|
||||
|| (oldProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader))
|
||||
!= newProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader))
|
||||
// || (oldProtoConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize)
|
||||
// != newProtoConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize))
|
||||
// || (oldProtoConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize)
|
||||
// != newProtoConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize))
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (container == DockerContainer::WireGuard) {
|
||||
if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
|
||||
!= newProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress))
|
||||
|| (oldProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)
|
||||
!= newProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (container == DockerContainer::Socks5Proxy) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (container == DockerContainer::Xray) {
|
||||
if (oldProtoConfig.value(config_key::port).toString(protocols::xray::defaultPort)
|
||||
!= newProtoConfig.value(config_key::port).toString(protocols::xray::defaultPort)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
// Use the existing isServerSettingsEqual method from ProtocolConfig
|
||||
return !oldProtocolConfig->isServerSettingsEqual(newProtocolConfig);
|
||||
}
|
||||
|
||||
ErrorCode ServerController::installDockerWorker(const ServerCredentials &credentials, DockerContainer container)
|
||||
@@ -435,13 +378,13 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent
|
||||
return error;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
ErrorCode ServerController::prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const ContainerConfig &config)
|
||||
{
|
||||
// create folder on host
|
||||
return runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::prepare_host), generateVarsForContainer(credentials, container)));
|
||||
}
|
||||
|
||||
ErrorCode ServerController::buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
ErrorCode ServerController::buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const ContainerConfig &config)
|
||||
{
|
||||
QString dockerFilePath = amnezia::server::getDockerfileFolder(container) + "/Dockerfile";
|
||||
QString scriptString = QString("sudo rm %1").arg(dockerFilePath);
|
||||
@@ -479,7 +422,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
||||
return error;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
||||
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, ContainerConfig &config)
|
||||
{
|
||||
QString stdOut;
|
||||
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
||||
@@ -502,7 +445,7 @@ ErrorCode ServerController::runContainerWorker(const ServerCredentials &credenti
|
||||
return e;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
||||
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, ContainerConfig &config)
|
||||
{
|
||||
QString stdOut;
|
||||
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
||||
@@ -524,7 +467,7 @@ ErrorCode ServerController::configureContainerWorker(const ServerCredentials &cr
|
||||
return e;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
ErrorCode ServerController::startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const ContainerConfig &config)
|
||||
{
|
||||
QString script = amnezia::scriptData(ProtocolScriptType::container_startup, container);
|
||||
|
||||
@@ -546,7 +489,7 @@ ErrorCode ServerController::startupContainerWorker(const ServerCredentials &cred
|
||||
|
||||
|
||||
ServerController::Vars ServerController::generateVarsForContainer(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &config)
|
||||
const ContainerConfig &config)
|
||||
{
|
||||
// For VPN containers, use configurator pattern
|
||||
if (ContainerProps::containerService(container) != ServiceType::Other) {
|
||||
@@ -582,7 +525,9 @@ ServerController::Vars ServerController::generateVarsForContainer(const ServerCr
|
||||
}
|
||||
|
||||
if (configurator) {
|
||||
return configurator->generateProtocolVars(credentials, container, config);
|
||||
QString protocolName = ProtocolProps::protoToString(protocol);
|
||||
auto protocolConfig = config.protocolConfigs.value(protocolName);
|
||||
return configurator->generateProtocolVars(credentials, container, protocolConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -606,33 +551,37 @@ ServerController::Vars ServerController::generateVarsForContainer(const ServerCr
|
||||
|
||||
// Handle container-specific variables for non-VPN services
|
||||
if (container == DockerContainer::Sftp) {
|
||||
SftpProtocolConfig protocolConfig(config.value(ProtocolProps::protoToString(Proto::Sftp)).toObject(),
|
||||
ProtocolProps::protoToString(Proto::Sftp));
|
||||
QString protocolName = ProtocolProps::protoToString(Proto::Sftp);
|
||||
auto sftpConfig = qSharedPointerCast<SftpProtocolConfig>(config.protocolConfigs.value(protocolName));
|
||||
|
||||
QString port = protocolConfig.serverProtocolConfig.port;
|
||||
if (port.isEmpty()) {
|
||||
port = QString::number(ProtocolProps::defaultPort(Proto::Sftp));
|
||||
if (sftpConfig) {
|
||||
QString port = sftpConfig->serverProtocolConfig.port;
|
||||
if (port.isEmpty()) {
|
||||
port = QString::number(ProtocolProps::defaultPort(Proto::Sftp));
|
||||
}
|
||||
|
||||
vars.append({{"$SFTP_PORT", port}});
|
||||
vars.append({{"$SFTP_USER", sftpConfig->serverProtocolConfig.userName}});
|
||||
vars.append({{"$SFTP_PASSWORD", sftpConfig->serverProtocolConfig.password}});
|
||||
}
|
||||
|
||||
vars.append({{"$SFTP_PORT", port}});
|
||||
vars.append({{"$SFTP_USER", protocolConfig.serverProtocolConfig.userName}});
|
||||
vars.append({{"$SFTP_PASSWORD", protocolConfig.serverProtocolConfig.password}});
|
||||
} else if (container == DockerContainer::Socks5Proxy) {
|
||||
Socks5ProtocolConfig protocolConfig(config.value(ProtocolProps::protoToString(Proto::Socks5Proxy)).toObject(),
|
||||
ProtocolProps::protoToString(Proto::Socks5Proxy));
|
||||
QString protocolName = ProtocolProps::protoToString(Proto::Socks5Proxy);
|
||||
auto socks5Config = qSharedPointerCast<Socks5ProtocolConfig>(config.protocolConfigs.value(protocolName));
|
||||
|
||||
QString port = protocolConfig.serverProtocolConfig.port;
|
||||
if (port.isEmpty()) {
|
||||
port = protocols::socks5Proxy::defaultPort;
|
||||
if (socks5Config) {
|
||||
QString port = socks5Config->serverProtocolConfig.port;
|
||||
if (port.isEmpty()) {
|
||||
port = protocols::socks5Proxy::defaultPort;
|
||||
}
|
||||
|
||||
vars.append({{"$SOCKS5_PROXY_PORT", port}});
|
||||
|
||||
const QString &username = socks5Config->serverProtocolConfig.userName;
|
||||
const QString &password = socks5Config->serverProtocolConfig.password;
|
||||
QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : "";
|
||||
vars.append({{"$SOCKS5_USER", socks5user}});
|
||||
vars.append({{"$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong"}});
|
||||
}
|
||||
|
||||
vars.append({{"$SOCKS5_PROXY_PORT", port}});
|
||||
|
||||
const QString &username = protocolConfig.serverProtocolConfig.userName;
|
||||
const QString &password = protocolConfig.serverProtocolConfig.password;
|
||||
QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : "";
|
||||
vars.append({{"$SOCKS5_USER", socks5user}});
|
||||
vars.append({{"$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong"}});
|
||||
}
|
||||
|
||||
return vars;
|
||||
@@ -674,7 +623,7 @@ QString ServerController::replaceVars(const QString &script, const Vars &vars)
|
||||
return s;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credentials, DockerContainer container, const ContainerConfig &config)
|
||||
{
|
||||
if (container == DockerContainer::Dns) {
|
||||
return ErrorCode::NoError;
|
||||
@@ -691,15 +640,37 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential
|
||||
};
|
||||
|
||||
const Proto protocol = ContainerProps::defaultProtocol(container);
|
||||
const QString containerString = ProtocolProps::protoToString(protocol);
|
||||
const QJsonObject containerConfig = config.value(containerString).toObject();
|
||||
const QString protocolName = ProtocolProps::protoToString(protocol);
|
||||
auto protocolConfig = config.protocolConfigs.value(protocolName);
|
||||
|
||||
QStringList fixedPorts = ContainerProps::fixedPortsForContainer(container);
|
||||
|
||||
QString defaultPort("%1");
|
||||
QString port = containerConfig.value(config_key::port).toString(defaultPort.arg(ProtocolProps::defaultPort(protocol)));
|
||||
QString defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(protocol), protocol);
|
||||
QString transportProto = containerConfig.value(config_key::transport_proto).toString(defaultTransportProto);
|
||||
QString port = QString::number(ProtocolProps::defaultPort(protocol)); // default
|
||||
QString transportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(protocol), protocol); // default
|
||||
|
||||
if (protocolConfig) {
|
||||
if (auto openVpnConfig = qSharedPointerCast<OpenVpnProtocolConfig>(protocolConfig)) {
|
||||
port = openVpnConfig->serverProtocolConfig.port;
|
||||
transportProto = openVpnConfig->serverProtocolConfig.transportProto;
|
||||
} else if (auto wgConfig = qSharedPointerCast<WireGuardProtocolConfig>(protocolConfig)) {
|
||||
port = wgConfig->serverProtocolConfig.port;
|
||||
transportProto = wgConfig->serverProtocolConfig.transportProto;
|
||||
} else if (auto awgConfig = qSharedPointerCast<AwgProtocolConfig>(protocolConfig)) {
|
||||
port = awgConfig->serverProtocolConfig.port;
|
||||
transportProto = awgConfig->serverProtocolConfig.transportProto;
|
||||
} else if (auto xrayConfig = qSharedPointerCast<XrayProtocolConfig>(protocolConfig)) {
|
||||
port = xrayConfig->serverProtocolConfig.port;
|
||||
transportProto = xrayConfig->serverProtocolConfig.transportProto;
|
||||
} else if (auto shadowsocksConfig = qSharedPointerCast<ShadowsocksProtocolConfig>(protocolConfig)) {
|
||||
port = shadowsocksConfig->serverProtocolConfig.port;
|
||||
} else if (auto cloakConfig = qSharedPointerCast<CloakProtocolConfig>(protocolConfig)) {
|
||||
port = cloakConfig->serverProtocolConfig.port;
|
||||
} else if (auto sftpConfig = qSharedPointerCast<SftpProtocolConfig>(protocolConfig)) {
|
||||
port = sftpConfig->serverProtocolConfig.port;
|
||||
} else if (auto socks5Config = qSharedPointerCast<Socks5ProtocolConfig>(protocolConfig)) {
|
||||
port = socks5Config->serverProtocolConfig.port;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO reimplement with netstat
|
||||
QString script = QString("which lsof > /dev/null 2>&1 || true && sudo lsof -i -P -n 2>/dev/null | grep -E ':%1 ").arg(port);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QObject>
|
||||
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "core/models/containers/containerConfig.h"
|
||||
#include "core/defs.h"
|
||||
#include "core/sshclient.h"
|
||||
|
||||
@@ -25,12 +26,12 @@ public:
|
||||
ErrorCode rebootServer(const ServerCredentials &credentials);
|
||||
ErrorCode removeAllContainers(const ServerCredentials &credentials);
|
||||
ErrorCode removeContainer(const ServerCredentials &credentials, DockerContainer container);
|
||||
ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config, bool isUpdate = false);
|
||||
ErrorCode updateContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &oldConfig,
|
||||
QJsonObject &newConfig);
|
||||
ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, ContainerConfig &config, bool isUpdate = false);
|
||||
ErrorCode updateContainer(const ServerCredentials &credentials, DockerContainer container, const ContainerConfig &oldConfig,
|
||||
ContainerConfig &newConfig);
|
||||
|
||||
ErrorCode startupContainerWorker(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &config = QJsonObject());
|
||||
const ContainerConfig &config = ContainerConfig());
|
||||
|
||||
ErrorCode uploadTextFileToContainer(DockerContainer container, const ServerCredentials &credentials, const QString &file,
|
||||
const QString &path,
|
||||
@@ -40,7 +41,7 @@ public:
|
||||
|
||||
QString replaceVars(const QString &script, const Vars &vars);
|
||||
Vars generateVarsForContainer(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &config = QJsonObject());
|
||||
const ContainerConfig &config = ContainerConfig());
|
||||
|
||||
ErrorCode runScript(const ServerCredentials &credentials, QString script,
|
||||
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdOut = nullptr,
|
||||
@@ -59,14 +60,14 @@ public:
|
||||
|
||||
private:
|
||||
ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container);
|
||||
ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const ContainerConfig &config = ContainerConfig());
|
||||
ErrorCode buildContainerWorker(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &config = QJsonObject());
|
||||
ErrorCode runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config);
|
||||
ErrorCode configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config);
|
||||
const ContainerConfig &config = ContainerConfig());
|
||||
ErrorCode runContainerWorker(const ServerCredentials &credentials, DockerContainer container, ContainerConfig &config);
|
||||
ErrorCode configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, ContainerConfig &config);
|
||||
|
||||
ErrorCode isServerPortBusy(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config);
|
||||
bool isReinstallContainerRequired(DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig);
|
||||
ErrorCode isServerPortBusy(const ServerCredentials &credentials, DockerContainer container, const ContainerConfig &config);
|
||||
bool isReinstallContainerRequired(DockerContainer container, const ContainerConfig &oldConfig, const ContainerConfig &newConfig);
|
||||
ErrorCode isUserInSudo(const ServerCredentials &credentials, DockerContainer container);
|
||||
ErrorCode isServerDpkgBusy(const ServerCredentials &credentials, DockerContainer container);
|
||||
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
#include "core/models/protocols/ikev2ProtocolConfig.h"
|
||||
#include "core/models/protocols/openvpnProtocolConfig.h"
|
||||
#include "core/models/protocols/shadowsocksProtocolConfig.h"
|
||||
#include "core/models/protocols/torWebsiteProtocolConfig.h"
|
||||
#include "core/models/protocols/wireguardProtocolConfig.h"
|
||||
#include "core/models/protocols/xrayProtocolConfig.h"
|
||||
#include "core/models/protocols/protocolConfig.h"
|
||||
#include <variant>
|
||||
|
||||
VpnConfigurationsController::VpnConfigurationsController(const std::shared_ptr<Settings> &settings,
|
||||
QSharedPointer<ServerController> serverController, QObject *parent)
|
||||
@@ -36,31 +39,33 @@ QScopedPointer<ConfiguratorBase> VpnConfigurationsController::createConfigurator
|
||||
}
|
||||
}
|
||||
|
||||
QSharedPointer<ProtocolConfig> VpnConfigurationsController::createProtocolConfig(const Proto protocol, const QJsonObject &protocolConfigJson)
|
||||
QSharedPointer<ProtocolConfig> VpnConfigurationsController::createProtocolConfig(const Proto protocol)
|
||||
{
|
||||
switch (protocol) {
|
||||
case Proto::OpenVpn:
|
||||
return QSharedPointer<OpenVpnProtocolConfig>::create(protocolConfigJson, ProtocolProps::protoToString(protocol));
|
||||
return QSharedPointer<OpenVpnProtocolConfig>::create(QJsonObject(), ProtocolProps::protoToString(protocol));
|
||||
case Proto::ShadowSocks:
|
||||
return QSharedPointer<ShadowsocksProtocolConfig>::create(protocolConfigJson, ProtocolProps::protoToString(protocol));
|
||||
return QSharedPointer<ShadowsocksProtocolConfig>::create(QJsonObject(), ProtocolProps::protoToString(protocol));
|
||||
case Proto::Cloak:
|
||||
return QSharedPointer<CloakProtocolConfig>::create(protocolConfigJson, ProtocolProps::protoToString(protocol));
|
||||
return QSharedPointer<CloakProtocolConfig>::create(QJsonObject(), ProtocolProps::protoToString(protocol));
|
||||
case Proto::WireGuard:
|
||||
return QSharedPointer<WireGuardProtocolConfig>::create(protocolConfigJson, ProtocolProps::protoToString(protocol));
|
||||
return QSharedPointer<WireGuardProtocolConfig>::create(QJsonObject(), ProtocolProps::protoToString(protocol));
|
||||
case Proto::Awg:
|
||||
return QSharedPointer<AwgProtocolConfig>::create(protocolConfigJson, ProtocolProps::protoToString(protocol));
|
||||
return QSharedPointer<AwgProtocolConfig>::create(QJsonObject(), ProtocolProps::protoToString(protocol));
|
||||
case Proto::Xray:
|
||||
case Proto::SSXray:
|
||||
return QSharedPointer<XrayProtocolConfig>::create(protocolConfigJson, ProtocolProps::protoToString(protocol));
|
||||
return QSharedPointer<XrayProtocolConfig>::create(QJsonObject(), ProtocolProps::protoToString(protocol));
|
||||
case Proto::Ikev2:
|
||||
return QSharedPointer<Ikev2ProtocolConfig>::create(ProtocolProps::protoToString(protocol));
|
||||
case Proto::TorWebSite:
|
||||
return QSharedPointer<TorWebsiteProtocolConfig>::create(QJsonObject(), ProtocolProps::protoToString(protocol));
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ErrorCode VpnConfigurationsController::createProtocolConfigForContainer(const ServerCredentials &credentials,
|
||||
const DockerContainer container, QJsonObject &containerConfig)
|
||||
const DockerContainer container, ContainerConfig &containerConfig)
|
||||
{
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
|
||||
@@ -69,13 +74,16 @@ ErrorCode VpnConfigurationsController::createProtocolConfigForContainer(const Se
|
||||
}
|
||||
|
||||
for (Proto protocol : ContainerProps::protocolsForContainer(container)) {
|
||||
QJsonObject protocolConfigJson = containerConfig.value(ProtocolProps::protoToString(protocol)).toObject();
|
||||
|
||||
// Create ProtocolConfig from JSON
|
||||
auto protocolConfig = createProtocolConfig(protocol, protocolConfigJson);
|
||||
QString protocolName = ProtocolProps::protoToString(protocol);
|
||||
auto protocolConfig = containerConfig.protocolConfigs.value(protocolName);
|
||||
|
||||
if (!protocolConfig) {
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return errorCode;
|
||||
protocolConfig = createProtocolConfig(protocol);
|
||||
if (!protocolConfig) {
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return errorCode;
|
||||
}
|
||||
containerConfig.protocolConfigs.insert(protocolName, protocolConfig);
|
||||
}
|
||||
|
||||
auto configurator = createConfigurator(protocol);
|
||||
@@ -84,35 +92,16 @@ ErrorCode VpnConfigurationsController::createProtocolConfigForContainer(const Se
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
// Extract nativeConfig and store back in JSON for backward compatibility
|
||||
QString nativeConfig;
|
||||
if (auto openVpnConfig = qSharedPointerCast<OpenVpnProtocolConfig>(result)) {
|
||||
nativeConfig = openVpnConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto wgConfig = qSharedPointerCast<WireGuardProtocolConfig>(result)) {
|
||||
nativeConfig = wgConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto awgConfig = qSharedPointerCast<AwgProtocolConfig>(result)) {
|
||||
nativeConfig = awgConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto cloakConfig = qSharedPointerCast<CloakProtocolConfig>(result)) {
|
||||
nativeConfig = cloakConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto xrayConfig = qSharedPointerCast<XrayProtocolConfig>(result)) {
|
||||
nativeConfig = xrayConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto shadowsocksConfig = qSharedPointerCast<ShadowsocksProtocolConfig>(result)) {
|
||||
nativeConfig = shadowsocksConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto ikev2Config = qSharedPointerCast<Ikev2ProtocolConfig>(result)) {
|
||||
nativeConfig = ikev2Config->clientProtocolConfig.nativeConfig;
|
||||
}
|
||||
|
||||
protocolConfigJson.insert(config_key::last_config, nativeConfig);
|
||||
containerConfig.insert(ProtocolProps::protoToString(protocol), protocolConfigJson);
|
||||
containerConfig.protocolConfigs.insert(protocolName, result);
|
||||
}
|
||||
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
ErrorCode VpnConfigurationsController::createProtocolConfigString(const bool isApiConfig, const QPair<QString, QString> &dns,
|
||||
const ServerCredentials &credentials, const DockerContainer container,
|
||||
const QJsonObject &containerConfig, const Proto protocol,
|
||||
QString &protocolConfigString)
|
||||
const ServerCredentials &credentials, const DockerContainer container,
|
||||
const ContainerConfig &containerConfig, const Proto protocol,
|
||||
QString &protocolConfigString)
|
||||
{
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
|
||||
@@ -120,9 +109,8 @@ ErrorCode VpnConfigurationsController::createProtocolConfigString(const bool isA
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
// Create ProtocolConfig from JSON
|
||||
QJsonObject protocolConfigJson = containerConfig.value(ProtocolProps::protoToString(protocol)).toObject();
|
||||
auto protocolConfig = createProtocolConfig(protocol, protocolConfigJson);
|
||||
QString protocolName = ProtocolProps::protoToString(protocol);
|
||||
auto protocolConfig = containerConfig.protocolConfigs.value(protocolName);
|
||||
if (!protocolConfig) {
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return errorCode;
|
||||
@@ -134,31 +122,17 @@ ErrorCode VpnConfigurationsController::createProtocolConfigString(const bool isA
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
// Extract nativeConfig
|
||||
QString nativeConfig;
|
||||
if (auto openVpnConfig = qSharedPointerCast<OpenVpnProtocolConfig>(result)) {
|
||||
nativeConfig = openVpnConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto wgConfig = qSharedPointerCast<WireGuardProtocolConfig>(result)) {
|
||||
nativeConfig = wgConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto awgConfig = qSharedPointerCast<AwgProtocolConfig>(result)) {
|
||||
nativeConfig = awgConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto cloakConfig = qSharedPointerCast<CloakProtocolConfig>(result)) {
|
||||
nativeConfig = cloakConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto xrayConfig = qSharedPointerCast<XrayProtocolConfig>(result)) {
|
||||
nativeConfig = xrayConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto shadowsocksConfig = qSharedPointerCast<ShadowsocksProtocolConfig>(result)) {
|
||||
nativeConfig = shadowsocksConfig->clientProtocolConfig.nativeConfig;
|
||||
} else if (auto ikev2Config = qSharedPointerCast<Ikev2ProtocolConfig>(result)) {
|
||||
nativeConfig = ikev2Config->clientProtocolConfig.nativeConfig;
|
||||
}
|
||||
|
||||
protocolConfigString = configurator->processConfigWithExportSettings(dns, isApiConfig, nativeConfig);
|
||||
configurator->processConfigWithExportSettings(dns, isApiConfig, result);
|
||||
ProtocolConfigVariant variant = ProtocolConfig::getProtocolConfigVariant(result);
|
||||
std::visit([&protocolConfigString](const auto &config) -> void {
|
||||
protocolConfigString = config->clientProtocolConfig.nativeConfig;
|
||||
}, variant);
|
||||
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair<QString, QString> &dns, const QJsonObject &serverConfig,
|
||||
const QJsonObject &containerConfig, const DockerContainer container)
|
||||
QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair<QString, QString> &dns, const QSharedPointer<ServerConfig> &serverConfig,
|
||||
const ContainerConfig &containerConfig, const DockerContainer container)
|
||||
{
|
||||
QJsonObject vpnConfiguration {};
|
||||
|
||||
@@ -166,22 +140,44 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair<QStr
|
||||
return vpnConfiguration;
|
||||
}
|
||||
|
||||
bool isApiConfig = serverConfig.value(config_key::configVersion).toInt();
|
||||
bool isApiConfig = static_cast<int>(serverConfig->type);
|
||||
|
||||
for (ProtocolEnumNS::Proto proto : ContainerProps::protocolsForContainer(container)) {
|
||||
if (isApiConfig && container == DockerContainer::Cloak && proto == ProtocolEnumNS::Proto::ShadowSocks) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString protocolConfigString =
|
||||
containerConfig.value(ProtocolProps::protoToString(proto)).toObject().value(config_key::last_config).toString();
|
||||
QString protocolName = ProtocolProps::protoToString(proto);
|
||||
auto protocolConfig = containerConfig.protocolConfigs.value(protocolName);
|
||||
QString protocolConfigString;
|
||||
|
||||
if (protocolConfig) {
|
||||
auto configurator = createConfigurator(proto);
|
||||
configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfig);
|
||||
ProtocolConfigVariant variant = ProtocolConfig::getProtocolConfigVariant(protocolConfig);
|
||||
std::visit([&protocolConfigString](const auto &config) -> void {
|
||||
protocolConfigString = config->clientProtocolConfig.nativeConfig;
|
||||
}, variant);
|
||||
} else {
|
||||
protocolConfigString = "";
|
||||
}
|
||||
|
||||
auto configurator = createConfigurator(proto);
|
||||
protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString);
|
||||
|
||||
QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
||||
QJsonObject vpnConfigData;
|
||||
if (proto == Proto::Xray || proto == Proto::SSXray) {
|
||||
vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
||||
} else {
|
||||
vpnConfigData[config_key::config] = protocolConfigString;
|
||||
if (protocolConfig) {
|
||||
QJsonObject protocolJson = protocolConfig->toJson();
|
||||
for (auto it = protocolJson.begin(); it != protocolJson.end(); ++it) {
|
||||
if (it.key() != config_key::config && it.key() != config_key::last_config) {
|
||||
vpnConfigData[it.key()] = it.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (container == DockerContainer::Awg || container == DockerContainer::WireGuard) {
|
||||
// add mtu for old configs
|
||||
if (vpnConfigData[config_key::mtu].toString().isEmpty()) {
|
||||
vpnConfigData[config_key::mtu] =
|
||||
container == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
||||
@@ -197,31 +193,32 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair<QStr
|
||||
vpnConfiguration[config_key::dns1] = dns.first;
|
||||
vpnConfiguration[config_key::dns2] = dns.second;
|
||||
|
||||
vpnConfiguration[config_key::hostName] = serverConfig.value(config_key::hostName).toString();
|
||||
vpnConfiguration[config_key::description] = serverConfig.value(config_key::description).toString();
|
||||
vpnConfiguration[config_key::hostName] = serverConfig->hostName;
|
||||
vpnConfiguration[config_key::description] = serverConfig->toJson().value(config_key::description).toString();
|
||||
|
||||
vpnConfiguration[config_key::configVersion] = static_cast<int>(serverConfig->type);
|
||||
|
||||
vpnConfiguration[config_key::configVersion] = serverConfig.value(config_key::configVersion).toInt();
|
||||
// TODO: try to get hostName, port, description for 3rd party configs
|
||||
// vpnConfiguration[config_key::port] = ...;
|
||||
|
||||
return vpnConfiguration;
|
||||
}
|
||||
|
||||
void VpnConfigurationsController::updateContainerConfigAfterInstallation(const DockerContainer container, QJsonObject &containerConfig,
|
||||
const QString &stdOut)
|
||||
void VpnConfigurationsController::updateContainerConfigAfterInstallation(const DockerContainer container, ContainerConfig &containerConfig,
|
||||
const QString &stdOut)
|
||||
{
|
||||
Proto mainProto = ContainerProps::defaultProtocol(container);
|
||||
|
||||
if (container == DockerContainer::TorWebSite) {
|
||||
QJsonObject protocol = containerConfig.value(ProtocolProps::protoToString(mainProto)).toObject();
|
||||
QString protocolName = ProtocolProps::protoToString(mainProto);
|
||||
auto protocolConfig = containerConfig.protocolConfigs.value(protocolName);
|
||||
|
||||
qDebug() << "amnezia-tor onions" << stdOut;
|
||||
|
||||
QString onion = stdOut;
|
||||
onion.replace("\n", "");
|
||||
protocol.insert(config_key::site, onion);
|
||||
|
||||
containerConfig.insert(ProtocolProps::protoToString(mainProto), protocol);
|
||||
|
||||
if (auto torConfig = qSharedPointerCast<TorWebsiteProtocolConfig>(protocolConfig)) {
|
||||
torConfig->serverProtocolConfig.site = onion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
#include "configurators/configurator_base.h"
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "core/models/containers/containerConfig.h"
|
||||
#include "core/defs.h"
|
||||
#include "core/models/protocols/protocolConfig.h"
|
||||
#include "core/models/servers/serverConfig.h"
|
||||
#include "settings.h"
|
||||
|
||||
class VpnConfigurationsController : public QObject
|
||||
@@ -18,19 +20,21 @@ public:
|
||||
|
||||
public slots:
|
||||
ErrorCode createProtocolConfigForContainer(const ServerCredentials &credentials, const DockerContainer container,
|
||||
QJsonObject &containerConfig);
|
||||
ContainerConfig &containerConfig);
|
||||
ErrorCode createProtocolConfigString(const bool isApiConfig, const QPair<QString, QString> &dns, const ServerCredentials &credentials,
|
||||
const DockerContainer container, const QJsonObject &containerConfig, const Proto protocol,
|
||||
const DockerContainer container, const ContainerConfig &containerConfig, const Proto protocol,
|
||||
QString &protocolConfigString);
|
||||
QJsonObject createVpnConfiguration(const QPair<QString, QString> &dns, const QJsonObject &serverConfig,
|
||||
const QJsonObject &containerConfig, const DockerContainer container);
|
||||
QJsonObject createVpnConfiguration(const QPair<QString, QString> &dns, const QSharedPointer<ServerConfig> &serverConfig,
|
||||
const ContainerConfig &containerConfig, const DockerContainer container);
|
||||
|
||||
static void updateContainerConfigAfterInstallation(const DockerContainer container, QJsonObject &containerConfig, const QString &stdOut);
|
||||
static void updateContainerConfigAfterInstallation(const DockerContainer container, ContainerConfig &containerConfig, const QString &stdOut);
|
||||
signals:
|
||||
|
||||
public:
|
||||
QSharedPointer<ProtocolConfig> createProtocolConfig(const Proto protocol);
|
||||
|
||||
private:
|
||||
QScopedPointer<ConfiguratorBase> createConfigurator(const Proto protocol);
|
||||
QSharedPointer<ProtocolConfig> createProtocolConfig(const Proto protocol, const QJsonObject &protocolConfigJson);
|
||||
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
QSharedPointer<ServerController> m_serverController;
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
#include "vpnConnectionController.h"
|
||||
|
||||
#include <QtConcurrent>
|
||||
|
||||
#include "core/controllers/vpnConfigurationController.h"
|
||||
#include "core/controllers/selfhosted/serverController.h"
|
||||
#include "settings.h"
|
||||
#include "logger.h"
|
||||
#include "utilities.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
Logger logger("VpnConnectionController");
|
||||
}
|
||||
|
||||
VpnConnectionController::VpnConnectionController(std::shared_ptr<Settings> settings, QObject *parent)
|
||||
: QObject(parent), m_settings(settings)
|
||||
{
|
||||
}
|
||||
|
||||
QFuture<QJsonObject> VpnConnectionController::prepareVpnConfiguration(const QSharedPointer<ServerConfig> &serverConfig,
|
||||
DockerContainer container,
|
||||
const QJsonObject &containerConfig)
|
||||
{
|
||||
return QtConcurrent::run([this, serverConfig, container, containerConfig]() -> QJsonObject {
|
||||
logger.info() << "Preparing VPN configuration for container" << ContainerProps::containerToString(container);
|
||||
|
||||
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
|
||||
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
|
||||
|
||||
// TODO: Extract DNS pair from serverConfig
|
||||
QPair<QString, QString> dns = qMakePair(QString(), QString());
|
||||
|
||||
auto vpnConfiguration = vpnConfigurationController.createVpnConfiguration(dns,
|
||||
serverConfig->toJson(),
|
||||
containerConfig,
|
||||
container);
|
||||
|
||||
emit configurationPrepared(vpnConfiguration);
|
||||
return vpnConfiguration;
|
||||
});
|
||||
}
|
||||
|
||||
QFuture<bool> VpnConnectionController::validateConnection(const QSharedPointer<ServerConfig> &serverConfig,
|
||||
DockerContainer container)
|
||||
{
|
||||
return QtConcurrent::run([this, serverConfig, container]() -> bool {
|
||||
logger.info() << "Validating connection for container" << ContainerProps::containerToString(container);
|
||||
|
||||
if (!isServerSupported(serverConfig, container)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Implement connection validation logic
|
||||
// Check if container is supported by current platform
|
||||
// Check if server is reachable
|
||||
// Check if container is properly configured
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
QFuture<ErrorCode> VpnConnectionController::establishConnection(const QSharedPointer<ServerConfig> &serverConfig,
|
||||
DockerContainer container,
|
||||
const QJsonObject &vpnConfiguration)
|
||||
{
|
||||
return QtConcurrent::run([this, serverConfig, container, vpnConfiguration]() -> ErrorCode {
|
||||
logger.info() << "Establishing connection for container" << ContainerProps::containerToString(container);
|
||||
|
||||
// TODO: Implement connection establishment logic
|
||||
// This will delegate to VpnConnection or similar
|
||||
|
||||
emit connectionEstablished();
|
||||
return ErrorCode::NoError;
|
||||
});
|
||||
}
|
||||
|
||||
QFuture<ErrorCode> VpnConnectionController::terminateConnection()
|
||||
{
|
||||
return QtConcurrent::run([this]() -> ErrorCode {
|
||||
logger.info() << "Terminating VPN connection";
|
||||
|
||||
// TODO: Implement connection termination logic
|
||||
// This will delegate to VpnConnection or similar
|
||||
|
||||
emit connectionTerminated();
|
||||
return ErrorCode::NoError;
|
||||
});
|
||||
}
|
||||
|
||||
bool VpnConnectionController::isServerSupported(const QSharedPointer<ServerConfig> &serverConfig, DockerContainer container) const
|
||||
{
|
||||
// TODO: Implement server support validation
|
||||
// Check if container is supported by current platform
|
||||
Q_UNUSED(serverConfig)
|
||||
|
||||
return ContainerProps::isSupportedByCurrentPlatform(container);
|
||||
}
|
||||
|
||||
QJsonObject VpnConnectionController::createVpnConfiguration(const QPair<QString, QString> &dns,
|
||||
const QJsonObject &serverConfig,
|
||||
const QJsonObject &containerConfig,
|
||||
DockerContainer container)
|
||||
{
|
||||
// TODO: Implement VPN configuration creation logic
|
||||
// This will be moved from existing code
|
||||
Q_UNUSED(dns)
|
||||
Q_UNUSED(serverConfig)
|
||||
Q_UNUSED(containerConfig)
|
||||
Q_UNUSED(container)
|
||||
|
||||
return QJsonObject();
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
#ifndef VPNCONNECTIONCONTROLLER_H
|
||||
#define VPNCONNECTIONCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QFuture>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "core/models/servers/serverConfig.h"
|
||||
#include "protocols/vpnprotocol.h"
|
||||
|
||||
class Settings;
|
||||
class ServerController;
|
||||
class VpnConfigurationsController;
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
class VpnConnectionController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VpnConnectionController(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
||||
QFuture<QJsonObject> prepareVpnConfiguration(const QSharedPointer<ServerConfig> &serverConfig,
|
||||
DockerContainer container,
|
||||
const QJsonObject &containerConfig);
|
||||
|
||||
QFuture<bool> validateConnection(const QSharedPointer<ServerConfig> &serverConfig,
|
||||
DockerContainer container);
|
||||
|
||||
QFuture<ErrorCode> establishConnection(const QSharedPointer<ServerConfig> &serverConfig,
|
||||
DockerContainer container,
|
||||
const QJsonObject &vpnConfiguration);
|
||||
|
||||
QFuture<ErrorCode> terminateConnection();
|
||||
|
||||
bool isServerSupported(const QSharedPointer<ServerConfig> &serverConfig, DockerContainer container) const;
|
||||
|
||||
signals:
|
||||
void configurationPrepared(const QJsonObject &vpnConfiguration);
|
||||
void connectionEstablished();
|
||||
void connectionTerminated();
|
||||
void connectionError(ErrorCode errorCode);
|
||||
void connectionProgress(const QString &message);
|
||||
|
||||
private:
|
||||
QJsonObject createVpnConfiguration(const QPair<QString, QString> &dns,
|
||||
const QJsonObject &serverConfig,
|
||||
const QJsonObject &containerConfig,
|
||||
DockerContainer container);
|
||||
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
};
|
||||
|
||||
#endif // VPNCONNECTIONCONTROLLER_H
|
||||
76
client/core/models/clientInfo.cpp
Normal file
76
client/core/models/clientInfo.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "clientInfo.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace configKey
|
||||
{
|
||||
constexpr char clientId[] = "clientId";
|
||||
constexpr char clientName[] = "clientName";
|
||||
constexpr char container[] = "container";
|
||||
constexpr char userData[] = "userData";
|
||||
constexpr char creationDate[] = "creationDate";
|
||||
constexpr char latestHandshake[] = "latestHandshake";
|
||||
constexpr char dataReceived[] = "dataReceived";
|
||||
constexpr char dataSent[] = "dataSent";
|
||||
constexpr char allowedIps[] = "allowedIps";
|
||||
}
|
||||
}
|
||||
|
||||
ClientInfo::ClientInfo()
|
||||
: container(DockerContainer::None)
|
||||
{
|
||||
}
|
||||
|
||||
ClientInfo::ClientInfo(const QString &clientId, const QString &clientName)
|
||||
: clientId(clientId), clientName(clientName), creationDate(QDateTime::currentDateTime()), container(DockerContainer::None)
|
||||
{
|
||||
}
|
||||
|
||||
ClientInfo::ClientInfo(const QJsonObject &jsonObject)
|
||||
{
|
||||
clientId = jsonObject.value(configKey::clientId).toString();
|
||||
container = ContainerProps::containerFromString(jsonObject.value(configKey::container).toString());
|
||||
|
||||
QJsonObject userData = jsonObject.value(configKey::userData).toObject();
|
||||
clientName = userData.value(configKey::clientName).toString();
|
||||
creationDate = QDateTime::fromString(userData.value(configKey::creationDate).toString());
|
||||
|
||||
latestHandshake = jsonObject.value(configKey::latestHandshake).toString();
|
||||
dataReceived = jsonObject.value(configKey::dataReceived).toString();
|
||||
dataSent = jsonObject.value(configKey::dataSent).toString();
|
||||
allowedIps = jsonObject.value(configKey::allowedIps).toString();
|
||||
}
|
||||
|
||||
QJsonObject ClientInfo::toJson() const
|
||||
{
|
||||
QJsonObject jsonObject;
|
||||
jsonObject[configKey::clientId] = clientId;
|
||||
jsonObject[configKey::container] = ContainerProps::containerToString(container);
|
||||
|
||||
QJsonObject userData;
|
||||
userData[configKey::clientName] = clientName;
|
||||
userData[configKey::creationDate] = creationDate.toString();
|
||||
jsonObject[configKey::userData] = userData;
|
||||
|
||||
if (!latestHandshake.isEmpty()) {
|
||||
jsonObject[configKey::latestHandshake] = latestHandshake;
|
||||
}
|
||||
if (!dataReceived.isEmpty()) {
|
||||
jsonObject[configKey::dataReceived] = dataReceived;
|
||||
}
|
||||
if (!dataSent.isEmpty()) {
|
||||
jsonObject[configKey::dataSent] = dataSent;
|
||||
}
|
||||
if (!allowedIps.isEmpty()) {
|
||||
jsonObject[configKey::allowedIps] = allowedIps;
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
ClientInfo ClientInfo::fromJson(const QJsonObject &jsonObject)
|
||||
{
|
||||
return ClientInfo(jsonObject);
|
||||
}
|
||||
34
client/core/models/clientInfo.h
Normal file
34
client/core/models/clientInfo.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef CLIENTINFO_H
|
||||
#define CLIENTINFO_H
|
||||
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
class ClientInfo
|
||||
{
|
||||
public:
|
||||
ClientInfo();
|
||||
ClientInfo(const QString &clientId, const QString &clientName);
|
||||
ClientInfo(const QJsonObject &jsonObject);
|
||||
|
||||
QJsonObject toJson() const;
|
||||
|
||||
static ClientInfo fromJson(const QJsonObject &jsonObject);
|
||||
|
||||
QString clientId;
|
||||
QString clientName;
|
||||
QDateTime creationDate;
|
||||
DockerContainer container;
|
||||
|
||||
QString latestHandshake;
|
||||
QString dataReceived;
|
||||
QString dataSent;
|
||||
QString allowedIps;
|
||||
};
|
||||
|
||||
#endif // CLIENTINFO_H
|
||||
@@ -14,11 +14,13 @@ class AwgProtocolConfig;
|
||||
class SftpProtocolConfig;
|
||||
class Socks5ProtocolConfig;
|
||||
class Ikev2ProtocolConfig;
|
||||
class TorWebsiteProtocolConfig;
|
||||
|
||||
using ProtocolConfigVariant =
|
||||
std::variant<QSharedPointer<OpenVpnProtocolConfig>, QSharedPointer<WireGuardProtocolConfig>, QSharedPointer<ShadowsocksProtocolConfig>,
|
||||
QSharedPointer<CloakProtocolConfig>, QSharedPointer<XrayProtocolConfig>, QSharedPointer<AwgProtocolConfig>,
|
||||
QSharedPointer<SftpProtocolConfig>, QSharedPointer<Socks5ProtocolConfig>, QSharedPointer<Ikev2ProtocolConfig> >;
|
||||
QSharedPointer<SftpProtocolConfig>, QSharedPointer<Socks5ProtocolConfig>, QSharedPointer<Ikev2ProtocolConfig>,
|
||||
QSharedPointer<TorWebsiteProtocolConfig> >;
|
||||
|
||||
class ProtocolConfig
|
||||
{
|
||||
|
||||
32
client/core/models/protocols/torWebsiteProtocolConfig.cpp
Normal file
32
client/core/models/protocols/torWebsiteProtocolConfig.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "torWebsiteProtocolConfig.h"
|
||||
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
TorWebsiteProtocolConfig::TorWebsiteProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName)
|
||||
: ProtocolConfig(protocolName)
|
||||
{
|
||||
serverProtocolConfig.site = protocolConfigObject.value(config_key::site).toString();
|
||||
|
||||
clientProtocolConfig.isEmpty = false;
|
||||
}
|
||||
|
||||
QJsonObject TorWebsiteProtocolConfig::toJson() const
|
||||
{
|
||||
QJsonObject json;
|
||||
|
||||
json[config_key::site] = serverProtocolConfig.site;
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
bool TorWebsiteProtocolConfig::hasEqualServerSettings(const TorWebsiteProtocolConfig &other) const
|
||||
{
|
||||
return serverProtocolConfig.site == other.serverProtocolConfig.site;
|
||||
}
|
||||
|
||||
void TorWebsiteProtocolConfig::clearClientSettings()
|
||||
{
|
||||
clientProtocolConfig.isEmpty = true;
|
||||
}
|
||||
36
client/core/models/protocols/torWebsiteProtocolConfig.h
Normal file
36
client/core/models/protocols/torWebsiteProtocolConfig.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef TORWEBSITEPROTOCOLCONFIG_H
|
||||
#define TORWEBSITEPROTOCOLCONFIG_H
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
|
||||
#include "protocolConfig.h"
|
||||
|
||||
namespace torWebsite
|
||||
{
|
||||
struct ServerProtocolConfig
|
||||
{
|
||||
QString site;
|
||||
};
|
||||
|
||||
struct ClientProtocolConfig
|
||||
{
|
||||
bool isEmpty = true;
|
||||
};
|
||||
}
|
||||
|
||||
class TorWebsiteProtocolConfig : public ProtocolConfig
|
||||
{
|
||||
public:
|
||||
TorWebsiteProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName);
|
||||
|
||||
QJsonObject toJson() const override;
|
||||
|
||||
bool hasEqualServerSettings(const TorWebsiteProtocolConfig &other) const;
|
||||
void clearClientSettings();
|
||||
|
||||
torWebsite::ServerProtocolConfig serverProtocolConfig;
|
||||
torWebsite::ClientProtocolConfig clientProtocolConfig;
|
||||
};
|
||||
|
||||
#endif // TORWEBSITEPROTOCOLCONFIG_H
|
||||
@@ -204,26 +204,22 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur
|
||||
object:m_currentTunnel.connection];
|
||||
|
||||
|
||||
if (proto == amnezia::Proto::OpenVpn) {
|
||||
switch (proto) {
|
||||
case amnezia::Proto::OpenVpn:
|
||||
return setupOpenVPN();
|
||||
}
|
||||
if (proto == amnezia::Proto::Cloak) {
|
||||
case amnezia::Proto::Cloak:
|
||||
return setupCloak();
|
||||
}
|
||||
if (proto == amnezia::Proto::WireGuard) {
|
||||
case amnezia::Proto::WireGuard:
|
||||
return setupWireGuard();
|
||||
}
|
||||
if (proto == amnezia::Proto::Awg) {
|
||||
case amnezia::Proto::Awg:
|
||||
return setupAwg();
|
||||
}
|
||||
if (proto == amnezia::Proto::Xray) {
|
||||
case amnezia::Proto::Xray:
|
||||
return setupXray();
|
||||
}
|
||||
if (proto == amnezia::Proto::SSXray) {
|
||||
case amnezia::Proto::SSXray:
|
||||
return setupSSXray();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void IosController::disconnectVpn()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "connectionController.h"
|
||||
#include "connectionUIController.h"
|
||||
|
||||
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
|
||||
#include <QGuiApplication>
|
||||
@@ -7,71 +7,59 @@
|
||||
#endif
|
||||
|
||||
#include "core/controllers/vpnConfigurationController.h"
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "version.h"
|
||||
|
||||
ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &serversModel,
|
||||
const QSharedPointer<ContainersModel> &containersModel,
|
||||
const QSharedPointer<ClientManagementModel> &clientManagementModel,
|
||||
const QSharedPointer<VpnConnection> &vpnConnection, const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent)
|
||||
ConnectionUIController::ConnectionUIController(const QSharedPointer<ServersModel> &serversModel,
|
||||
const QSharedPointer<ContainersModel> &containersModel,
|
||||
const QSharedPointer<ClientManagementModel> &clientManagementModel,
|
||||
const QSharedPointer<ConnectionController> &connectionController, const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent)
|
||||
: QObject(parent),
|
||||
m_serversModel(serversModel),
|
||||
m_containersModel(containersModel),
|
||||
m_clientManagementModel(clientManagementModel),
|
||||
m_vpnConnection(vpnConnection),
|
||||
m_connectionController(connectionController),
|
||||
m_settings(settings)
|
||||
{
|
||||
connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, this, &ConnectionController::onConnectionStateChanged);
|
||||
connect(this, &ConnectionController::connectToVpn, m_vpnConnection.get(), &VpnConnection::connectToVpn, Qt::QueuedConnection);
|
||||
connect(this, &ConnectionController::disconnectFromVpn, m_vpnConnection.get(), &VpnConnection::disconnectFromVpn, Qt::QueuedConnection);
|
||||
connect(m_connectionController.get(), &ConnectionController::connectionEstablished, this, [this]() {
|
||||
onConnectionStateChanged(Vpn::ConnectionState::Connected);
|
||||
});
|
||||
connect(m_connectionController.get(), &ConnectionController::connectionTerminated, this, [this]() {
|
||||
onConnectionStateChanged(Vpn::ConnectionState::Disconnected);
|
||||
});
|
||||
connect(m_connectionController.get(), &ConnectionController::connectionError, this, [this](ErrorCode) {
|
||||
onConnectionStateChanged(Vpn::ConnectionState::Error);
|
||||
});
|
||||
|
||||
connect(this, &ConnectionController::connectButtonClicked, this, &ConnectionController::toggleConnection, Qt::QueuedConnection);
|
||||
connect(this, &ConnectionUIController::connectButtonClicked, this, &ConnectionUIController::toggleConnection, Qt::QueuedConnection);
|
||||
|
||||
m_state = Vpn::ConnectionState::Disconnected;
|
||||
}
|
||||
|
||||
void ConnectionController::openConnection()
|
||||
void ConnectionUIController::openConnection()
|
||||
{
|
||||
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
||||
if (!Utils::processIsRunning(Utils::executable(SERVICE_NAME, false), true)) {
|
||||
emit connectionErrorOccurred(ErrorCode::AmneziaServiceNotRunning);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int serverIndex = m_serversModel->getDefaultServerIndex();
|
||||
QJsonObject serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||
|
||||
DockerContainer container = qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
|
||||
|
||||
if (!m_containersModel->isSupportedByCurrentPlatform(container)) {
|
||||
emit connectionErrorOccurred(ErrorCode::NotSupportedOnThisPlatform);
|
||||
return;
|
||||
}
|
||||
|
||||
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
|
||||
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
|
||||
|
||||
QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
|
||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||
|
||||
auto dns = m_serversModel->getDnsPair(serverIndex);
|
||||
|
||||
auto vpnConfiguration = vpnConfigurationController.createVpnConfiguration(dns, serverConfig, containerConfig, container);
|
||||
emit connectToVpn(serverIndex, credentials, container, vpnConfiguration);
|
||||
m_connectionController->openConnection(serverIndex, serverConfig, container, credentials, dns);
|
||||
}
|
||||
|
||||
void ConnectionController::closeConnection()
|
||||
void ConnectionUIController::closeConnection()
|
||||
{
|
||||
emit disconnectFromVpn();
|
||||
m_connectionController->closeConnection();
|
||||
}
|
||||
|
||||
ErrorCode ConnectionController::getLastConnectionError()
|
||||
ErrorCode ConnectionUIController::getLastConnectionError()
|
||||
{
|
||||
return m_vpnConnection->lastError();
|
||||
}
|
||||
|
||||
void ConnectionController::onConnectionStateChanged(Vpn::ConnectionState state)
|
||||
void ConnectionUIController::onConnectionStateChanged(Vpn::ConnectionState state)
|
||||
{
|
||||
m_state = state;
|
||||
|
||||
@@ -124,7 +112,7 @@ void ConnectionController::onConnectionStateChanged(Vpn::ConnectionState state)
|
||||
emit connectionStateChanged();
|
||||
}
|
||||
|
||||
void ConnectionController::onCurrentContainerUpdated()
|
||||
void ConnectionUIController::onCurrentContainerUpdated()
|
||||
{
|
||||
if (m_isConnected || m_isConnectionInProgress) {
|
||||
emit reconnectWithUpdatedContainer(tr("Settings updated successfully, reconnnection..."));
|
||||
@@ -134,23 +122,23 @@ void ConnectionController::onCurrentContainerUpdated()
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionController::onTranslationsUpdated()
|
||||
void ConnectionUIController::onTranslationsUpdated()
|
||||
{
|
||||
// get translated text of current state
|
||||
onConnectionStateChanged(getCurrentConnectionState());
|
||||
}
|
||||
|
||||
Vpn::ConnectionState ConnectionController::getCurrentConnectionState()
|
||||
Vpn::ConnectionState ConnectionUIController::getCurrentConnectionState()
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
QString ConnectionController::connectionStateText() const
|
||||
QString ConnectionUIController::connectionStateText() const
|
||||
{
|
||||
return m_connectionStateText;
|
||||
}
|
||||
|
||||
void ConnectionController::toggleConnection()
|
||||
void ConnectionUIController::toggleConnection()
|
||||
{
|
||||
if (m_state == Vpn::ConnectionState::Preparing) {
|
||||
emit preparingConfig();
|
||||
@@ -166,12 +154,12 @@ void ConnectionController::toggleConnection()
|
||||
}
|
||||
}
|
||||
|
||||
bool ConnectionController::isConnectionInProgress() const
|
||||
bool ConnectionUIController::isConnectionInProgress() const
|
||||
{
|
||||
return m_isConnectionInProgress;
|
||||
}
|
||||
|
||||
bool ConnectionController::isConnected() const
|
||||
bool ConnectionUIController::isConnected() const
|
||||
{
|
||||
return m_isConnected;
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
#ifndef CONNECTIONCONTROLLER_H
|
||||
#define CONNECTIONCONTROLLER_H
|
||||
#ifndef CONNECTIONUICONTROLLER_H
|
||||
#define CONNECTIONUICONTROLLER_H
|
||||
|
||||
#include "protocols/vpnprotocol.h"
|
||||
#include "ui/models/selfhosted/clientManagementModel.h"
|
||||
#include "ui/models/containers_model.h"
|
||||
#include "ui/models/servers_model.h"
|
||||
#include "vpnconnection.h"
|
||||
#include "core/controllers/connectionController.h"
|
||||
|
||||
class ConnectionController : public QObject
|
||||
class ConnectionUIController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -16,12 +16,12 @@ public:
|
||||
Q_PROPERTY(bool isConnectionInProgress READ isConnectionInProgress NOTIFY connectionStateChanged)
|
||||
Q_PROPERTY(QString connectionStateText READ connectionStateText NOTIFY connectionStateChanged)
|
||||
|
||||
explicit ConnectionController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
|
||||
const QSharedPointer<ClientManagementModel> &clientManagementModel,
|
||||
const QSharedPointer<VpnConnection> &vpnConnection, const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent = nullptr);
|
||||
explicit ConnectionUIController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
|
||||
const QSharedPointer<ClientManagementModel> &clientManagementModel,
|
||||
const QSharedPointer<ConnectionController> &connectionController, const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~ConnectionController() = default;
|
||||
~ConnectionUIController() = default;
|
||||
|
||||
bool isConnected() const;
|
||||
bool isConnectionInProgress() const;
|
||||
@@ -41,8 +41,6 @@ public slots:
|
||||
void onTranslationsUpdated();
|
||||
|
||||
signals:
|
||||
void connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &vpnConfiguration);
|
||||
void disconnectFromVpn();
|
||||
void connectionStateChanged();
|
||||
|
||||
void connectionErrorOccurred(ErrorCode errorCode);
|
||||
@@ -61,7 +59,7 @@ private:
|
||||
QSharedPointer<ContainersModel> m_containersModel;
|
||||
QSharedPointer<ClientManagementModel> m_clientManagementModel;
|
||||
|
||||
QSharedPointer<VpnConnection> m_vpnConnection;
|
||||
QSharedPointer<ConnectionController> m_connectionController;
|
||||
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
|
||||
@@ -72,4 +70,4 @@ private:
|
||||
Vpn::ConnectionState m_state;
|
||||
};
|
||||
|
||||
#endif // CONNECTIONCONTROLLER_H
|
||||
#endif // CONNECTIONUICONTROLLER_H
|
||||
@@ -13,6 +13,19 @@
|
||||
#include "core/qrCodeUtils.h"
|
||||
#include "core/serialization/serialization.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
#include "core/models/protocols/awgProtocolConfig.h"
|
||||
#include "core/models/protocols/wireguardProtocolConfig.h"
|
||||
#include "core/models/protocols/openvpnProtocolConfig.h"
|
||||
#include "core/models/protocols/shadowsocksProtocolConfig.h"
|
||||
#include "core/models/protocols/xrayProtocolConfig.h"
|
||||
#include "core/models/protocols/cloakProtocolConfig.h"
|
||||
#include "core/models/protocols/protocolConfig.h"
|
||||
#include "core/models/servers/selfHostedServerConfig.h"
|
||||
#include "core/models/servers/serverConfig.h"
|
||||
#include <variant>
|
||||
#include "core/models/servers/apiV1ServerConfig.h"
|
||||
#include "core/models/servers/apiV2ServerConfig.h"
|
||||
#include "core/models/containers/containerConfig.h"
|
||||
#include "systemController.h"
|
||||
#include "utilities.h"
|
||||
|
||||
@@ -167,7 +180,7 @@ bool ImportController::extractConfigFromData(QString data)
|
||||
switch (m_configType) {
|
||||
case ConfigTypes::OpenVpn: {
|
||||
m_config = extractOpenVpnConfig(config);
|
||||
if (!m_config.empty()) {
|
||||
if (m_config) {
|
||||
checkForMaliciousStrings(m_config);
|
||||
return true;
|
||||
}
|
||||
@@ -176,23 +189,24 @@ bool ImportController::extractConfigFromData(QString data)
|
||||
case ConfigTypes::Awg:
|
||||
case ConfigTypes::WireGuard: {
|
||||
m_config = extractWireGuardConfig(config);
|
||||
return m_config.empty() ? false : true;
|
||||
return m_config ? true : false;
|
||||
}
|
||||
case ConfigTypes::Xray: {
|
||||
m_config = extractXrayConfig(config);
|
||||
return m_config.empty() ? false : true;
|
||||
return m_config ? true : false;
|
||||
}
|
||||
case ConfigTypes::Amnezia: {
|
||||
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
|
||||
QJsonObject configJson = QJsonDocument::fromJson(config.toUtf8()).object();
|
||||
|
||||
if (apiUtils::isServerFromApi(m_config)) {
|
||||
auto apiConfig = m_config.value(apiDefs::key::apiConfig).toObject();
|
||||
if (apiUtils::isServerFromApi(configJson)) {
|
||||
auto apiConfig = configJson.value(apiDefs::key::apiConfig).toObject();
|
||||
apiConfig[apiDefs::key::vpnKey] = data;
|
||||
m_config[apiDefs::key::apiConfig] = apiConfig;
|
||||
configJson[apiDefs::key::apiConfig] = apiConfig;
|
||||
}
|
||||
m_config = ServerConfig::createServerConfig(configJson);
|
||||
|
||||
processAmneziaConfig(m_config);
|
||||
if (!m_config.empty()) {
|
||||
if (m_config) {
|
||||
checkForMaliciousStrings(m_config);
|
||||
return true;
|
||||
}
|
||||
@@ -218,13 +232,14 @@ bool ImportController::extractConfigFromQr(const QByteArray &data)
|
||||
{
|
||||
QJsonObject dataObj = QJsonDocument::fromJson(data).object();
|
||||
if (!dataObj.isEmpty()) {
|
||||
m_config = dataObj;
|
||||
m_config = ServerConfig::createServerConfig(dataObj);
|
||||
return true;
|
||||
}
|
||||
|
||||
QByteArray ba_uncompressed = qUncompress(data);
|
||||
if (!ba_uncompressed.isEmpty()) {
|
||||
m_config = QJsonDocument::fromJson(ba_uncompressed).object();
|
||||
QJsonObject configObj = QJsonDocument::fromJson(ba_uncompressed).object();
|
||||
m_config = ServerConfig::createServerConfig(configObj);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -238,7 +253,8 @@ bool ImportController::extractConfigFromQr(const QByteArray &data)
|
||||
}
|
||||
|
||||
if (!ba.isEmpty()) {
|
||||
m_config = QJsonDocument::fromJson(ba).object();
|
||||
QJsonObject configObj = QJsonDocument::fromJson(ba).object();
|
||||
m_config = ServerConfig::createServerConfig(configObj);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -248,7 +264,10 @@ bool ImportController::extractConfigFromQr(const QByteArray &data)
|
||||
|
||||
QString ImportController::getConfig()
|
||||
{
|
||||
return QJsonDocument(m_config).toJson(QJsonDocument::Indented);
|
||||
if (!m_config) {
|
||||
return QString();
|
||||
}
|
||||
return QJsonDocument(m_config->toJson()).toJson(QJsonDocument::Indented);
|
||||
}
|
||||
|
||||
QString ImportController::getConfigFileName()
|
||||
@@ -268,95 +287,84 @@ bool ImportController::isNativeWireGuardConfig()
|
||||
|
||||
void ImportController::processNativeWireGuardConfig()
|
||||
{
|
||||
auto containers = m_config.value(config_key::containers).toArray();
|
||||
if (!containers.isEmpty()) {
|
||||
auto container = containers.at(0).toObject();
|
||||
auto serverProtocolConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::WireGuard)).toObject();
|
||||
auto clientProtocolConfig = QJsonDocument::fromJson(serverProtocolConfig.value(config_key::last_config).toString().toUtf8()).object();
|
||||
|
||||
QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(2, 5));
|
||||
QString junkPacketMinSize = QString::number(10);
|
||||
QString junkPacketMaxSize = QString::number(50);
|
||||
clientProtocolConfig[config_key::junkPacketCount] = junkPacketCount;
|
||||
clientProtocolConfig[config_key::junkPacketMinSize] = junkPacketMinSize;
|
||||
clientProtocolConfig[config_key::junkPacketMaxSize] = junkPacketMaxSize;
|
||||
clientProtocolConfig[config_key::initPacketJunkSize] = "0";
|
||||
clientProtocolConfig[config_key::responsePacketJunkSize] = "0";
|
||||
clientProtocolConfig[config_key::initPacketMagicHeader] = "1";
|
||||
clientProtocolConfig[config_key::responsePacketMagicHeader] = "2";
|
||||
clientProtocolConfig[config_key::underloadPacketMagicHeader] = "3";
|
||||
clientProtocolConfig[config_key::transportPacketMagicHeader] = "4";
|
||||
|
||||
// clientProtocolConfig[config_key::cookieReplyPacketJunkSize] = "0";
|
||||
// clientProtocolConfig[config_key::transportPacketJunkSize] = "0";
|
||||
|
||||
// clientProtocolConfig[config_key::specialJunk1] = "";
|
||||
// clientProtocolConfig[config_key::specialJunk2] = "";
|
||||
// clientProtocolConfig[config_key::specialJunk3] = "";
|
||||
// clientProtocolConfig[config_key::specialJunk4] = "";
|
||||
// clientProtocolConfig[config_key::specialJunk5] = "";
|
||||
// clientProtocolConfig[config_key::controlledJunk1] = "";
|
||||
// clientProtocolConfig[config_key::controlledJunk2] = "";
|
||||
// clientProtocolConfig[config_key::controlledJunk3] = "";
|
||||
// clientProtocolConfig[config_key::specialHandshakeTimeout] = "0";
|
||||
|
||||
clientProtocolConfig[config_key::isObfuscationEnabled] = true;
|
||||
|
||||
serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(clientProtocolConfig).toJson());
|
||||
container["wireguard"] = serverProtocolConfig;
|
||||
containers.replace(0, container);
|
||||
m_config[config_key::containers] = containers;
|
||||
if (!m_config) return;
|
||||
|
||||
auto selfHostedConfig = qSharedPointerCast<SelfHostedServerConfig>(m_config);
|
||||
if (!selfHostedConfig) return;
|
||||
|
||||
QString wireguardContainerName = ContainerProps::containerTypeToString(DockerContainer::WireGuard);
|
||||
if (!selfHostedConfig->containerConfigs.contains(wireguardContainerName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ContainerConfig wireguardContainer = selfHostedConfig->containerConfigs.value(wireguardContainerName);
|
||||
if (!wireguardContainer.protocolConfigs.contains("wireguard")) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto wireguardProtocol = wireguardContainer.protocolConfigs.value("wireguard");
|
||||
|
||||
QJsonObject awgProtocolConfigJson;
|
||||
awgProtocolConfigJson[config_key::protocolName] = "awg";
|
||||
awgProtocolConfigJson[config_key::last_config] = wireguardProtocol->toJson().value(config_key::last_config);
|
||||
|
||||
auto awgConfig = QSharedPointer<AwgProtocolConfig>::create(awgProtocolConfigJson, "awg");
|
||||
|
||||
QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(2, 5));
|
||||
awgConfig->serverProtocolConfig.junkPacketCount = junkPacketCount;
|
||||
awgConfig->serverProtocolConfig.junkPacketMinSize = "10";
|
||||
awgConfig->serverProtocolConfig.junkPacketMaxSize = "50";
|
||||
awgConfig->serverProtocolConfig.initPacketJunkSize = "0";
|
||||
awgConfig->serverProtocolConfig.responsePacketJunkSize = "0";
|
||||
awgConfig->serverProtocolConfig.initPacketMagicHeader = "1";
|
||||
awgConfig->serverProtocolConfig.responsePacketMagicHeader = "2";
|
||||
awgConfig->serverProtocolConfig.underloadPacketMagicHeader = "3";
|
||||
awgConfig->serverProtocolConfig.transportPacketMagicHeader = "4";
|
||||
|
||||
wireguardContainer.protocolConfigs["wireguard"] = awgConfig;
|
||||
selfHostedConfig->containerConfigs[wireguardContainerName] = wireguardContainer;
|
||||
}
|
||||
|
||||
void ImportController::importConfig()
|
||||
{
|
||||
ServerCredentials credentials;
|
||||
credentials.hostName = m_config.value(config_key::hostName).toString();
|
||||
credentials.port = m_config.value(config_key::port).toInt();
|
||||
credentials.userName = m_config.value(config_key::userName).toString();
|
||||
credentials.secretData = m_config.value(config_key::password).toString();
|
||||
if (!m_config) {
|
||||
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (credentials.isValid() || m_config.contains(config_key::containers)) {
|
||||
m_serversModel->addServer(m_config);
|
||||
if (auto selfHostedConfig = qSharedPointerCast<SelfHostedServerConfig>(m_config)) {
|
||||
if (selfHostedConfig->serverCredentials.isValid() || !selfHostedConfig->containerConfigs.isEmpty()) {
|
||||
m_serversModel->addServer(m_config->toJson());
|
||||
emit importFinished();
|
||||
} else if (m_config.contains(config_key::configVersion)) {
|
||||
quint16 crc = qChecksum(QJsonDocument(m_config).toJson());
|
||||
} else {
|
||||
qDebug() << "Failed to import profile - invalid credentials or no containers";
|
||||
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
|
||||
}
|
||||
} else if (apiUtils::isServerFromApi(m_config->toJson())) {
|
||||
quint16 crc = qChecksum(QJsonDocument(m_config->toJson()).toJson());
|
||||
if (m_serversModel->isServerFromApiAlreadyExists(crc)) {
|
||||
emit importErrorOccurred(ErrorCode::ApiConfigAlreadyAdded, true);
|
||||
} else {
|
||||
m_config.insert(config_key::crc, crc);
|
||||
QJsonObject configJson = m_config->toJson();
|
||||
configJson[config_key::crc] = crc;
|
||||
auto updatedConfig = ServerConfig::createServerConfig(configJson);
|
||||
|
||||
m_serversModel->addServer(m_config);
|
||||
m_serversModel->addServer(updatedConfig->toJson());
|
||||
emit importFinished();
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Failed to import profile";
|
||||
qDebug().noquote() << QJsonDocument(m_config).toJson();
|
||||
qDebug() << "Failed to import profile - unknown config type";
|
||||
qDebug().noquote() << QJsonDocument(m_config->toJson()).toJson();
|
||||
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
|
||||
}
|
||||
|
||||
m_config = {};
|
||||
m_config.reset();
|
||||
m_configFileName.clear();
|
||||
m_maliciousWarningText.clear();
|
||||
}
|
||||
|
||||
QJsonObject ImportController::extractOpenVpnConfig(const QString &data)
|
||||
QSharedPointer<ServerConfig> ImportController::extractOpenVpnConfig(const QString &data)
|
||||
{
|
||||
QJsonObject openVpnConfig;
|
||||
openVpnConfig[config_key::config] = data;
|
||||
|
||||
QJsonObject lastConfig;
|
||||
lastConfig[config_key::last_config] = QString(QJsonDocument(openVpnConfig).toJson());
|
||||
lastConfig[config_key::isThirdPartyConfig] = true;
|
||||
|
||||
QJsonObject containers;
|
||||
containers.insert(config_key::container, QJsonValue("amnezia-openvpn"));
|
||||
containers.insert(config_key::openvpn, QJsonValue(lastConfig));
|
||||
|
||||
QJsonArray arr;
|
||||
arr.push_back(containers);
|
||||
|
||||
QString hostName;
|
||||
const static QRegularExpression hostNameRegExp("remote\\s+([^\\s]+)");
|
||||
QRegularExpressionMatch hostNameMatch = hostNameRegExp.match(data);
|
||||
@@ -364,26 +372,34 @@ QJsonObject ImportController::extractOpenVpnConfig(const QString &data)
|
||||
hostName = hostNameMatch.captured(1);
|
||||
}
|
||||
|
||||
QJsonObject config;
|
||||
config[config_key::containers] = arr;
|
||||
config[config_key::defaultContainer] = "amnezia-openvpn";
|
||||
config[config_key::description] = m_settings->nextAvailableServerName();
|
||||
auto serverConfig = QSharedPointer<SelfHostedServerConfig>::create();
|
||||
serverConfig->hostName = hostName;
|
||||
serverConfig->description = m_settings->nextAvailableServerName();
|
||||
serverConfig->defaultContainer = "amnezia-openvpn";
|
||||
|
||||
const static QRegularExpression dnsRegExp("dhcp-option DNS (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
|
||||
QRegularExpressionMatchIterator dnsMatch = dnsRegExp.globalMatch(data);
|
||||
if (dnsMatch.hasNext()) {
|
||||
config[config_key::dns1] = dnsMatch.next().captured(1);
|
||||
serverConfig->dns1 = dnsMatch.next().captured(1);
|
||||
}
|
||||
if (dnsMatch.hasNext()) {
|
||||
config[config_key::dns2] = dnsMatch.next().captured(1);
|
||||
serverConfig->dns2 = dnsMatch.next().captured(1);
|
||||
}
|
||||
|
||||
config[config_key::hostName] = hostName;
|
||||
auto openVpnProtocolConfig = QSharedPointer<OpenVpnProtocolConfig>::create();
|
||||
openVpnProtocolConfig->clientProtocolConfig.nativeConfig = data;
|
||||
openVpnProtocolConfig->isThirdPartyConfig = true;
|
||||
|
||||
return config;
|
||||
ContainerConfig containerConfig;
|
||||
containerConfig.container = DockerContainer::OpenVpn;
|
||||
containerConfig.protocolConfigs["openvpn"] = openVpnProtocolConfig;
|
||||
|
||||
serverConfig->containerConfigs["amnezia-openvpn"] = containerConfig;
|
||||
|
||||
return serverConfig;
|
||||
}
|
||||
|
||||
QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
||||
QSharedPointer<ServerConfig> ImportController::extractWireGuardConfig(const QString &data)
|
||||
{
|
||||
QMap<QString, QString> configMap;
|
||||
auto configByLines = data.split("\n");
|
||||
@@ -399,9 +415,6 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
||||
}
|
||||
}
|
||||
|
||||
QJsonObject lastConfig;
|
||||
lastConfig[config_key::config] = data;
|
||||
|
||||
auto url { QUrl::fromUserInput(configMap.value("Endpoint")) };
|
||||
QString hostName;
|
||||
QString port;
|
||||
@@ -410,7 +423,7 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
||||
} else {
|
||||
qDebug() << "Key parameter 'Endpoint' is missing or has an invalid format";
|
||||
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
|
||||
return QJsonObject();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (url.port() != -1) {
|
||||
@@ -419,155 +432,182 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
||||
port = protocols::wireguard::defaultPort;
|
||||
}
|
||||
|
||||
lastConfig[config_key::hostName] = hostName;
|
||||
lastConfig[config_key::port] = port.toInt();
|
||||
|
||||
if (!configMap.value("PrivateKey").isEmpty() && !configMap.value("Address").isEmpty() && !configMap.value("PublicKey").isEmpty()) {
|
||||
lastConfig[config_key::client_priv_key] = configMap.value("PrivateKey");
|
||||
lastConfig[config_key::client_ip] = configMap.value("Address");
|
||||
|
||||
if (!configMap.value("PresharedKey").isEmpty()) {
|
||||
lastConfig[config_key::psk_key] = configMap.value("PresharedKey");
|
||||
} else if (!configMap.value("PreSharedKey").isEmpty()) {
|
||||
lastConfig[config_key::psk_key] = configMap.value("PreSharedKey");
|
||||
}
|
||||
|
||||
lastConfig[config_key::server_pub_key] = configMap.value("PublicKey");
|
||||
} else {
|
||||
if (configMap.value("PrivateKey").isEmpty() || configMap.value("Address").isEmpty() || configMap.value("PublicKey").isEmpty()) {
|
||||
qDebug() << "One of the key parameters is missing (PrivateKey, Address, PublicKey)";
|
||||
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
|
||||
return QJsonObject();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!configMap.value("MTU").isEmpty()) {
|
||||
lastConfig[config_key::mtu] = configMap.value("MTU");
|
||||
}
|
||||
|
||||
if (!configMap.value("PersistentKeepalive").isEmpty()) {
|
||||
lastConfig[config_key::persistent_keep_alive] = configMap.value("PersistentKeepalive");
|
||||
}
|
||||
|
||||
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(", "));
|
||||
|
||||
lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;
|
||||
|
||||
QString protocolName = "wireguard";
|
||||
|
||||
const QStringList requiredJunkFields = { config_key::junkPacketCount, config_key::junkPacketMinSize,
|
||||
config_key::junkPacketMaxSize, config_key::initPacketJunkSize,
|
||||
config_key::responsePacketJunkSize, config_key::initPacketMagicHeader,
|
||||
config_key::responsePacketMagicHeader, config_key::underloadPacketMagicHeader,
|
||||
config_key::transportPacketMagicHeader };
|
||||
|
||||
const QStringList optionalJunkFields = { // config_key::cookieReplyPacketJunkSize,
|
||||
// config_key::transportPacketJunkSize,
|
||||
config_key::specialJunk1, config_key::specialJunk2, config_key::specialJunk3,
|
||||
const QStringList optionalJunkFields = { config_key::specialJunk1, config_key::specialJunk2, config_key::specialJunk3,
|
||||
config_key::specialJunk4, config_key::specialJunk5, config_key::controlledJunk1,
|
||||
config_key::controlledJunk2, config_key::controlledJunk3, config_key::specialHandshakeTimeout
|
||||
};
|
||||
|
||||
bool hasAllRequiredFields = std::all_of(requiredJunkFields.begin(), requiredJunkFields.end(),
|
||||
[&configMap](const QString &field) { return !configMap.value(field).isEmpty(); });
|
||||
if (hasAllRequiredFields) {
|
||||
for (const QString &field : requiredJunkFields) {
|
||||
lastConfig[field] = configMap.value(field);
|
||||
}
|
||||
|
||||
for (const QString &field : optionalJunkFields) {
|
||||
if (!configMap.value(field).isEmpty()) {
|
||||
lastConfig[field] = configMap.value(field);
|
||||
}
|
||||
}
|
||||
|
||||
protocolName = "awg";
|
||||
m_configType = ConfigTypes::Awg;
|
||||
}
|
||||
|
||||
if (!configMap.value("MTU").isEmpty()) {
|
||||
lastConfig[config_key::mtu] = configMap.value("MTU");
|
||||
} else {
|
||||
lastConfig[config_key::mtu] = protocolName == "awg" ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
||||
}
|
||||
|
||||
QJsonObject wireguardConfig;
|
||||
wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson());
|
||||
wireguardConfig[config_key::isThirdPartyConfig] = true;
|
||||
wireguardConfig[config_key::port] = port;
|
||||
wireguardConfig[config_key::transport_proto] = "udp";
|
||||
|
||||
QJsonObject containers;
|
||||
containers.insert(config_key::container, QJsonValue("amnezia-" + protocolName));
|
||||
containers.insert(protocolName, QJsonValue(wireguardConfig));
|
||||
|
||||
QJsonArray arr;
|
||||
arr.push_back(containers);
|
||||
|
||||
QJsonObject config;
|
||||
config[config_key::containers] = arr;
|
||||
config[config_key::defaultContainer] = "amnezia-" + protocolName;
|
||||
config[config_key::description] = m_settings->nextAvailableServerName();
|
||||
auto serverConfig = QSharedPointer<SelfHostedServerConfig>::create();
|
||||
serverConfig->hostName = hostName;
|
||||
serverConfig->description = m_settings->nextAvailableServerName();
|
||||
|
||||
const static QRegularExpression dnsRegExp(
|
||||
"DNS = "
|
||||
"(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
|
||||
QRegularExpressionMatch dnsMatch = dnsRegExp.match(data);
|
||||
if (dnsMatch.hasMatch()) {
|
||||
config[config_key::dns1] = dnsMatch.captured(1);
|
||||
config[config_key::dns2] = dnsMatch.captured(2);
|
||||
serverConfig->dns1 = dnsMatch.captured(1);
|
||||
serverConfig->dns2 = dnsMatch.captured(2);
|
||||
}
|
||||
|
||||
config[config_key::hostName] = hostName;
|
||||
ContainerConfig containerConfig;
|
||||
QSharedPointer<ProtocolConfig> protocolConfig;
|
||||
|
||||
return config;
|
||||
if (hasAllRequiredFields) {
|
||||
m_configType = ConfigTypes::Awg;
|
||||
serverConfig->defaultContainer = "amnezia-awg";
|
||||
containerConfig.container = DockerContainer::Awg;
|
||||
|
||||
auto awgConfig = QSharedPointer<AwgProtocolConfig>::create();
|
||||
awgConfig->clientProtocolConfig.nativeConfig = data;
|
||||
awgConfig->clientProtocolConfig.clientPrivateKey = configMap.value("PrivateKey");
|
||||
awgConfig->clientProtocolConfig.clientIp = configMap.value("Address");
|
||||
awgConfig->serverProtocolConfig.serverPublicKey = configMap.value("PublicKey");
|
||||
|
||||
if (!configMap.value("PresharedKey").isEmpty()) {
|
||||
awgConfig->clientProtocolConfig.pskKey = configMap.value("PresharedKey");
|
||||
} else if (!configMap.value("PreSharedKey").isEmpty()) {
|
||||
awgConfig->clientProtocolConfig.pskKey = configMap.value("PreSharedKey");
|
||||
}
|
||||
|
||||
awgConfig->serverProtocolConfig.hostName = hostName;
|
||||
awgConfig->serverProtocolConfig.port = port.toInt();
|
||||
awgConfig->serverProtocolConfig.mtu = configMap.value("MTU").isEmpty() ? protocols::awg::defaultMtu : configMap.value("MTU").toInt();
|
||||
|
||||
if (!configMap.value("PersistentKeepalive").isEmpty()) {
|
||||
awgConfig->clientProtocolConfig.persistentKeepalive = configMap.value("PersistentKeepalive");
|
||||
}
|
||||
|
||||
QStringList allowedIps = configMap.value("AllowedIPs").split(", ");
|
||||
awgConfig->clientProtocolConfig.allowedIps = allowedIps;
|
||||
|
||||
for (const QString &field : requiredJunkFields) {
|
||||
QString value = configMap.value(field);
|
||||
if (field == config_key::junkPacketCount) awgConfig->serverProtocolConfig.junkPacketCount = value;
|
||||
else if (field == config_key::junkPacketMinSize) awgConfig->serverProtocolConfig.junkPacketMinSize = value;
|
||||
else if (field == config_key::junkPacketMaxSize) awgConfig->serverProtocolConfig.junkPacketMaxSize = value;
|
||||
else if (field == config_key::initPacketJunkSize) awgConfig->serverProtocolConfig.initPacketJunkSize = value;
|
||||
else if (field == config_key::responsePacketJunkSize) awgConfig->serverProtocolConfig.responsePacketJunkSize = value;
|
||||
else if (field == config_key::initPacketMagicHeader) awgConfig->serverProtocolConfig.initPacketMagicHeader = value;
|
||||
else if (field == config_key::responsePacketMagicHeader) awgConfig->serverProtocolConfig.responsePacketMagicHeader = value;
|
||||
else if (field == config_key::underloadPacketMagicHeader) awgConfig->serverProtocolConfig.underloadPacketMagicHeader = value;
|
||||
else if (field == config_key::transportPacketMagicHeader) awgConfig->serverProtocolConfig.transportPacketMagicHeader = value;
|
||||
}
|
||||
|
||||
for (const QString &field : optionalJunkFields) {
|
||||
QString value = configMap.value(field);
|
||||
if (!value.isEmpty()) {
|
||||
if (field == config_key::specialJunk1) awgConfig->serverProtocolConfig.specialJunk1 = value;
|
||||
else if (field == config_key::specialJunk2) awgConfig->serverProtocolConfig.specialJunk2 = value;
|
||||
else if (field == config_key::specialJunk3) awgConfig->serverProtocolConfig.specialJunk3 = value;
|
||||
else if (field == config_key::specialJunk4) awgConfig->serverProtocolConfig.specialJunk4 = value;
|
||||
else if (field == config_key::specialJunk5) awgConfig->serverProtocolConfig.specialJunk5 = value;
|
||||
else if (field == config_key::controlledJunk1) awgConfig->serverProtocolConfig.controlledJunk1 = value;
|
||||
else if (field == config_key::controlledJunk2) awgConfig->serverProtocolConfig.controlledJunk2 = value;
|
||||
else if (field == config_key::controlledJunk3) awgConfig->serverProtocolConfig.controlledJunk3 = value;
|
||||
else if (field == config_key::specialHandshakeTimeout) awgConfig->serverProtocolConfig.specialHandshakeTimeout = value;
|
||||
}
|
||||
}
|
||||
|
||||
awgConfig->isThirdPartyConfig = true;
|
||||
protocolConfig = awgConfig;
|
||||
containerConfig.protocolConfigs["awg"] = protocolConfig;
|
||||
} else {
|
||||
serverConfig->defaultContainer = "amnezia-wireguard";
|
||||
containerConfig.container = DockerContainer::WireGuard;
|
||||
|
||||
auto wgConfig = QSharedPointer<WireGuardProtocolConfig>::create();
|
||||
wgConfig->clientProtocolConfig.nativeConfig = data;
|
||||
wgConfig->clientProtocolConfig.clientPrivateKey = configMap.value("PrivateKey");
|
||||
wgConfig->clientProtocolConfig.clientIp = configMap.value("Address");
|
||||
wgConfig->serverProtocolConfig.serverPublicKey = configMap.value("PublicKey");
|
||||
|
||||
if (!configMap.value("PresharedKey").isEmpty()) {
|
||||
wgConfig->clientProtocolConfig.pskKey = configMap.value("PresharedKey");
|
||||
} else if (!configMap.value("PreSharedKey").isEmpty()) {
|
||||
wgConfig->clientProtocolConfig.pskKey = configMap.value("PreSharedKey");
|
||||
}
|
||||
|
||||
wgConfig->serverProtocolConfig.hostName = hostName;
|
||||
wgConfig->serverProtocolConfig.port = port.toInt();
|
||||
wgConfig->serverProtocolConfig.mtu = configMap.value("MTU").isEmpty() ? protocols::wireguard::defaultMtu : configMap.value("MTU").toInt();
|
||||
|
||||
if (!configMap.value("PersistentKeepalive").isEmpty()) {
|
||||
wgConfig->clientProtocolConfig.persistentKeepalive = configMap.value("PersistentKeepalive");
|
||||
}
|
||||
|
||||
QStringList allowedIps = configMap.value("AllowedIPs").split(", ");
|
||||
wgConfig->clientProtocolConfig.allowedIps = allowedIps;
|
||||
|
||||
wgConfig->isThirdPartyConfig = true;
|
||||
protocolConfig = wgConfig;
|
||||
containerConfig.protocolConfigs["wireguard"] = protocolConfig;
|
||||
}
|
||||
|
||||
serverConfig->containerConfigs[serverConfig->defaultContainer] = containerConfig;
|
||||
|
||||
return serverConfig;
|
||||
}
|
||||
|
||||
QJsonObject ImportController::extractXrayConfig(const QString &data, const QString &description)
|
||||
QSharedPointer<ServerConfig> ImportController::extractXrayConfig(const QString &data, const QString &description)
|
||||
{
|
||||
QJsonParseError parserErr;
|
||||
QJsonDocument jsonConf = QJsonDocument::fromJson(data.toLocal8Bit(), &parserErr);
|
||||
|
||||
QJsonObject xrayVpnConfig;
|
||||
xrayVpnConfig[config_key::config] = jsonConf.toJson().constData();
|
||||
QJsonObject lastConfig;
|
||||
lastConfig[config_key::last_config] = jsonConf.toJson().constData();
|
||||
lastConfig[config_key::isThirdPartyConfig] = true;
|
||||
|
||||
QJsonObject containers;
|
||||
if (m_configType == ConfigTypes::ShadowSocks) {
|
||||
containers.insert(config_key::ssxray, QJsonValue(lastConfig));
|
||||
containers.insert(config_key::container, QJsonValue("amnezia-ssxray"));
|
||||
} else {
|
||||
containers.insert(config_key::container, QJsonValue("amnezia-xray"));
|
||||
containers.insert(config_key::xray, QJsonValue(lastConfig));
|
||||
}
|
||||
|
||||
QJsonArray arr;
|
||||
arr.push_back(containers);
|
||||
|
||||
QString hostName;
|
||||
|
||||
const static QRegularExpression hostNameRegExp("\"address\":\\s*\"([^\"]+)");
|
||||
QRegularExpressionMatch hostNameMatch = hostNameRegExp.match(data);
|
||||
if (hostNameMatch.hasMatch()) {
|
||||
hostName = hostNameMatch.captured(1);
|
||||
}
|
||||
|
||||
QJsonObject config;
|
||||
config[config_key::containers] = arr;
|
||||
auto serverConfig = QSharedPointer<SelfHostedServerConfig>::create();
|
||||
serverConfig->hostName = hostName;
|
||||
serverConfig->description = description.isEmpty() ? m_settings->nextAvailableServerName() : description;
|
||||
|
||||
ContainerConfig containerConfig;
|
||||
QSharedPointer<ProtocolConfig> protocolConfig;
|
||||
|
||||
if (m_configType == ConfigTypes::ShadowSocks) {
|
||||
config[config_key::defaultContainer] = "amnezia-ssxray";
|
||||
} else {
|
||||
config[config_key::defaultContainer] = "amnezia-xray";
|
||||
}
|
||||
if (description.isEmpty()) {
|
||||
config[config_key::description] = m_settings->nextAvailableServerName();
|
||||
} else {
|
||||
config[config_key::description] = description;
|
||||
}
|
||||
config[config_key::hostName] = hostName;
|
||||
serverConfig->defaultContainer = "amnezia-ssxray";
|
||||
containerConfig.container = DockerContainer::ShadowSocks;
|
||||
|
||||
return config;
|
||||
auto shadowsocksConfig = QSharedPointer<ShadowsocksProtocolConfig>::create();
|
||||
shadowsocksConfig->clientProtocolConfig.nativeConfig = data;
|
||||
shadowsocksConfig->isThirdPartyConfig = true;
|
||||
|
||||
protocolConfig = shadowsocksConfig;
|
||||
containerConfig.protocolConfigs["ssxray"] = protocolConfig;
|
||||
} else {
|
||||
serverConfig->defaultContainer = "amnezia-xray";
|
||||
containerConfig.container = DockerContainer::Xray;
|
||||
|
||||
auto xrayConfig = QSharedPointer<XrayProtocolConfig>::create();
|
||||
xrayConfig->clientProtocolConfig.nativeConfig = data;
|
||||
xrayConfig->isThirdPartyConfig = true;
|
||||
|
||||
protocolConfig = xrayConfig;
|
||||
containerConfig.protocolConfigs["xray"] = protocolConfig;
|
||||
}
|
||||
|
||||
serverConfig->containerConfigs[serverConfig->defaultContainer] = containerConfig;
|
||||
|
||||
return serverConfig;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
@@ -677,20 +717,41 @@ QString ImportController::getQrCodeScanProgressString()
|
||||
}
|
||||
#endif
|
||||
|
||||
void ImportController::checkForMaliciousStrings(const QJsonObject &serverConfig)
|
||||
void ImportController::checkForMaliciousStrings(const QSharedPointer<ServerConfig> &serverConfig)
|
||||
{
|
||||
const QJsonArray &containers = serverConfig[config_key::containers].toArray();
|
||||
for (const QJsonValue &container : containers) {
|
||||
auto containerConfig = container.toObject();
|
||||
auto containerName = containerConfig[config_key::container].toString();
|
||||
if ((containerName == ContainerProps::containerToString(DockerContainer::OpenVpn))
|
||||
|| (containerName == ContainerProps::containerToString(DockerContainer::Cloak))
|
||||
|| (containerName == ContainerProps::containerToString(DockerContainer::ShadowSocks))) {
|
||||
if (!serverConfig) return;
|
||||
|
||||
auto selfHostedConfig = qSharedPointerCast<SelfHostedServerConfig>(serverConfig);
|
||||
if (!selfHostedConfig) return;
|
||||
|
||||
QString protocolConfig =
|
||||
containerConfig[ProtocolProps::protoToString(Proto::OpenVpn)].toObject()[config_key::last_config].toString();
|
||||
QString protocolConfigJson = QJsonDocument::fromJson(protocolConfig.toUtf8()).object()[config_key::config].toString();
|
||||
for (const auto &containerEntry : selfHostedConfig->containerConfigs) {
|
||||
const ContainerConfig &containerConfig = containerEntry.second;
|
||||
|
||||
if (containerConfig.container == DockerContainer::OpenVpn ||
|
||||
containerConfig.container == DockerContainer::Cloak ||
|
||||
containerConfig.container == DockerContainer::ShadowSocks) {
|
||||
|
||||
QString protocolConfigJson;
|
||||
|
||||
for (const auto &protocolEntry : containerConfig.protocolConfigs) {
|
||||
auto protocolConfig = protocolEntry.second;
|
||||
ProtocolConfigVariant variant = ProtocolConfig::getProtocolConfigVariant(protocolConfig);
|
||||
|
||||
std::visit([&protocolConfigJson](const auto &config) -> void {
|
||||
using ConfigType = std::decay_t<decltype(*config)>;
|
||||
if constexpr (std::is_same_v<ConfigType, OpenVpnProtocolConfig> ||
|
||||
std::is_same_v<ConfigType, CloakProtocolConfig> ||
|
||||
std::is_same_v<ConfigType, ShadowsocksProtocolConfig>) {
|
||||
protocolConfigJson = config->clientProtocolConfig.nativeConfig;
|
||||
}
|
||||
}, variant);
|
||||
|
||||
if (!protocolConfigJson.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!protocolConfigJson.isEmpty()) {
|
||||
// https://github.com/OpenVPN/openvpn/blob/master/doc/man-sections/script-options.rst
|
||||
QStringList dangerousTags {
|
||||
"up", "tls-verify", "ipchange", "client-connect", "route-up", "route-pre-down", "client-disconnect", "down", "learn-address", "auth-user-pass-verify"
|
||||
@@ -715,34 +776,39 @@ void ImportController::checkForMaliciousStrings(const QJsonObject &serverConfig)
|
||||
m_maliciousWarningText.push_back(tr("<br>In the imported configuration, potentially dangerous lines were found:"));
|
||||
for (const auto &string : maliciousStrings) {
|
||||
m_maliciousWarningText.push_back(QString("<br><i>%1</i>").arg(string));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImportController::processAmneziaConfig(QJsonObject &config)
|
||||
void ImportController::processAmneziaConfig(QSharedPointer<ServerConfig> &config)
|
||||
{
|
||||
auto containers = config.value(config_key::containers).toArray();
|
||||
for (auto i = 0; i < containers.size(); i++) {
|
||||
auto container = containers.at(i).toObject();
|
||||
auto dockerContainer = ContainerProps::containerFromString(container.value(config_key::container).toString());
|
||||
if (!config) return;
|
||||
|
||||
auto selfHostedConfig = qSharedPointerCast<SelfHostedServerConfig>(config);
|
||||
if (!selfHostedConfig) return;
|
||||
|
||||
for (auto &containerEntry : selfHostedConfig->containerConfigs) {
|
||||
QString containerName = containerEntry.first;
|
||||
ContainerConfig &containerConfig = containerEntry.second;
|
||||
|
||||
DockerContainer dockerContainer = ContainerProps::containerFromString(containerName);
|
||||
if (dockerContainer == DockerContainer::Awg || dockerContainer == DockerContainer::WireGuard) {
|
||||
auto containerConfig = container.value(ContainerProps::containerTypeToString(dockerContainer)).toObject();
|
||||
auto protocolConfig = containerConfig.value(config_key::last_config).toString();
|
||||
if (protocolConfig.isEmpty()) {
|
||||
return;
|
||||
QString protocolName = ContainerProps::containerTypeToString(dockerContainer);
|
||||
if (containerConfig.protocolConfigs.contains(protocolName)) {
|
||||
auto protocolConfig = containerConfig.protocolConfigs.value(protocolName);
|
||||
|
||||
if (auto wgConfig = qSharedPointerCast<WireGuardProtocolConfig>(protocolConfig)) {
|
||||
wgConfig->serverProtocolConfig.mtu =
|
||||
dockerContainer == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
||||
} else if (auto awgConfig = qSharedPointerCast<AwgProtocolConfig>(protocolConfig)) {
|
||||
awgConfig->serverProtocolConfig.mtu =
|
||||
dockerContainer == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
||||
}
|
||||
}
|
||||
|
||||
QJsonObject jsonConfig = QJsonDocument::fromJson(protocolConfig.toUtf8()).object();
|
||||
jsonConfig[config_key::mtu] =
|
||||
dockerContainer == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
||||
|
||||
containerConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
||||
|
||||
container[ContainerProps::containerTypeToString(dockerContainer)] = containerConfig;
|
||||
containers.replace(i, container);
|
||||
config.insert(config_key::containers, containers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "ui/models/containers_model.h"
|
||||
#include "ui/models/servers_model.h"
|
||||
#include "core/models/servers/serverConfig.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -61,13 +62,13 @@ signals:
|
||||
void restoreAppConfig(const QByteArray &data);
|
||||
|
||||
private:
|
||||
QJsonObject extractOpenVpnConfig(const QString &data);
|
||||
QJsonObject extractWireGuardConfig(const QString &data);
|
||||
QJsonObject extractXrayConfig(const QString &data, const QString &description = "");
|
||||
QSharedPointer<ServerConfig> extractOpenVpnConfig(const QString &data);
|
||||
QSharedPointer<ServerConfig> extractWireGuardConfig(const QString &data);
|
||||
QSharedPointer<ServerConfig> extractXrayConfig(const QString &data, const QString &description = "");
|
||||
|
||||
void checkForMaliciousStrings(const QJsonObject &protocolConfig);
|
||||
void checkForMaliciousStrings(const QSharedPointer<ServerConfig> &serverConfig);
|
||||
|
||||
void processAmneziaConfig(QJsonObject &config);
|
||||
void processAmneziaConfig(QSharedPointer<ServerConfig> &config);
|
||||
|
||||
#if defined Q_OS_ANDROID || defined Q_OS_IOS
|
||||
void stopDecodingQr();
|
||||
@@ -77,7 +78,7 @@ private:
|
||||
QSharedPointer<ContainersModel> m_containersModel;
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
|
||||
QJsonObject m_config;
|
||||
QSharedPointer<ServerConfig> m_config;
|
||||
QString m_configFileName;
|
||||
ConfigTypes m_configType;
|
||||
QString m_maliciousWarningText;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "core/controllers/vpnConfigurationController.h"
|
||||
#include "core/controllers/selfhosted/exportController.h"
|
||||
#include "core/models/containers/containers_defs.h"
|
||||
#include "core/qrCodeUtils.h"
|
||||
#include "systemController.h"
|
||||
|
||||
@@ -32,7 +33,7 @@ void ExportUIController::generateFullAccessConfig()
|
||||
clearPreviousConfig();
|
||||
|
||||
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||
QJsonObject serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||
|
||||
auto result = m_coreExportController->generateFullAccessConfig(serverConfig);
|
||||
|
||||
@@ -55,9 +56,12 @@ void ExportUIController::generateConnectionConfig(const QString &clientName)
|
||||
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getProcessedContainerIndex());
|
||||
QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
|
||||
QJsonObject serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||
auto dnsSettings = m_serversModel->getDnsPair(serverIndex);
|
||||
|
||||
// Get the container config from the server config instead of the containers model
|
||||
QString containerName = ContainerProps::containerToString(container);
|
||||
ContainerConfig containerConfig = serverConfig->containerConfigs.value(containerName);
|
||||
|
||||
auto result = m_coreExportController->generateConnectionConfig(clientName, credentials, container,
|
||||
containerConfig, serverConfig, dnsSettings);
|
||||
|
||||
@@ -40,41 +40,39 @@ ClientManagementModel::ClientManagementModel(QSharedPointer<ClientManagementCont
|
||||
int ClientManagementModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return static_cast<int>(m_clientsTable.size());
|
||||
return static_cast<int>(m_clientsList.size());
|
||||
}
|
||||
|
||||
QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(m_clientsTable.size())) {
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(m_clientsList.size())) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
auto client = m_clientsTable.at(index.row()).toObject();
|
||||
auto userData = client.value(configKey::userData).toObject();
|
||||
const ClientInfo &client = m_clientsList.at(index.row());
|
||||
|
||||
switch (role) {
|
||||
case ClientNameRole: return userData.value(configKey::clientName).toString();
|
||||
case CreationDateRole: return userData.value(configKey::creationDate).toString();
|
||||
case LatestHandshakeRole: return userData.value(configKey::latestHandshake).toString();
|
||||
case DataReceivedRole: return userData.value(configKey::dataReceived).toString();
|
||||
case DataSentRole: return userData.value(configKey::dataSent).toString();
|
||||
case AllowedIpsRole: return userData.value(configKey::allowedIps).toString();
|
||||
case ClientNameRole: return client.clientName;
|
||||
case CreationDateRole: return client.creationDate.toString();
|
||||
case LatestHandshakeRole: return client.latestHandshake;
|
||||
case DataReceivedRole: return client.dataReceived;
|
||||
case DataSentRole: return client.dataSent;
|
||||
case AllowedIpsRole: return client.allowedIps;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ClientManagementModel::onClientsDataUpdated(const QJsonArray &clientsTable)
|
||||
void ClientManagementModel::onClientsDataUpdated(const QList<ClientInfo> &clientsList)
|
||||
{
|
||||
beginResetModel();
|
||||
m_clientsTable = clientsTable;
|
||||
m_clientsList = clientsList;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ClientManagementModel::onClientRenamed(const int row, const QString &newName)
|
||||
{
|
||||
Q_UNUSED(newName)
|
||||
if (row >= 0 && row < m_clientsTable.size()) {
|
||||
if (row >= 0 && row < m_clientsList.size()) {
|
||||
emit dataChanged(index(row, 0), index(row, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
#define CLIENTMANAGEMENTMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QJsonArray>
|
||||
#include <QList>
|
||||
|
||||
#include "core/controllers/selfhosted/clientManagementController.h"
|
||||
#include "core/models/clientInfo.h"
|
||||
|
||||
class ClientManagementModel : public QAbstractListModel
|
||||
{
|
||||
@@ -33,11 +34,11 @@ signals:
|
||||
void adminConfigRevoked(const DockerContainer container);
|
||||
|
||||
private slots:
|
||||
void onClientsDataUpdated(const QJsonArray &clientsTable);
|
||||
void onClientsDataUpdated(const QList<ClientInfo> &clientsList);
|
||||
void onClientRenamed(const int row, const QString &newName);
|
||||
|
||||
private:
|
||||
QJsonArray m_clientsTable;
|
||||
QList<ClientInfo> m_clientsList;
|
||||
QSharedPointer<ClientManagementController> m_clientManagementController;
|
||||
};
|
||||
|
||||
|
||||
@@ -639,49 +639,7 @@ bool ServersModel::setProcessedServerData(const QString &roleString, const QVari
|
||||
|
||||
bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling()
|
||||
{
|
||||
auto serverConfig = m_servers1.at(m_defaultServerIndex);
|
||||
auto defaultContainer = ContainerProps::containerFromString(serverConfig->defaultContainer);
|
||||
|
||||
for (const auto &container : serverConfig->containerConfigs) {
|
||||
if (container.containerName != serverConfig->defaultContainer) {
|
||||
continue;
|
||||
}
|
||||
if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::WireGuard) {
|
||||
auto protocolConfigVariant = ProtocolConfig::getProtocolConfigVariant(container.protocolConfigs[serverConfig->defaultContainer]);
|
||||
return std::visit(
|
||||
[](const auto &ptr) -> bool {
|
||||
if constexpr (requires {
|
||||
ptr->clientProtocolConfig;
|
||||
ptr->clientProtocolConfig.wireGuardData;
|
||||
}) {
|
||||
const auto nativeConfig = ptr->clientProtocolConfig.nativeConfig;
|
||||
const auto allowedIps = ptr->clientProtocolConfig.wireGuardData.allowedIps;
|
||||
|
||||
return (nativeConfig.contains("AllowedIPs") && !nativeConfig.contains("AllowedIPs = 0.0.0.0/0, ::/0"))
|
||||
|| (!allowedIps.isEmpty() && !allowedIps.contains("0.0.0.0/0"));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
protocolConfigVariant);
|
||||
} else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn
|
||||
|| defaultContainer == DockerContainer::ShadowSocks) {
|
||||
auto protocolConfigVariant = ProtocolConfig::getProtocolConfigVariant(
|
||||
container.protocolConfigs[ContainerProps::containerTypeToString(DockerContainer::OpenVpn)]);
|
||||
return std::visit(
|
||||
[](const auto &ptr) -> bool {
|
||||
if constexpr (requires { ptr->clientProtocolConfig; }) {
|
||||
const auto nativeConfig = ptr->clientProtocolConfig.nativeConfig;
|
||||
|
||||
return (!nativeConfig.isEmpty() && !nativeConfig.contains("redirect-gateway"));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
protocolConfigVariant);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return m_serverConfigController->isDefaultServerDefaultContainerHasSplitTunneling();
|
||||
}
|
||||
|
||||
bool ServersModel::isServerFromApi(const int serverIndex)
|
||||
|
||||
Reference in New Issue
Block a user