mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-21 02:01:03 +07:00
refactor: refactor the application to the mvvm architecture (#2009)
* refactor: move business logic from servers model * refactor: move containersModel initialization * refactor: added protocol ui controller and removed settings class from protocols model * refactor: moved cli management to separate controller * refactor: moved app split to separate controller * refactor: moved site split to separate controller * refactor: moved allowed dns to separate controller * refactor: moved language logic to separate ui controller * refactor: removed Settings from devices model * refactor: moved configs and services api logit to separate core controller * refactor: added a layer with a repository between the storage and controllers * refactor: use child parent system instead of smart pointers for controllers and models initialization * refactor: moved install functions from server controller to install controller * refactor: install controller refactoring * chore: renamed exportController to exportUiController * refactor: separate export controller * refactor: removed VpnConfigurationsController * chore: renamed ServerController to SshSession * refactor: replaced ServerController to SshSession * chore: moved qml controllers to separate folder * chore: include fixes * chore: moved utils from core root to core/utils * chore: include fixes * chore: rename core/utils files to camelCase foramt * chore: include fixes * chore: moved some utils to api and selfhosted folders * chore: include fixes * chore: remove unused file * chore: moved serialization folder to core/utils * chore: include fixes * chore: moved some files from client root to core/utils * chore: include fixes * chore: moved ui utils to ui/utils folder * chore: include fixes * chore: move utils from root to ui/utils * chore: include fixes * chore: moved configurators to core/configurators * chore: include fixes * refactor: moved iap logic from ui controller to core * refactor: moved remaining core logic from ApiConfigsController to SubscriptionController * chore: rename apiNewsController to apiNewsUiController * refactor: moved core logic from news ui controller to core * chore: renamed apiConfigsController to subscriptionUiController * chore: include fixes * refactor: merge ApiSettingsController with SubscriptionUiController * chore: moved ui selfhosted controllers to separate folder * chore: include fixes * chore: rename connectionController to connectiomUiController * refactor: moved core logic from connectionUiController * chore: rename settingsController to settingsUiController * refactor: move core logic from settingsUiController * refactor: moved core controller signal/slot connections to separate class * fix: newsController fixes after refactoring * chore: rename model to camelCase * chore: include fixes * chore: remove unused code * chore: move selfhosted core to separate folder * chore: include fixes * chore: rename importController to importUiController * refactor: move core logic from importUiController * chore: minor fixes * chore: remove prem v1 migration * refactor: remove openvpn over cloak and openvpn over shadowsocks * refactor: removed protocolsForContainer function * refactor: add core models * refactor: replace json with c++ structs for server config * refactor: move getDnsPair to ServerConfigUtils * feat: add admin selfhosted config export test * feat: add multi import test * refactor: use coreController for tests * feat: add few simple tests * chore: qrepos in all core controllers * feat: add test for settings * refactor: remove repo dependency from configurators * chore: moved protocols to core folder * chore: include fixes * refactor: moved containersDefs, defs, apiDefs, protocolsDefs to different places * chore: include fixes * chore: build fixes * chore: build fixes * refactor: remove q repo and interface repo * feat: add test for ui servers model and controller * chore: renamed to camelCase * chore: include fixes * refactor: moved core logic from sites ui controller * fix: fixed api config processing * fix: fixed processed server index processing * refactor: protocol models now use c++ structs instead of json configs * refactor: servers model now use c++ struct instead of json config * fix: fixed default server index processing * fix: fix logs init * fix: fix secure settings load keys * chore: build fixes * fix: fixed clear settings * fix: fixed restore backup * fix: sshSession usage * fix: fixed export functions signatures * fix: return missing part from buildContainerWorker * fix: fixed server description on page home * refactor: add container config helpers functions * refactor: c++ structs instead of json * chore: add dns protocol config struct * refactor: move config utils functions to config structs * feat: add test for selfhosted server setup * refactor: separate resources.qrc * fix: fixed server rename * chore: return nameOverriddenByUser * fix: build fixes * fix: fixed models init * refactor: cleanup models usage * fix: fixed models init * chore: cleanup connections and functions signatures * chore: cleanup updateModel calls * feat: added cache to servers repo * chore: cleanup unused functions * chore: ssxray processing * chore: remove transportProtoWithDefault and portWithDefault functions * chore: removed proto types any and l2tp * refactor: moved some constants * fix: fixed native configs export * refactor: remove json from processConfigWith functions * fix: fixed processed server index usage * fix: qml warning fixes * chore: merge fixes * chore: update tests * fix: fixed xray config processing * fix: fixed split tunneling processing * chore: rename sites controllers and model * chore: rename fixes * chore: minor fixes * chore: remove ability to load backup from "file with connection settings" button * fix: fixed api device revoke * fix: remove full model update when renaming a user * fix: fixed premium/free server rename * fix: fixed selfhosted new server install * fix: fixed updateContainer function * fix: fixed revoke for external premium configs * feat: add native configs qr processing * chore: codestyle fixes * fix: fixed admin config create * chore: again remove ability to load backup from "file with connection settings" button * chore: minor fixes * fix: fixed variables initialization * fix: fixed qml imports * fix: minor fixes * fix: fix vpnConnection function calls * feat: add buckup error handling * fix: fixed admin config revok * fix: fixed selfhosted awg installation * fix: ad visability * feat: add empty check for primary dns * chore: minor fixes
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
#include "scriptsRegistry.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QLoggingCategory>
|
||||
#include "core/utils/networkUtilities.h"
|
||||
#include "core/utils/containerEnum.h"
|
||||
#include "core/utils/containers/containerUtils.h"
|
||||
#include "core/utils/protocolEnum.h"
|
||||
#include "core/utils/protocolEnum.h"
|
||||
#include "core/protocols/protocolUtils.h"
|
||||
#include "core/utils/constants/configKeys.h"
|
||||
#include "core/utils/constants/protocolConstants.h"
|
||||
#include "core/models/containerConfig.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/sftpProtocolConfig.h"
|
||||
#include "core/models/protocols/socks5ProxyProtocolConfig.h"
|
||||
|
||||
using namespace amnezia;
|
||||
using namespace ProtocolUtils;
|
||||
|
||||
QString amnezia::scriptFolder(amnezia::DockerContainer container)
|
||||
{
|
||||
switch (container) {
|
||||
case DockerContainer::OpenVpn: return QLatin1String("openvpn");
|
||||
case DockerContainer::WireGuard: return QLatin1String("wireguard");
|
||||
case DockerContainer::Awg2: return QLatin1String("awg");
|
||||
case DockerContainer::Awg: return QLatin1String("awg_legacy");
|
||||
case DockerContainer::Ipsec: return QLatin1String("ipsec");
|
||||
case DockerContainer::Xray: return QLatin1String("xray");
|
||||
|
||||
case DockerContainer::TorWebSite: return QLatin1String("website_tor");
|
||||
case DockerContainer::Dns: return QLatin1String("dns");
|
||||
case DockerContainer::Sftp: return QLatin1String("sftp");
|
||||
case DockerContainer::Socks5Proxy: return QLatin1String("socks5_proxy");
|
||||
default: return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QString amnezia::scriptName(SharedScriptType type)
|
||||
{
|
||||
switch (type) {
|
||||
case SharedScriptType::prepare_host: return QLatin1String("prepare_host.sh");
|
||||
case SharedScriptType::install_docker: return QLatin1String("install_docker.sh");
|
||||
case SharedScriptType::build_container: return QLatin1String("build_container.sh");
|
||||
case SharedScriptType::remove_container: return QLatin1String("remove_container.sh");
|
||||
case SharedScriptType::remove_all_containers: return QLatin1String("remove_all_containers.sh");
|
||||
case SharedScriptType::setup_host_firewall: return QLatin1String("setup_host_firewall.sh");
|
||||
case SharedScriptType::check_connection: return QLatin1String("check_connection.sh");
|
||||
case SharedScriptType::check_server_is_busy: return QLatin1String("check_server_is_busy.sh");
|
||||
case SharedScriptType::check_user_in_sudo: return QLatin1String("check_user_in_sudo.sh");
|
||||
default: return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QString amnezia::scriptName(ProtocolScriptType type)
|
||||
{
|
||||
switch (type) {
|
||||
case ProtocolScriptType::dockerfile: return QLatin1String("Dockerfile");
|
||||
case ProtocolScriptType::run_container: return QLatin1String("run_container.sh");
|
||||
case ProtocolScriptType::configure_container: return QLatin1String("configure_container.sh");
|
||||
case ProtocolScriptType::container_startup: return QLatin1String("start.sh");
|
||||
case ProtocolScriptType::openvpn_template: return QLatin1String("template.ovpn");
|
||||
case ProtocolScriptType::wireguard_template: return QLatin1String("template.conf");
|
||||
case ProtocolScriptType::awg_template: return QLatin1String("template.conf");
|
||||
case ProtocolScriptType::xray_template: return QLatin1String("template.json");
|
||||
default: return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QString amnezia::scriptData(amnezia::SharedScriptType type)
|
||||
{
|
||||
QString fileName = QString(":/server_scripts/%1").arg(amnezia::scriptName(type));
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qDebug() << "Warning: script missing" << fileName;
|
||||
return "";
|
||||
}
|
||||
QByteArray ba = file.readAll();
|
||||
if (ba.isEmpty()) {
|
||||
qDebug() << "Warning: script is empty" << fileName;
|
||||
}
|
||||
return ba;
|
||||
}
|
||||
|
||||
QString amnezia::scriptData(amnezia::ProtocolScriptType type, DockerContainer container)
|
||||
{
|
||||
QString fileName = QString(":/server_scripts/%1/%2").arg(amnezia::scriptFolder(container), amnezia::scriptName(type));
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qDebug() << "Warning: script missing" << fileName;
|
||||
return "";
|
||||
}
|
||||
QByteArray data = file.readAll();
|
||||
data.replace("\r", "");
|
||||
return data;
|
||||
}
|
||||
|
||||
amnezia::ScriptVars amnezia::genBaseVars(const ServerCredentials &credentials,
|
||||
DockerContainer container,
|
||||
const QString &primaryDns,
|
||||
const QString &secondaryDns)
|
||||
{
|
||||
ScriptVars vars;
|
||||
|
||||
vars.append({ { "$REMOTE_HOST", credentials.hostName } });
|
||||
vars.append({ { "$CONTAINER_NAME", ContainerUtils::containerToString(container) } });
|
||||
vars.append({ { "$DOCKERFILE_FOLDER", "/opt/amnezia/" + ContainerUtils::containerToString(container) } });
|
||||
|
||||
QString serverIp = (!ContainerUtils::isAwgContainer(container) && container != DockerContainer::WireGuard && container != DockerContainer::Xray)
|
||||
? NetworkUtilities::getIPAddress(credentials.hostName)
|
||||
: credentials.hostName;
|
||||
if (!serverIp.isEmpty()) {
|
||||
vars.append({ { "$SERVER_IP_ADDRESS", serverIp } });
|
||||
} else {
|
||||
qWarning() << "amnezia::genBaseVars unable to resolve address for credentials.hostName";
|
||||
}
|
||||
|
||||
QString dns1 = primaryDns.isEmpty() ? QString("8.8.8.8") : primaryDns;
|
||||
QString dns2 = secondaryDns.isEmpty() ? QString("8.8.4.4") : secondaryDns;
|
||||
vars.append({ { "$PRIMARY_SERVER_DNS", dns1 } });
|
||||
vars.append({ { "$SECONDARY_SERVER_DNS", dns2 } });
|
||||
|
||||
// IPsec vars (constants)
|
||||
vars.append({ { "$IPSEC_VPN_L2TP_NET", "192.168.42.0/24" } });
|
||||
vars.append({ { "$IPSEC_VPN_L2TP_POOL", "192.168.42.10-192.168.42.250" } });
|
||||
vars.append({ { "$IPSEC_VPN_L2TP_LOCAL", "192.168.42.1" } });
|
||||
vars.append({ { "$IPSEC_VPN_XAUTH_NET", "192.168.43.0/24" } });
|
||||
vars.append({ { "$IPSEC_VPN_XAUTH_POOL", "192.168.43.10-192.168.43.250" } });
|
||||
vars.append({ { "$IPSEC_VPN_SHA2_TRUNCBUG", "yes" } });
|
||||
vars.append({ { "$IPSEC_VPN_VPN_ANDROID_MTU_FIX", "yes" } });
|
||||
vars.append({ { "$IPSEC_VPN_DISABLE_IKEV2", "no" } });
|
||||
vars.append({ { "$IPSEC_VPN_DISABLE_L2TP", "no" } });
|
||||
vars.append({ { "$IPSEC_VPN_DISABLE_XAUTH", "no" } });
|
||||
vars.append({ { "$IPSEC_VPN_C2C_TRAFFIC", "no" } });
|
||||
|
||||
return vars;
|
||||
}
|
||||
|
||||
amnezia::ScriptVars amnezia::genOpenVpnVars(const ContainerConfig &containerConfig)
|
||||
{
|
||||
ScriptVars vars;
|
||||
|
||||
if (auto* openVpnProtocolConfig = containerConfig.getOpenVpnProtocolConfig()) {
|
||||
const OpenVpnServerConfig& config = openVpnProtocolConfig->serverConfig;
|
||||
|
||||
vars.append({ { "$OPENVPN_SUBNET_IP", config.subnetAddress.isEmpty() ? protocols::openvpn::defaultSubnetAddress : config.subnetAddress } });
|
||||
vars.append({ { "$OPENVPN_SUBNET_CIDR", config.subnetCidr.isEmpty() ? protocols::openvpn::defaultSubnetCidr : config.subnetCidr } });
|
||||
vars.append({ { "$OPENVPN_SUBNET_MASK", config.subnetMask.isEmpty() ? protocols::openvpn::defaultSubnetMask : config.subnetMask } });
|
||||
vars.append({ { "$OPENVPN_PORT", config.port.isEmpty() ? protocols::openvpn::defaultPort : config.port } });
|
||||
vars.append({ { "$OPENVPN_TRANSPORT_PROTO", config.transportProto.isEmpty() ? protocols::openvpn::defaultTransportProto : config.transportProto } });
|
||||
|
||||
vars.append({ { "$OPENVPN_NCP_DISABLE", config.ncpDisable ? protocols::openvpn::ncpDisableString : "" } });
|
||||
vars.append({ { "$OPENVPN_CIPHER", config.cipher.isEmpty() ? protocols::openvpn::defaultCipher : config.cipher } });
|
||||
vars.append({ { "$OPENVPN_HASH", config.hash.isEmpty() ? protocols::openvpn::defaultHash : config.hash } });
|
||||
|
||||
vars.append({ { "$OPENVPN_TLS_AUTH", config.tlsAuth ? protocols::openvpn::tlsAuthString : "" } });
|
||||
if (!config.tlsAuth) {
|
||||
vars.append({ { "$OPENVPN_TA_KEY", "" } });
|
||||
}
|
||||
|
||||
vars.append({ { "$OPENVPN_ADDITIONAL_CLIENT_CONFIG", config.additionalClientConfig.isEmpty() ? protocols::openvpn::defaultAdditionalClientConfig : config.additionalClientConfig } });
|
||||
vars.append({ { "$OPENVPN_ADDITIONAL_SERVER_CONFIG", config.additionalServerConfig.isEmpty() ? protocols::openvpn::defaultAdditionalServerConfig : config.additionalServerConfig } });
|
||||
}
|
||||
|
||||
return vars;
|
||||
}
|
||||
|
||||
amnezia::ScriptVars amnezia::genXrayVars(const ContainerConfig &containerConfig)
|
||||
{
|
||||
ScriptVars vars;
|
||||
|
||||
if (auto* xrayProtocolConfig = containerConfig.getXrayProtocolConfig()) {
|
||||
const XrayServerConfig& config = xrayProtocolConfig->serverConfig;
|
||||
|
||||
vars.append({ { "$XRAY_SITE_NAME", config.site.isEmpty() ? protocols::xray::defaultSite : config.site } });
|
||||
vars.append({ { "$XRAY_SERVER_PORT", config.port.isEmpty() ? protocols::xray::defaultPort : config.port } });
|
||||
}
|
||||
|
||||
return vars;
|
||||
}
|
||||
|
||||
amnezia::ScriptVars amnezia::genWireGuardVars(const ContainerConfig &containerConfig)
|
||||
{
|
||||
ScriptVars vars;
|
||||
|
||||
if (auto* wireGuardProtocolConfig = containerConfig.getWireGuardProtocolConfig()) {
|
||||
const WireGuardServerConfig& config = wireGuardProtocolConfig->serverConfig;
|
||||
|
||||
vars.append({ { "$WIREGUARD_SUBNET_IP", config.subnetAddress.isEmpty() ? protocols::wireguard::defaultSubnetAddress : config.subnetAddress } });
|
||||
vars.append({ { "$WIREGUARD_SUBNET_CIDR", config.subnetCidr.isEmpty() ? protocols::wireguard::defaultSubnetCidr : config.subnetCidr } });
|
||||
vars.append({ { "$WIREGUARD_SERVER_PORT", config.port.isEmpty() ? protocols::wireguard::defaultPort : config.port } });
|
||||
}
|
||||
|
||||
return vars;
|
||||
}
|
||||
|
||||
amnezia::ScriptVars amnezia::genAwgVars(const ContainerConfig &containerConfig)
|
||||
{
|
||||
ScriptVars vars;
|
||||
|
||||
if (auto* awgProtocolConfig = containerConfig.getAwgProtocolConfig()) {
|
||||
const AwgServerConfig& config = awgProtocolConfig->serverConfig;
|
||||
|
||||
vars.append({ { "$AWG_SUBNET_IP", config.subnetAddress.isEmpty() ? protocols::wireguard::defaultSubnetAddress : config.subnetAddress } });
|
||||
vars.append({ { "$WIREGUARD_SUBNET_CIDR", config.subnetCidr.isEmpty() ? protocols::wireguard::defaultSubnetCidr : config.subnetCidr } });
|
||||
vars.append({ { "$AWG_SERVER_PORT", config.port.isEmpty() ? protocols::awg::defaultPort : config.port } });
|
||||
vars.append({ { "$JUNK_PACKET_COUNT", config.junkPacketCount } });
|
||||
vars.append({ { "$JUNK_PACKET_MIN_SIZE", config.junkPacketMinSize } });
|
||||
vars.append({ { "$JUNK_PACKET_MAX_SIZE", config.junkPacketMaxSize } });
|
||||
vars.append({ { "$INIT_PACKET_JUNK_SIZE", config.initPacketJunkSize } });
|
||||
vars.append({ { "$RESPONSE_PACKET_JUNK_SIZE", config.responsePacketJunkSize } });
|
||||
vars.append({ { "$INIT_PACKET_MAGIC_HEADER", config.initPacketMagicHeader } });
|
||||
vars.append({ { "$RESPONSE_PACKET_MAGIC_HEADER", config.responsePacketMagicHeader } });
|
||||
vars.append({ { "$UNDERLOAD_PACKET_MAGIC_HEADER", config.underloadPacketMagicHeader } });
|
||||
vars.append({ { "$TRANSPORT_PACKET_MAGIC_HEADER", config.transportPacketMagicHeader } });
|
||||
vars.append({ { "$COOKIE_REPLY_PACKET_JUNK_SIZE", config.cookieReplyPacketJunkSize } });
|
||||
vars.append({ { "$TRANSPORT_PACKET_JUNK_SIZE", config.transportPacketJunkSize } });
|
||||
vars.append({ { "$SPECIAL_JUNK_1", config.specialJunk1 } });
|
||||
vars.append({ { "$SPECIAL_JUNK_2", config.specialJunk2 } });
|
||||
vars.append({ { "$SPECIAL_JUNK_3", config.specialJunk3 } });
|
||||
vars.append({ { "$SPECIAL_JUNK_4", config.specialJunk4 } });
|
||||
vars.append({ { "$SPECIAL_JUNK_5", config.specialJunk5 } });
|
||||
}
|
||||
|
||||
return vars;
|
||||
}
|
||||
|
||||
amnezia::ScriptVars amnezia::genSftpVars(const ContainerConfig &containerConfig)
|
||||
{
|
||||
ScriptVars vars;
|
||||
|
||||
if (auto* sftpProtocolConfig = containerConfig.getSftpProtocolConfig()) {
|
||||
vars.append({ { "$SFTP_PORT", sftpProtocolConfig->port.isEmpty() ? QString::number(ProtocolUtils::defaultPort(Proto::Sftp)) : sftpProtocolConfig->port } });
|
||||
vars.append({ { "$SFTP_USER", sftpProtocolConfig->userName } });
|
||||
vars.append({ { "$SFTP_PASSWORD", sftpProtocolConfig->password } });
|
||||
}
|
||||
|
||||
return vars;
|
||||
}
|
||||
|
||||
amnezia::ScriptVars amnezia::genSocks5ProxyVars(const ContainerConfig &containerConfig)
|
||||
{
|
||||
ScriptVars vars;
|
||||
|
||||
if (auto* socks5ProxyProtocolConfig = containerConfig.getSocks5ProxyProtocolConfig()) {
|
||||
vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyProtocolConfig->port.isEmpty() ? protocols::socks5Proxy::defaultPort : socks5ProxyProtocolConfig->port } });
|
||||
QString socks5user = (!socks5ProxyProtocolConfig->userName.isEmpty() && !socks5ProxyProtocolConfig->password.isEmpty())
|
||||
? QString("users %1:CL:%2").arg(socks5ProxyProtocolConfig->userName, socks5ProxyProtocolConfig->password)
|
||||
: "";
|
||||
vars.append({ { "$SOCKS5_USER", socks5user } });
|
||||
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
|
||||
}
|
||||
|
||||
return vars;
|
||||
}
|
||||
|
||||
amnezia::ScriptVars amnezia::genProtocolVarsForContainer(DockerContainer container, const ContainerConfig &containerConfig)
|
||||
{
|
||||
ScriptVars vars;
|
||||
Proto protocol = ContainerUtils::defaultProtocol(container);
|
||||
|
||||
switch (protocol) {
|
||||
case Proto::OpenVpn:
|
||||
vars.append(genOpenVpnVars(containerConfig));
|
||||
break;
|
||||
case Proto::Xray:
|
||||
vars.append(genXrayVars(containerConfig));
|
||||
break;
|
||||
case Proto::WireGuard:
|
||||
vars.append(genWireGuardVars(containerConfig));
|
||||
break;
|
||||
case Proto::Awg:
|
||||
vars.append(genAwgVars(containerConfig));
|
||||
break;
|
||||
case Proto::Sftp:
|
||||
vars.append(genSftpVars(containerConfig));
|
||||
break;
|
||||
case Proto::Socks5Proxy:
|
||||
vars.append(genSocks5ProxyVars(containerConfig));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return vars;
|
||||
}
|
||||
Reference in New Issue
Block a user