Compare commits

...

6 Commits

Author SHA1 Message Date
Yaroslav Gurov 890103a16a fix: update amneziawg (#2743)
* chore(conan): update amneziawg

* fix(conan): use cmake 4.2+ to support MSVC26

* fix(ci/cd): use the latest cmake generator available on windows
2026-06-17 19:56:53 +07:00
yp 56ab82f87f fix: Use shared OpenSSL on Android (#2736) 2026-06-16 10:57:32 +07:00
lunardunno 3984acbb44 feat: updating install_docker.sh script (#2661)
* Updating install_docker.sh script

Implementing a Docker service status check.
The Docker reinstall step has been removed due to the implementation of Docker service checking.
Implementing locale checking and assignment.
Implementation of execution of some actions through commands with sudo, to reduce delays caused by differences in the values ​​of the PATH variable for the root user and the user included in the sudo group.
Implementation of a verification step for the install containerization app to avoid installing unsupported podman-docker applications.

* adding message handling to install controller

Adding handling for "Containerization app is not supported" and "Service status not active" messages to the controller.

* Error Codes added

Error Codes added for ServerContainerizationNotSupported & DockerServiceNotActive

* Adding extended descriptions of new errors

* fix last line in errorCodes.h

* fix last line in errorStrings.cpp

* Changing the names of errors

* various changes in the script

The messages output for processing by the server controller have been changed: "Container runtime is not supported" and "Container runtime service is not running."
The redundant check and output of the "Packet manager not found" message, as well as the interruption of script execution, have been eliminated, as this situation is handled by the server controller at an earlier stage (check_server_is_busy.sh) and only there.
Added installation of the whish package if it is missing from the OS, for subsequent re-execution of the install_docker.sh and check_server_is_busy.sh scripts.
Implemented an alternative method for detecting the package manager if the whish package is initially missing from the OS.
The algorithm for setting the $pm variable (package manager) has been changed.

* processed phrases have been changed

The phrases processed by the server controller have been changed.

* Attempting to use "command -v"

Switching to using "command -v" instead of "which".

* "which" as main, "command" as backup.

* "which" as main, "command" as backup for check user

* which  LOCK_CMD with sudo

Run the "which" with sudo to check the $LOCK_CMD variable in case the user's PATH variable has incorrect values ​​if the user is not root and is only a member of the sudo group.

* suppressing sudo password prompt

* suppressing sudo password prompt

* suppressing sudo password prompt install_docker.sh

* Changing the phrase for check stdout

"sudo:" with "not found" instead of "command not found"

* Changing phrases for check stdout check_user_in_sudo.sh‎

* sudo|docker and not found, in one line

* check only sudoers
2026-06-15 22:28:38 +07:00
yp cc404378f9 fix: remove only amnezia- prefixed docker volumes (#2728) 2026-06-15 13:12:19 +07:00
yp 594635e5cf fix: script remove docker volume (#2686)
* move sudo docker volume rm -f

* fix: remove unnecessary function

---------

Co-authored-by: vkamn <vk@amnezia.org>
2026-06-04 22:58:39 +08:00
vkamn f9b106cf5b fix: various fixes (#2693)
* fix: fixed country model update

* fix: fixed context menu crush on ios

* fix: fixed passphrase dialog freeze

* fix: fixed country switch

* fix: fixed start minimized

* fix: fixed black screen after remove container

* refactor: return cloak and ss only for view

* fix: fixed default server change after improt while connected

* fix: divider visibility

* fix: fixed revoke admin user

* fix: fixed language restore after backup

* fix: link hover for tor settings page

* fix: fixed openvpn connecntion status

* fix: fixed free color status

* fix: fixed client config update

* chore: bump version
2026-06-04 22:45:53 +08:00
74 changed files with 613 additions and 237 deletions
+1 -1
View File
@@ -157,7 +157,7 @@ jobs:
run: pip install "conan==2.28.0" run: pip install "conan==2.28.0"
- name: 'Build dependencies' - name: 'Build dependencies'
run: cmake -S . -B build -G "Visual Studio 17 2022" -DPREBUILTS_ONLY=1 run: cmake -S . -B build -DPREBUILTS_ONLY=1
- name: 'Authorize in remote' - name: 'Authorize in remote'
if: github.ref == 'refs/heads/dev' if: github.ref == 'refs/heads/dev'
+2 -2
View File
@@ -4,7 +4,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(PROJECT AmneziaVPN) set(PROJECT AmneziaVPN)
set(AMNEZIAVPN_VERSION 4.9.0.1) set(AMNEZIAVPN_VERSION 4.9.0.2)
set(QT_CREATOR_SKIP_PACKAGE_MANAGER_SETUP ON CACHE BOOL "" FORCE) set(QT_CREATOR_SKIP_PACKAGE_MANAGER_SETUP ON CACHE BOOL "" FORCE)
set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES
@@ -28,7 +28,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}") set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}) set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(APP_ANDROID_VERSION_CODE 2122) set(APP_ANDROID_VERSION_CODE 2123)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux") set(MZ_PLATFORM_NAME "linux")
@@ -49,14 +49,92 @@ void ConnectionController::setConnectionState(Vpn::ConnectionState state)
} }
} }
ErrorCode ConnectionController::prepareConnection(const QString &serverId, ErrorCode ConnectionController::defaultContainerForServer(const QString &serverId, DockerContainer &container) const
QJsonObject& vpnConfiguration,
DockerContainer& container)
{ {
const auto kind = m_serversRepository->serverKind(serverId);
switch (kind) {
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
const auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
if (!cfg.has_value()) {
return ErrorCode::InternalError;
}
container = cfg->defaultContainer;
return ErrorCode::NoError;
}
case serverConfigUtils::ConfigType::SelfHostedUser: {
const auto cfg = m_serversRepository->selfHostedUserConfig(serverId);
if (!cfg.has_value()) {
return ErrorCode::InternalError;
}
container = cfg->defaultContainer;
return ErrorCode::NoError;
}
case serverConfigUtils::ConfigType::Native: {
const auto cfg = m_serversRepository->nativeConfig(serverId);
if (!cfg.has_value()) {
return ErrorCode::InternalError;
}
container = cfg->defaultContainer;
return ErrorCode::NoError;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
case serverConfigUtils::ConfigType::AmneziaFreeV3:
case serverConfigUtils::ConfigType::ExternalPremium: {
const auto cfg = m_serversRepository->apiV2Config(serverId);
if (!cfg.has_value()) {
return ErrorCode::InternalError;
}
container = cfg->defaultContainer;
return ErrorCode::NoError;
}
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
case serverConfigUtils::ConfigType::AmneziaFreeV2:
return ErrorCode::LegacyApiV1NotSupportedError;
case serverConfigUtils::ConfigType::Invalid:
default:
return ErrorCode::InternalError;
}
}
ErrorCode ConnectionController::isConnectionSupported(const QString &serverId) const
{
if (serverId.isEmpty()) {
return ErrorCode::InternalError;
}
if (!isServiceReady()) { if (!isServiceReady()) {
return ErrorCode::AmneziaServiceNotRunning; return ErrorCode::AmneziaServiceNotRunning;
} }
if (serverConfigUtils::isLegacyApiSubscription(m_serversRepository->serverKind(serverId))) {
return ErrorCode::LegacyApiV1NotSupportedError;
}
DockerContainer container = DockerContainer::None;
const ErrorCode errorCode = defaultContainerForServer(serverId, container);
if (errorCode != ErrorCode::NoError) {
return errorCode;
}
if (container == DockerContainer::None) {
return ErrorCode::NoInstalledContainersError;
}
if (ContainerUtils::isUnsupportedContainer(container)) {
return ErrorCode::LegacyContainerNotSupportedError;
}
if (!isContainerSupported(container)) {
return ErrorCode::NotSupportedOnThisPlatform;
}
return ErrorCode::NoError;
}
ErrorCode ConnectionController::prepareConnection(const QString &serverId,
QJsonObject& vpnConfiguration,
DockerContainer& container)
{
ContainerConfig containerConfigModel; ContainerConfig containerConfigModel;
QPair<QString, QString> dns; QPair<QString, QString> dns;
QString hostName; QString hostName;
@@ -120,10 +198,6 @@ ErrorCode ConnectionController::prepareConnection(const QString &serverId,
return ErrorCode::InternalError; return ErrorCode::InternalError;
} }
if (!isContainerSupported(container)) {
return ErrorCode::NotSupportedOnThisPlatform;
}
vpnConfiguration = createConnectionConfiguration(dns, isApiConfig, hostName, description, configVersion, vpnConfiguration = createConnectionConfiguration(dns, isApiConfig, hostName, description, configVersion,
containerConfigModel, container); containerConfigModel, container);
@@ -34,6 +34,8 @@ public:
QJsonObject& vpnConfiguration, QJsonObject& vpnConfiguration,
DockerContainer& container); DockerContainer& container);
ErrorCode isConnectionSupported(const QString &serverId) const;
ErrorCode openConnection(const QString &serverId); ErrorCode openConnection(const QString &serverId);
void closeConnection(); void closeConnection();
@@ -73,6 +75,8 @@ signals:
#endif #endif
private: private:
ErrorCode defaultContainerForServer(const QString &serverId, DockerContainer &container) const;
SecureServersRepository* m_serversRepository; SecureServersRepository* m_serversRepository;
SecureAppSettingsRepository* m_appSettingsRepository; SecureAppSettingsRepository* m_appSettingsRepository;
VpnConnection* m_vpnConnection; VpnConnection* m_vpnConnection;
+1 -1
View File
@@ -191,7 +191,7 @@ void CoreController::initControllers()
m_languageUiController = new LanguageUiController(m_settingsController, m_languageModel, this); m_languageUiController = new LanguageUiController(m_settingsController, m_languageModel, this);
setQmlContextProperty("LanguageUiController", m_languageUiController); setQmlContextProperty("LanguageUiController", m_languageUiController);
m_settingsUiController = new SettingsUiController(m_settingsController, m_serversController, m_languageUiController, this); m_settingsUiController = new SettingsUiController(m_settingsController, m_serversController, this);
setQmlContextProperty("SettingsController", m_settingsUiController); setQmlContextProperty("SettingsController", m_settingsUiController);
m_pageController = new PageController(m_serversController, m_settingsController, this); m_pageController = new PageController(m_serversController, m_settingsController, this);
+23 -19
View File
@@ -33,7 +33,6 @@
#include "core/controllers/connectionController.h" #include "core/controllers/connectionController.h"
#include "ui/models/clientManagementModel.h" #include "ui/models/clientManagementModel.h"
#include "ui/controllers/api/apiNewsUiController.h" #include "ui/controllers/api/apiNewsUiController.h"
#include "ui/models/api/apiCountryModel.h"
#include "ui/models/containersModel.h" #include "ui/models/containersModel.h"
#include "core/utils/containerEnum.h" #include "core/utils/containerEnum.h"
@@ -156,15 +155,17 @@ void CoreSignalHandlers::initExportControllerHandler()
void CoreSignalHandlers::initImportControllerHandler() void CoreSignalHandlers::initImportControllerHandler()
{ {
connect(m_coreController->m_importCoreController, &ImportController::importFinished, this, [this]() { connect(m_coreController->m_importCoreController, &ImportController::importFinished, this, [this]() {
if (!m_coreController->m_connectionController->isConnected()) { if (m_coreController->m_connectionUiController->isConnected()) {
int newServerIndex = m_coreController->m_serversController->getServersCount() - 1; return;
const QString serverId = m_coreController->m_serversController->getServerId(newServerIndex); }
if (!serverId.isEmpty()) {
m_coreController->m_serversController->setDefaultServer(serverId); const int newServerIndex = m_coreController->m_serversController->getServersCount() - 1;
} const QString serverId = m_coreController->m_serversController->getServerId(newServerIndex);
if (m_coreController->m_serversUiController) { if (!serverId.isEmpty()) {
m_coreController->m_serversUiController->setProcessedServerId(serverId); m_coreController->m_serversController->setDefaultServer(serverId);
} }
if (m_coreController->m_serversUiController) {
m_coreController->m_serversUiController->setProcessedServerId(serverId);
} }
}); });
} }
@@ -176,17 +177,14 @@ void CoreSignalHandlers::initApiCountryModelUpdateHandler()
if (processedServerId.isEmpty()) { if (processedServerId.isEmpty()) {
return; return;
} }
QJsonArray availableCountries;
QString serverCountryCode;
const auto apiV2 = m_coreController->m_serversRepository->apiV2Config(processedServerId); const auto apiV2 = m_coreController->m_serversRepository->apiV2Config(processedServerId);
if (apiV2.has_value()) { if (!apiV2.has_value()) {
availableCountries = apiV2->apiConfig.availableCountries; return;
serverCountryCode = apiV2->apiConfig.serverCountryCode;
} }
m_coreController->m_apiCountryModel->updateModel(availableCountries, serverCountryCode); m_coreController->m_apiCountryModel->updateModel(apiV2->apiConfig.availableCountries,
apiV2->apiConfig.serverCountryCode);
}); });
} }
@@ -237,13 +235,16 @@ void CoreSignalHandlers::initLanguageHandler()
connect(m_coreController->m_settingsUiController, &SettingsUiController::resetLanguageToSystem, m_coreController->m_languageUiController, [this]() { connect(m_coreController->m_settingsUiController, &SettingsUiController::resetLanguageToSystem, m_coreController->m_languageUiController, [this]() {
m_coreController->m_languageUiController->changeLanguage(m_coreController->m_languageUiController->getSystemLanguageEnum()); m_coreController->m_languageUiController->changeLanguage(m_coreController->m_languageUiController->getSystemLanguageEnum());
}); });
connect(m_coreController->m_settingsUiController, &SettingsUiController::appLanguageChanged, m_coreController->m_languageUiController, [this]() {
m_coreController->m_languageUiController->onAppLanguageChanged(m_coreController->m_settingsController->getAppLanguage());
});
} }
void CoreSignalHandlers::initAutoConnectHandler() void CoreSignalHandlers::initAutoConnectHandler()
{ {
if (m_coreController->m_settingsUiController->isAutoConnectEnabled() if (m_coreController->m_settingsUiController->isAutoConnectEnabled()
&& !m_coreController->m_serversController->getDefaultServerId().isEmpty()) { && !m_coreController->m_serversController->getDefaultServerId().isEmpty()) {
QTimer::singleShot(1000, this, [this]() { m_coreController->m_connectionUiController->openConnection(); }); QTimer::singleShot(1000, this, [this]() { m_coreController->m_connectionUiController->toggleConnection(); });
} }
} }
@@ -348,6 +349,9 @@ void CoreSignalHandlers::initUnsupportedConnectDrawerHandler()
{ {
connect(m_coreController->m_subscriptionUiController, &SubscriptionUiController::unsupportedConnectDrawerRequested, connect(m_coreController->m_subscriptionUiController, &SubscriptionUiController::unsupportedConnectDrawerRequested,
m_coreController->m_pageController, &PageController::unsupportedConnectDrawerRequested); m_coreController->m_pageController, &PageController::unsupportedConnectDrawerRequested);
connect(m_coreController->m_connectionUiController, &ConnectionUiController::unsupportedConnectDrawerRequested,
m_coreController->m_pageController, &PageController::unsupportedConnectDrawerRequested);
} }
void CoreSignalHandlers::initStrictKillSwitchHandler() void CoreSignalHandlers::initStrictKillSwitchHandler()
@@ -72,6 +72,16 @@ namespace
} }
return false; return false;
} }
QString buildRemoveContainerScript(const amnezia::ScriptVars &vars, bool removeDataVolume)
{
QString script = SshSession::replaceVars(amnezia::scriptData(SharedScriptType::remove_container), vars);
if (removeDataVolume) {
script += QLatin1String("\nsudo docker volume rm -f $CONTAINER_NAME-data 2>/dev/null || true");
script = SshSession::replaceVars(script, vars);
}
return script;
}
} }
InstallController::InstallController(SecureServersRepository *serversRepository, InstallController::InstallController(SecureServersRepository *serversRepository,
@@ -120,14 +130,10 @@ ErrorCode InstallController::setupContainer(const ServerCredentials &credentials
return e; return e;
qDebug().noquote() << "InstallController::setupContainer prepareHostWorker finished"; qDebug().noquote() << "InstallController::setupContainer prepareHostWorker finished";
amnezia::ScriptVars removeContainerVars = const amnezia::ScriptVars removeContainerVars =
amnezia::genBaseVars(credentials, container, QString(), QString()); amnezia::genBaseVars(credentials, container, QString(), QString());
if (!isUpdate) { const bool removeDataVolume = !isUpdate && (container == DockerContainer::MtProxy || container == DockerContainer::Telemt);
removeContainerVars.append({ { "$REMOVE_CONTAINER_DATA", QStringLiteral("1") } }); sshSession.runScript(credentials, buildRemoveContainerScript(removeContainerVars, removeDataVolume));
}
sshSession.runScript(credentials,
sshSession.replaceVars(amnezia::scriptData(SharedScriptType::remove_container),
removeContainerVars));
qDebug().noquote() << "InstallController::setupContainer removeContainer finished"; qDebug().noquote() << "InstallController::setupContainer removeContainer finished";
qDebug().noquote() << "buildContainerWorker start"; qDebug().noquote() << "buildContainerWorker start";
@@ -152,8 +158,8 @@ ErrorCode InstallController::setupContainer(const ServerCredentials &credentials
return startupContainerWorker(credentials, container, config, sshSession); return startupContainerWorker(credentials, container, config, sshSession);
} }
ErrorCode InstallController::updateContainer(const QString &serverId, DockerContainer container, const ContainerConfig &oldConfig, ErrorCode InstallController::updateServerConfig(const QString &serverId, DockerContainer container, const ContainerConfig &oldConfig,
ContainerConfig &newConfig) ContainerConfig &newConfig)
{ {
if (!isUpdateDockerContainerRequired(container, oldConfig, newConfig)) { if (!isUpdateDockerContainerRequired(container, oldConfig, newConfig)) {
auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId); auto adminConfig = m_serversRepository->selfHostedAdminConfig(serverId);
@@ -185,7 +191,7 @@ ErrorCode InstallController::updateContainer(const QString &serverId, DockerCont
SshSession sshSession(this); SshSession sshSession(this);
bool reinstallRequired = isReinstallContainerRequired(container, oldConfig, newConfig); bool reinstallRequired = isReinstallContainerRequired(container, oldConfig, newConfig);
qDebug() << "InstallController::updateContainer for container" << container << "reinstall required is" << reinstallRequired; qDebug() << "InstallController::updateServerConfig for container" << container << "reinstall required is" << reinstallRequired;
bool xrayServerSettingsChanged = false; bool xrayServerSettingsChanged = false;
if (container == DockerContainer::Xray || container == DockerContainer::SSXray) { if (container == DockerContainer::Xray || container == DockerContainer::SSXray) {
@@ -213,11 +219,11 @@ ErrorCode InstallController::updateContainer(const QString &serverId, DockerCont
if (errorCode == ErrorCode::NoError && xrayServerSettingsChanged && !skipXrayInboundSync) { if (errorCode == ErrorCode::NoError && xrayServerSettingsChanged && !skipXrayInboundSync) {
DnsSettings dnsSettings = { m_appSettingsRepository->primaryDns(), m_appSettingsRepository->secondaryDns() }; DnsSettings dnsSettings = { m_appSettingsRepository->primaryDns(), m_appSettingsRepository->secondaryDns() };
XrayConfigurator xrayConfigurator(&sshSession); XrayConfigurator xrayConfigurator(&sshSession);
qDebug() << "InstallController::updateContainer applying Xray server inbound sync, reinstall=" qDebug() << "InstallController::updateServerConfig applying Xray server inbound sync, reinstall="
<< reinstallRequired; << reinstallRequired;
errorCode = xrayConfigurator.applyServerSettingsToRemote(credentials, container, newConfig, dnsSettings, false); errorCode = xrayConfigurator.applyServerSettingsToRemote(credentials, container, newConfig, dnsSettings, false);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
qDebug() << "InstallController::updateContainer Xray inbound sync failed, error=" qDebug() << "InstallController::updateServerConfig Xray inbound sync failed, error="
<< static_cast<int>(errorCode); << static_cast<int>(errorCode);
} }
} }
@@ -236,6 +242,41 @@ ErrorCode InstallController::updateContainer(const QString &serverId, DockerCont
return errorCode; return errorCode;
} }
ErrorCode InstallController::updateClientConfig(const QString &serverId, DockerContainer container, ContainerConfig &newConfig)
{
switch (m_serversRepository->serverKind(serverId)) {
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
auto config = m_serversRepository->selfHostedAdminConfig(serverId);
if (!config.has_value()) {
return ErrorCode::InternalError;
}
config->updateContainerConfig(container, newConfig);
m_serversRepository->editServer(serverId, config->toJson(), serverConfigUtils::ConfigType::SelfHostedAdmin);
return ErrorCode::NoError;
}
case serverConfigUtils::ConfigType::SelfHostedUser: {
auto config = m_serversRepository->selfHostedUserConfig(serverId);
if (!config.has_value()) {
return ErrorCode::InternalError;
}
config->updateContainerConfig(container, newConfig);
m_serversRepository->editServer(serverId, config->toJson(), serverConfigUtils::ConfigType::SelfHostedUser);
return ErrorCode::NoError;
}
case serverConfigUtils::ConfigType::Native: {
auto config = m_serversRepository->nativeConfig(serverId);
if (!config.has_value()) {
return ErrorCode::InternalError;
}
config->updateContainerConfig(container, newConfig);
m_serversRepository->editServer(serverId, config->toJson(), serverConfigUtils::ConfigType::Native);
return ErrorCode::NoError;
}
default:
return ErrorCode::InternalError;
}
}
void InstallController::clearCachedProfile(const QString &serverId, DockerContainer container) void InstallController::clearCachedProfile(const QString &serverId, DockerContainer container)
{ {
if (ContainerUtils::containerService(container) == ServiceType::Other) { if (ContainerUtils::containerService(container) == ServiceType::Other) {
@@ -795,8 +836,8 @@ ErrorCode InstallController::installDockerWorker(const ServerCredentials &creden
qDebug().noquote() << "InstallController::installDockerWorker" << stdOut; qDebug().noquote() << "InstallController::installDockerWorker" << stdOut;
if (container == DockerContainer::Awg2) { if (container == DockerContainer::Awg2) {
QRegularExpression regex(R"(Linux\s+(\d+)\.(\d+)[^\d]*)"); QRegularExpression kernelVersionRegex(R"(Linux\s+(\d+)\.(\d+)[^\d]*)");
QRegularExpressionMatch match = regex.match(stdOut); QRegularExpressionMatch match = kernelVersionRegex.match(stdOut);
if (match.hasMatch()) { if (match.hasMatch()) {
int majorVersion = match.captured(1).toInt(); int majorVersion = match.captured(1).toInt();
int minorVersion = match.captured(2).toInt(); int minorVersion = match.captured(2).toInt();
@@ -809,8 +850,19 @@ ErrorCode InstallController::installDockerWorker(const ServerCredentials &creden
if (stdOut.contains("lock")) if (stdOut.contains("lock"))
return ErrorCode::ServerPacketManagerError; return ErrorCode::ServerPacketManagerError;
if (stdOut.contains("command not found")) if (stdOut.contains("Container runtime is not supported"))
return ErrorCode::ServerContainerRuntimeNotSupported;
QRegularExpression notFoundRegex(
R"(^.*(?:sudo:|docker:).*not found.*$)",
QRegularExpression::MultilineOption);
if (notFoundRegex.match(stdOut).hasMatch()) {
return ErrorCode::ServerDockerFailedError; return ErrorCode::ServerDockerFailedError;
}
if (stdOut.contains("Container runtime service not running"))
return ErrorCode::ContainerRuntimeServiceNotRunning;
return error; return error;
} }
@@ -847,7 +899,7 @@ ErrorCode InstallController::isUserInSudo(const ServerCredentials &credentials,
return ErrorCode::ServerUserNotInSudo; return ErrorCode::ServerUserNotInSudo;
if (stdOut.contains("can't cd to") || stdOut.contains("Permission denied") || stdOut.contains("No such file or directory")) if (stdOut.contains("can't cd to") || stdOut.contains("Permission denied") || stdOut.contains("No such file or directory"))
return ErrorCode::ServerUserDirectoryNotAccessible; return ErrorCode::ServerUserDirectoryNotAccessible;
if (stdOut.contains("sudoers") || stdOut.contains("is not allowed to run sudo on")) if (stdOut.contains(QRegularExpression(R"(\bsudoers\b)")) || stdOut.contains("is not allowed to") || stdOut.contains("can't do that"))
return ErrorCode::ServerUserNotAllowedInSudoers; return ErrorCode::ServerUserNotAllowedInSudoers;
if (stdOut.contains("password is required") || stdOut.contains("authentication is required")) if (stdOut.contains("password is required") || stdOut.contains("authentication is required"))
return ErrorCode::ServerUserPasswordRequired; return ErrorCode::ServerUserPasswordRequired;
@@ -980,12 +1032,11 @@ ErrorCode InstallController::removeContainer(const QString &serverId, DockerCont
return ErrorCode::InternalError; return ErrorCode::InternalError;
} }
SshSession sshSession(this); SshSession sshSession(this);
amnezia::ScriptVars removeContainerVars = const amnezia::ScriptVars removeContainerVars =
amnezia::genBaseVars(credentials, container, QString(), QString()); amnezia::genBaseVars(credentials, container, QString(), QString());
removeContainerVars.append({ { "$REMOVE_CONTAINER_DATA", QStringLiteral("1") } }); const bool removeDataVolume = (container == DockerContainer::MtProxy || container == DockerContainer::Telemt);
ErrorCode errorCode = sshSession.runScript( ErrorCode errorCode =
credentials, sshSession.runScript(credentials, buildRemoveContainerScript(removeContainerVars, removeDataVolume));
sshSession.replaceVars(amnezia::scriptData(SharedScriptType::remove_container), removeContainerVars));
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
QMap<DockerContainer, ContainerConfig> containers = adminConfig->containers; QMap<DockerContainer, ContainerConfig> containers = adminConfig->containers;
@@ -1463,7 +1514,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
QString transportProtoStr = containerAndPortMatch.captured(3); QString transportProtoStr = containerAndPortMatch.captured(3);
DockerContainer container = ContainerUtils::containerFromString(name); DockerContainer container = ContainerUtils::containerFromString(name);
if (container == DockerContainer::None) { if (container == DockerContainer::None || ContainerUtils::isUnsupportedContainer(container)) {
continue; continue;
} }
@@ -1488,7 +1539,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
QString transportProtoStr = torOrDnsRegMatch.captured(3); QString transportProtoStr = torOrDnsRegMatch.captured(3);
DockerContainer container = ContainerUtils::containerFromString(name); DockerContainer container = ContainerUtils::containerFromString(name);
if (container == DockerContainer::None) { if (container == DockerContainer::None || ContainerUtils::isUnsupportedContainer(container)) {
continue; continue;
} }
@@ -34,7 +34,12 @@ public:
~InstallController(); ~InstallController();
ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, ContainerConfig &config, bool isUpdate = false); ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, ContainerConfig &config, bool isUpdate = false);
ErrorCode updateContainer(const QString &serverId, DockerContainer container, const ContainerConfig &oldConfig, ContainerConfig &newConfig);
// Updates server-side container settings (admin self-hosted only): reconfigures the container over SSH.
ErrorCode updateServerConfig(const QString &serverId, DockerContainer container, const ContainerConfig &oldConfig, ContainerConfig &newConfig);
// Updates client-local settings only: rewrites the stored container config for any self-hosted/native server. No SSH.
ErrorCode updateClientConfig(const QString &serverId, DockerContainer container, ContainerConfig &newConfig);
ErrorCode rebootServer(const QString &serverId); ErrorCode rebootServer(const QString &serverId);
ErrorCode removeAllContainers(const QString &serverId); ErrorCode removeAllContainers(const QString &serverId);
@@ -29,6 +29,11 @@ ContainerConfig NativeServerConfig::containerConfig(DockerContainer container) c
return containers.value(container); return containers.value(container);
} }
void NativeServerConfig::updateContainerConfig(DockerContainer container, const ContainerConfig &config)
{
containers[container] = config;
}
QPair<QString, QString> NativeServerConfig::getDnsPair(const QString &primaryDns, const QString &secondaryDns) const QPair<QString, QString> NativeServerConfig::getDnsPair(const QString &primaryDns, const QString &secondaryDns) const
{ {
QString d1 = dns1; QString d1 = dns1;
@@ -27,6 +27,8 @@ struct NativeServerConfig {
bool hasContainers() const; bool hasContainers() const;
ContainerConfig containerConfig(DockerContainer container) const; ContainerConfig containerConfig(DockerContainer container) const;
void updateContainerConfig(DockerContainer container, const ContainerConfig &config);
QPair<QString, QString> getDnsPair(const QString &primaryDns, const QString &secondaryDns) const; QPair<QString, QString> getDnsPair(const QString &primaryDns, const QString &secondaryDns) const;
QJsonObject toJson() const; QJsonObject toJson() const;
@@ -43,6 +43,11 @@ ContainerConfig SelfHostedUserServerConfig::containerConfig(DockerContainer cont
return containers.value(container); return containers.value(container);
} }
void SelfHostedUserServerConfig::updateContainerConfig(DockerContainer container, const ContainerConfig &config)
{
containers[container] = config;
}
QPair<QString, QString> SelfHostedUserServerConfig::getDnsPair(const QString &primaryDns, QPair<QString, QString> SelfHostedUserServerConfig::getDnsPair(const QString &primaryDns,
const QString &secondaryDns) const const QString &secondaryDns) const
{ {
@@ -32,6 +32,8 @@ struct SelfHostedUserServerConfig {
bool hasContainers() const; bool hasContainers() const;
ContainerConfig containerConfig(DockerContainer container) const; ContainerConfig containerConfig(DockerContainer container) const;
void updateContainerConfig(DockerContainer container, const ContainerConfig &config);
QPair<QString, QString> getDnsPair(const QString &primaryDns, const QString &secondaryDns) const; QPair<QString, QString> getDnsPair(const QString &primaryDns, const QString &secondaryDns) const;
QJsonObject toJson() const; QJsonObject toJson() const;
+24 -13
View File
@@ -39,33 +39,44 @@ QString OpenVpnProtocol::defaultConfigPath()
return p; return p;
} }
void OpenVpnProtocol::stop() void OpenVpnProtocol::cleanupResources()
{ {
qDebug() << "OpenVpnProtocol::stop()"; if (m_openVpnProcess || openVpnProcessIsRunning()) {
setConnectionState(Vpn::ConnectionState::Disconnecting);
// TODO: need refactoring
// sendTermSignal() will even return true while server connected ???
if ((m_connectionState == Vpn::ConnectionState::Preparing) || (m_connectionState == Vpn::ConnectionState::Connecting)
|| (m_connectionState == Vpn::ConnectionState::Connected)
|| (m_connectionState == Vpn::ConnectionState::Reconnecting)) {
if (!sendTermSignal()) { if (!sendTermSignal()) {
killOpenVpnProcess(); killOpenVpnProcess();
} }
QThread::msleep(10); QThread::msleep(10);
m_managementServer.stop();
} }
m_managementServer.stop();
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_MACOS) #if defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
IpcClient::withInterface([](QSharedPointer<IpcInterfaceReplica> iface) { IpcClient::withInterface([](QSharedPointer<IpcInterfaceReplica> iface) {
QRemoteObjectPendingReply<bool> reply = iface->disableKillSwitch(); QRemoteObjectPendingReply<bool> reply = iface->disableKillSwitch();
if (!reply.waitForFinished(1000) && !reply.returnValue()) { if (!reply.waitForFinished(1000) && !reply.returnValue()) {
qWarning() << "OpenVpnProtocol::stop(): Failed to disable killswitch"; qWarning() << "OpenVpnProtocol::cleanupResources(): Failed to disable killswitch";
} }
}); });
#endif #endif
}
setConnectionState(Vpn::ConnectionState::Disconnected); void OpenVpnProtocol::stop()
{
qDebug() << "OpenVpnProtocol::stop()";
const bool wasActive = m_connectionState == Vpn::ConnectionState::Preparing
|| m_connectionState == Vpn::ConnectionState::Connecting
|| m_connectionState == Vpn::ConnectionState::Connected
|| m_connectionState == Vpn::ConnectionState::Reconnecting;
if (wasActive) {
setConnectionState(Vpn::ConnectionState::Disconnecting);
}
cleanupResources();
if (wasActive || m_connectionState == Vpn::ConnectionState::Disconnecting) {
setConnectionState(Vpn::ConnectionState::Disconnected);
}
} }
ErrorCode OpenVpnProtocol::prepare() ErrorCode OpenVpnProtocol::prepare()
@@ -168,7 +179,7 @@ void OpenVpnProtocol::updateRouteGateway(QString line)
ErrorCode OpenVpnProtocol::start() ErrorCode OpenVpnProtocol::start()
{ {
OpenVpnProtocol::stop(); cleanupResources();
if (!QFileInfo::exists(configPath())) { if (!QFileInfo::exists(configPath())) {
setLastError(ErrorCode::OpenVpnConfigMissing); setLastError(ErrorCode::OpenVpnConfigMissing);
+1
View File
@@ -29,6 +29,7 @@ protected slots:
void onReadyReadDataFromManagementServer(); void onReadyReadDataFromManagementServer();
private: private:
void cleanupResources();
QString configPath() const; QString configPath() const;
bool openVpnProcessIsRunning() const; bool openVpnProcessIsRunning() const;
bool sendTermSignal(); bool sendTermSignal();
+2
View File
@@ -15,6 +15,8 @@ namespace amnezia
Awg2, Awg2,
WireGuard, WireGuard,
OpenVpn, OpenVpn,
Cloak,
ShadowSocks,
Ipsec, Ipsec,
Xray, Xray,
SSXray, SSXray,
@@ -21,6 +21,8 @@ QString ContainerUtils::containerToString(DockerContainer c)
{ {
if (c == DockerContainer::None) if (c == DockerContainer::None)
return "none"; return "none";
if (c == DockerContainer::Cloak)
return "amnezia-openvpn-cloak";
if (c == DockerContainer::Awg) if (c == DockerContainer::Awg)
return "amnezia-awg"; return "amnezia-awg";
if (c == DockerContainer::Awg2) if (c == DockerContainer::Awg2)
@@ -62,6 +64,8 @@ QMap<DockerContainer, QString> ContainerUtils::containerHumanNames()
{ {
return { { DockerContainer::None, "Not installed" }, return { { DockerContainer::None, "Not installed" },
{ DockerContainer::OpenVpn, "OpenVPN" }, { DockerContainer::OpenVpn, "OpenVPN" },
{ DockerContainer::ShadowSocks, "OpenVPN over SS" },
{ DockerContainer::Cloak, "OpenVPN over Cloak" },
{ DockerContainer::WireGuard, "WireGuard" }, { DockerContainer::WireGuard, "WireGuard" },
{ DockerContainer::Awg, "AmneziaWG" }, { DockerContainer::Awg, "AmneziaWG" },
{ DockerContainer::Awg2, "AmneziaWG" }, { DockerContainer::Awg2, "AmneziaWG" },
@@ -83,6 +87,10 @@ QMap<DockerContainer, QString> ContainerUtils::containerDescriptions()
return { { DockerContainer::OpenVpn, return { { DockerContainer::OpenVpn,
QObject::tr("OpenVPN is the most popular VPN protocol, with flexible configuration options. It uses its " QObject::tr("OpenVPN is the most popular VPN protocol, with flexible configuration options. It uses its "
"own security protocol with SSL/TLS for key exchange.") }, "own security protocol with SSL/TLS for key exchange.") },
{ DockerContainer::ShadowSocks,
QObject::tr("This protocol is no longer supported.") },
{ DockerContainer::Cloak,
QObject::tr("This protocol is no longer supported.") },
{ DockerContainer::WireGuard, { DockerContainer::WireGuard,
QObject::tr("WireGuard - popular VPN protocol with high performance, high speed and low power " QObject::tr("WireGuard - popular VPN protocol with high performance, high speed and low power "
"consumption.") }, "consumption.") },
@@ -194,6 +202,9 @@ QMap<DockerContainer, QString> ContainerUtils::containerDetailedDescriptions()
ServiceType ContainerUtils::containerService(DockerContainer c) ServiceType ContainerUtils::containerService(DockerContainer c)
{ {
if (isUnsupportedContainer(c)) {
return ServiceType::Vpn;
}
return ProtocolUtils::protocolService(defaultProtocol(c)); return ProtocolUtils::protocolService(defaultProtocol(c));
} }
@@ -202,6 +213,8 @@ Proto ContainerUtils::defaultProtocol(DockerContainer c)
switch (c) { switch (c) {
case DockerContainer::None: return Proto::Unknown; case DockerContainer::None: return Proto::Unknown;
case DockerContainer::OpenVpn: return Proto::OpenVpn; case DockerContainer::OpenVpn: return Proto::OpenVpn;
case DockerContainer::Cloak:
case DockerContainer::ShadowSocks: return Proto::Unknown;
case DockerContainer::WireGuard: return Proto::WireGuard; case DockerContainer::WireGuard: return Proto::WireGuard;
case DockerContainer::Awg2: return Proto::Awg; case DockerContainer::Awg2: return Proto::Awg;
case DockerContainer::Awg: return Proto::Awg; case DockerContainer::Awg: return Proto::Awg;
@@ -252,6 +265,8 @@ bool ContainerUtils::isSupportedByCurrentPlatform(DockerContainer c)
// macOS build using Network Extension allow OpenVPN for parity with iOS. // macOS build using Network Extension allow OpenVPN for parity with iOS.
switch (c) { switch (c) {
case DockerContainer::OpenVpn: return true; case DockerContainer::OpenVpn: return true;
case DockerContainer::Cloak: return false;
case DockerContainer::ShadowSocks: return false;
case DockerContainer::WireGuard: return true; case DockerContainer::WireGuard: return true;
case DockerContainer::Awg2: return true; case DockerContainer::Awg2: return true;
case DockerContainer::Awg: return true; case DockerContainer::Awg: return true;
@@ -336,6 +351,10 @@ int ContainerUtils::easySetupOrder(DockerContainer container)
bool ContainerUtils::isShareable(DockerContainer container) bool ContainerUtils::isShareable(DockerContainer container)
{ {
if (isUnsupportedContainer(container)) {
return false;
}
switch (container) { switch (container) {
case DockerContainer::TorWebSite: return false; case DockerContainer::TorWebSite: return false;
case DockerContainer::Dns: return false; case DockerContainer::Dns: return false;
@@ -352,6 +371,11 @@ bool ContainerUtils::isAwgContainer(DockerContainer container)
return container == DockerContainer::Awg || container == DockerContainer::Awg2; return container == DockerContainer::Awg || container == DockerContainer::Awg2;
} }
bool ContainerUtils::isUnsupportedContainer(DockerContainer container)
{
return container == DockerContainer::Cloak || container == DockerContainer::ShadowSocks;
}
QJsonObject ContainerUtils::getProtocolConfigFromContainer(const Proto protocol, const QJsonObject &containerConfig) QJsonObject ContainerUtils::getProtocolConfigFromContainer(const Proto protocol, const QJsonObject &containerConfig)
{ {
QString protocolConfigString = containerConfig.value(ProtocolUtils::protoToString(protocol)) QString protocolConfigString = containerConfig.value(ProtocolUtils::protoToString(protocol))
@@ -45,6 +45,8 @@ namespace amnezia
bool isAwgContainer(DockerContainer container); bool isAwgContainer(DockerContainer container);
bool isUnsupportedContainer(DockerContainer container);
QJsonObject getProtocolConfigFromContainer(const Proto protocol, const QJsonObject &containerConfig); QJsonObject getProtocolConfigFromContainer(const Proto protocol, const QJsonObject &containerConfig);
int installPageOrder(DockerContainer container); int installPageOrder(DockerContainer container);
+3 -2
View File
@@ -38,6 +38,8 @@ namespace amnezia
XrayServerConfigInvalid = 215, XrayServerConfigInvalid = 215,
XrayServerNoVlessClients = 216, XrayServerNoVlessClients = 216,
XrayRealityKeysReadFailed = 217, XrayRealityKeysReadFailed = 217,
ServerContainerRuntimeNotSupported = 218,
ContainerRuntimeServiceNotRunning = 219,
// Ssh connection errors // Ssh connection errors
SshRequestDeniedError = 300, SshRequestDeniedError = 300,
@@ -79,6 +81,7 @@ namespace amnezia
ImportBackupFileUseRestoreInstead = 903, ImportBackupFileUseRestoreInstead = 903,
RestoreBackupInvalidError = 904, RestoreBackupInvalidError = 904,
LegacyApiV1NotSupportedError = 905, LegacyApiV1NotSupportedError = 905,
LegacyContainerNotSupportedError = 906,
// Android errors // Android errors
AndroidError = 1000, AndroidError = 1000,
@@ -123,5 +126,3 @@ namespace amnezia
Q_DECLARE_METATYPE(amnezia::ErrorCode) Q_DECLARE_METATYPE(amnezia::ErrorCode)
#endif // ERRORCODES_H #endif // ERRORCODES_H
+3
View File
@@ -39,6 +39,8 @@ QString errorString(ErrorCode code) {
case(ErrorCode::XrayRealityKeysReadFailed): case(ErrorCode::XrayRealityKeysReadFailed):
errorMessage = QObject::tr("Server error: failed to read XRay Reality keys from the server"); errorMessage = QObject::tr("Server error: failed to read XRay Reality keys from the server");
break; break;
case(ErrorCode::ServerContainerRuntimeNotSupported): errorMessage = QObject::tr("Server error: The default container runtime available for installation on this server is not supported.\n Install Docker Engine on the server manually and try again."); break;
case(ErrorCode::ContainerRuntimeServiceNotRunning): errorMessage = QObject::tr("Container runtime error: The container runtime service is not running.\n Check the container runtime service on the server, or wait about a minute and try again."); break;
// Libssh errors // Libssh errors
case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("SSH request was denied"); break; case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("SSH request was denied"); break;
@@ -69,6 +71,7 @@ QString errorString(ErrorCode code) {
case (ErrorCode::ImportBackupFileUseRestoreInstead): errorMessage = QObject::tr("Backup files cannot be imported here. Use 'Restore from backup' instead."); break; case (ErrorCode::ImportBackupFileUseRestoreInstead): errorMessage = QObject::tr("Backup files cannot be imported here. Use 'Restore from backup' instead."); break;
case (ErrorCode::RestoreBackupInvalidError): errorMessage = QObject::tr("Backup file is corrupted or has invalid format"); break; case (ErrorCode::RestoreBackupInvalidError): errorMessage = QObject::tr("Backup file is corrupted or has invalid format"); break;
case (ErrorCode::LegacyApiV1NotSupportedError): errorMessage = QObject::tr("This legacy Amnezia subscription format is no longer supported"); break; case (ErrorCode::LegacyApiV1NotSupportedError): errorMessage = QObject::tr("This legacy Amnezia subscription format is no longer supported"); break;
case (ErrorCode::LegacyContainerNotSupportedError): errorMessage = QObject::tr("This protocol is no longer supported. Please select another protocol or remove this container from the server settings."); break;
case (ErrorCode::ImportOpenConfigError): errorMessage = QObject::tr("Unable to open config file"); break; case (ErrorCode::ImportOpenConfigError): errorMessage = QObject::tr("Unable to open config file"); break;
case (ErrorCode::NoInstalledContainersError): errorMessage = QObject::tr("VPN Protocols is not installed.\n Please install VPN container at first"); break; case (ErrorCode::NoInstalledContainersError): errorMessage = QObject::tr("VPN Protocols is not installed.\n Please install VPN container at first"); break;
@@ -1,7 +1,8 @@
if which apt-get > /dev/null 2>&1; then LOCK_CMD="fuser"; LOCK_FILE="/var/lib/dpkg/lock-frontend";\ if which apt-get > /dev/null 2>&1 || command -v apt-get > /dev/null 2>&1; then LOCK_CMD="fuser"; LOCK_FILE="/var/lib/dpkg/lock-frontend";\
elif which dnf > /dev/null 2>&1; then LOCK_CMD="fuser"; LOCK_FILE="/var/cache/dnf/* /var/run/dnf/* /var/lib/dnf/* /var/lib/rpm/*";\ elif which dnf > /dev/null 2>&1 || command -v dnf > /dev/null 2>&1; then LOCK_CMD="fuser"; LOCK_FILE="/var/cache/dnf/* /var/run/dnf/* /var/lib/dnf/* /var/lib/rpm/*";\
elif which yum > /dev/null 2>&1; then LOCK_CMD="cat"; LOCK_FILE="/var/run/yum.pid";\ elif which yum > /dev/null 2>&1 || command -v yum > /dev/null 2>&1; then LOCK_CMD="cat"; LOCK_FILE="/var/run/yum.pid";\
elif which zypper > /dev/null 2>&1; then LOCK_CMD="cat"; LOCK_FILE="/var/run/zypp.pid";\ elif which zypper > /dev/null 2>&1 || command -v zypper > /dev/null 2>&1; then LOCK_CMD="cat"; LOCK_FILE="/var/run/zypp.pid";\
elif which pacman > /dev/null 2>&1; then LOCK_CMD="fuser"; LOCK_FILE="/var/lib/pacman/db.lck";\ elif which pacman > /dev/null 2>&1 || command -v pacman > /dev/null 2>&1; then LOCK_CMD="fuser"; LOCK_FILE="/var/lib/pacman/db.lck";\
else echo "Packet manager not found"; echo "Internal error"; exit 1; fi;\ else echo "Packet manager not found"; echo "Internal error"; exit 1;\
if command -v $LOCK_CMD > /dev/null 2>&1; then sudo $LOCK_CMD $LOCK_FILE 2>/dev/null; else echo "$LOCK_CMD not installed"; fi fi;\
if sudo -n which $LOCK_CMD > /dev/null 2>&1 || command -v $LOCK_CMD > /dev/null 2>&1; then sudo -n $LOCK_CMD $LOCK_FILE 2>/dev/null; else echo "$LOCK_CMD not installed"; fi
+5 -5
View File
@@ -1,8 +1,8 @@
if which apt-get > /dev/null 2>&1; then pm=$(which apt-get); opt="--version";\ if pm=$(which apt-get 2>/dev/null || command -v apt-get 2>/dev/null); then opt="--version";\
elif which dnf > /dev/null 2>&1; then pm=$(which dnf); opt="--version";\ elif pm=$(which dnf 2>/dev/null || command -v dnf 2>/dev/null); then opt="--version";\
elif which yum > /dev/null 2>&1; then pm=$(which yum); opt="--version";\ elif pm=$(which yum 2>/dev/null || command -v yum 2>/dev/null); then opt="--version";\
elif which zypper > /dev/null 2>&1; then pm=$(which zypper); opt="--version";\ elif pm=$(which zypper 2>/dev/null || command -v zypper 2>/dev/null); then opt="--version";\
elif which pacman > /dev/null 2>&1; then pm=$(which pacman); opt="--version";\ elif pm=$(which pacman 2>/dev/null || command -v pacman 2>/dev/null); then opt="--version";\
else pm="uname"; opt="-a";\ else pm="uname"; opt="-a";\
fi;\ fi;\
CUR_USER=$(whoami 2>/dev/null || echo $HOME | sed 's/.*\///');\ CUR_USER=$(whoami 2>/dev/null || echo $HOME | sed 's/.*\///');\
+28 -19
View File
@@ -1,25 +1,34 @@
if which apt-get > /dev/null 2>&1; then pm=$(which apt-get); silent_inst="-yq install --install-recommends"; check_pkgs="-yq update"; docker_pkg="docker.io"; dist="debian";\ if pm=$(which apt-get 2>/dev/null || command -v apt-get 2>/dev/null); then silent_inst="-yq install --install-recommends"; what_pkg="-s install"; check_pkgs="-yq update"; docker_pkg="docker.io"; dist="debian";\
elif which dnf > /dev/null 2>&1; then pm=$(which dnf); silent_inst="-yq install"; check_pkgs="-yq check-update"; docker_pkg="docker"; dist="fedora";\ elif pm=$(which dnf 2>/dev/null || command -v dnf 2>/dev/null); then silent_inst="-yq install"; what_pkg="--assumeno install --setopt=tsflags=test"; check_pkgs="-yq check-update"; docker_pkg="docker"; dist="fedora";\
elif which yum > /dev/null 2>&1; then pm=$(which yum); silent_inst="-y -q install"; check_pkgs="-y -q check-update"; docker_pkg="docker"; dist="centos";\ elif pm=$(which yum 2>/dev/null || command -v yum 2>/dev/null); then silent_inst="-y -q install"; what_pkg="--assumeno install --setopt=tsflags=test"; check_pkgs="-y -q check-update"; docker_pkg="docker"; dist="centos";\
elif which zypper > /dev/null 2>&1; then pm=$(which zypper); silent_inst="-nq install"; check_pkgs="-nq refresh"; docker_pkg="docker"; dist="opensuse";\ elif pm=$(which zypper 2>/dev/null || command -v zypper 2>/dev/null); then silent_inst="-nq install"; what_pkg="--dry-run install"; check_pkgs="-nq refresh"; docker_pkg="docker"; dist="suse";\
elif which pacman > /dev/null 2>&1; then pm=$(which pacman); silent_inst="-S --noconfirm --noprogressbar --quiet"; check_pkgs="-Sup"; docker_pkg="docker"; dist="archlinux";\ elif pm=$(which pacman 2>/dev/null || command -v pacman 2>/dev/null); then silent_inst="-S --noconfirm --noprogressbar --quiet"; what_pkg="-Sp"; check_pkgs="-Sup"; docker_pkg="docker"; dist="archlinux";\
else echo "Packet manager not found"; exit 1; fi;\ fi;\
echo "Dist: $dist, Packet manager: $pm, Install command: $silent_inst, Check pkgs command: $check_pkgs, Docker pkg: $docker_pkg";\ echo "Dist: $dist, Packet manager: $pm, Install command: $silent_inst, What pkg command: $what_pkg, Check pkgs command: $check_pkgs, Docker pkg: $docker_pkg, Language: $LANG";\
echo $LANG | grep -qE '^(en_US.UTF-8|C.UTF-8|C)$' || export LC_ALL=C;\
if [ "$dist" = "debian" ]; then export DEBIAN_FRONTEND=noninteractive; fi;\ if [ "$dist" = "debian" ]; then export DEBIAN_FRONTEND=noninteractive; fi;\
if ! command -v sudo > /dev/null 2>&1; then $pm $check_pkgs; $pm $silent_inst sudo; fi;\ if ! command -v sudo > /dev/null 2>&1; then $pm $check_pkgs; $pm $silent_inst sudo; fi;\
if ! command -v fuser > /dev/null 2>&1; then sudo $pm $check_pkgs; sudo $pm $silent_inst psmisc; fi;\ if ! sudo -n sh -c 'command -v which > /dev/null 2>&1'; then sudo -n $pm $check_pkgs; sudo -n $pm $silent_inst which; fi;\
if ! command -v lsof > /dev/null 2>&1; then sudo $pm $check_pkgs; sudo $pm $silent_inst lsof; fi;\ if ! sudo -n sh -c 'command -v fuser > /dev/null 2>&1'; then sudo -n $pm $check_pkgs; sudo -n $pm $silent_inst psmisc; fi;\
if ! command -v docker > /dev/null 2>&1; then \ if ! sudo -n sh -c 'command -v lsof > /dev/null 2>&1'; then sudo -n $pm $check_pkgs; sudo -n $pm $silent_inst lsof; fi;\
sudo $pm $check_pkgs; sudo $pm $silent_inst $docker_pkg;\ if ! sudo -n sh -c 'command -v docker > /dev/null 2>&1'; then \
sleep 5; sudo systemctl enable --now docker; sleep 5;\ sudo -n $pm $check_pkgs;\
if ! sudo -n $pm $what_pkg $docker_pkg 2>/dev/null | grep -qi podman; then \
sudo -n $pm $silent_inst $docker_pkg;\
sleep 5; sudo -n systemctl enable --now docker; sleep 5;\
else \
echo "Container runtime is not supported";\
exit 1;\
fi;\
fi;\ fi;\
if [ "$(cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = "Y" ]; then \ if [ "$(sudo -n cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = "Y" ]; then \
if ! command -v apparmor_parser > /dev/null 2>&1; then sudo $pm $check_pkgs; sudo $pm $silent_inst apparmor; fi;\ if ! sudo -n sh -c 'command -v apparmor_parser > /dev/null 2>&1'; then \
sudo -n $pm $check_pkgs; sudo -n $pm $silent_inst apparmor;\
fi;\
fi;\ fi;\
if [ "$(systemctl is-active docker)" != "active" ]; then \ if [ "$(sudo -n systemctl is-active docker)" != "active" ]; then \
sudo $pm $check_pkgs; sudo $pm $silent_inst $docker_pkg;\ sleep 5; sudo -n systemctl start docker; sleep 5;\
sleep 5; sudo systemctl start docker; sleep 5;\ if [ "$(sudo -n systemctl is-active docker)" != "active" ]; then echo "Container runtime service not running"; fi;\
fi;\ fi;\
if ! command -v sudo > /dev/null 2>&1; then echo "Failed to install sudo, command not found"; exit 1; fi;\ sudo -n docker --version || docker --version;\
docker --version;\
uname -sr uname -sr
@@ -1,6 +1,6 @@
sudo docker ps -a | grep amnezia | awk '{print $1}' | xargs sudo docker stop;\ sudo docker ps -a | grep amnezia | awk '{print $1}' | xargs sudo docker stop;\
sudo docker ps -a | grep amnezia | awk '{print $1}' | xargs sudo docker rm -fv;\ sudo docker ps -a | grep amnezia | awk '{print $1}' | xargs sudo docker rm -fv;\
sudo docker images -a --format table | grep amnezia | awk '{print $3, $1 ":" $2}' | xargs sudo docker rmi;\ sudo docker images -a --format table | grep amnezia | awk '{print $3, $1 ":" $2}' | xargs sudo docker rmi;\
sudo docker volume ls | grep amnezia | awk '{print $2}' | xargs sudo docker volume rm -f;\ sudo docker volume ls --format '{{.Name}}' | grep '^amnezia-' | xargs -r sudo docker volume rm -f;\
sudo docker network ls | grep amnezia-dns-net | awk '{print $1}' | xargs sudo docker network rm;\ sudo docker network ls | grep amnezia-dns-net | awk '{print $1}' | xargs sudo docker network rm;\
sudo rm -frd /opt/amnezia sudo rm -frd /opt/amnezia
+1 -2
View File
@@ -1,4 +1,3 @@
sudo docker stop $CONTAINER_NAME;\ sudo docker stop $CONTAINER_NAME;\
sudo docker rm -fv $CONTAINER_NAME;\ sudo docker rm -fv $CONTAINER_NAME;\
sudo docker rmi $CONTAINER_NAME;\ sudo docker rmi $CONTAINER_NAME;
test "$REMOVE_CONTAINER_DATA" = "1" && sudo docker volume rm -f ${CONTAINER_NAME}-data 2>/dev/null || true
@@ -475,8 +475,7 @@ bool SubscriptionUiController::deactivateExternalDevice(const QString &serverId,
void SubscriptionUiController::validateConfig() void SubscriptionUiController::validateConfig()
{ {
const QString serverId = m_serversController->getDefaultServerId(); const QString serverId = m_serversController->getDefaultServerId();
if (!serverId.isEmpty() && m_serversController->isLegacyApiV1Server(serverId)) { if (serverId.isEmpty()) {
emit unsupportedConnectDrawerRequested();
emit configValidated(false); emit configValidated(false);
return; return;
} }
@@ -8,6 +8,8 @@
#include "amneziaApplication.h" #include "amneziaApplication.h"
#include "core/controllers/serversController.h" #include "core/controllers/serversController.h"
#include "core/models/containerConfig.h"
#include "core/utils/containerEnum.h"
ConnectionUiController::ConnectionUiController(ConnectionController* connectionController, ConnectionUiController::ConnectionUiController(ConnectionController* connectionController,
ServersController* serversController, ServersController* serversController,
@@ -33,7 +35,7 @@ void ConnectionUiController::openConnection()
ErrorCode errorCode = m_connectionController->openConnection(serverId); ErrorCode errorCode = m_connectionController->openConnection(serverId);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
emit connectionErrorOccurred(errorCode); notifyConnectionBlocked(errorCode);
return; return;
} }
} }
@@ -130,10 +132,36 @@ void ConnectionUiController::toggleConnection()
} else if (isConnected()) { } else if (isConnected()) {
closeConnection(); closeConnection();
} else { } else {
const QString serverId = m_serversController->getDefaultServerId();
if (serverId.isEmpty()) {
return;
}
const ErrorCode errorCode = m_connectionController->isConnectionSupported(serverId);
if (errorCode != ErrorCode::NoError) {
notifyConnectionBlocked(errorCode);
return;
}
emit prepareConfig(); emit prepareConfig();
} }
} }
void ConnectionUiController::notifyConnectionBlocked(ErrorCode errorCode)
{
if (errorCode == ErrorCode::LegacyApiV1NotSupportedError) {
emit unsupportedConnectDrawerRequested();
return;
}
if (errorCode == ErrorCode::NoInstalledContainersError) {
emit noInstalledContainers();
return;
}
emit connectionErrorOccurred(errorCode);
}
bool ConnectionUiController::isConnectionInProgress() const bool ConnectionUiController::isConnectionInProgress() const
{ {
return m_isConnectionInProgress; return m_isConnectionInProgress;
@@ -143,3 +171,32 @@ bool ConnectionUiController::isConnected() const
{ {
return m_isConnected; return m_isConnected;
} }
bool ConnectionUiController::isRevokeBlockedDuringActiveConnection(const QString &serverId, int containerIndex,
const QString &clientId) const
{
if (clientId.isEmpty() || (!isConnected() && !isConnectionInProgress())) {
return false;
}
if (m_serversController->getDefaultServerId() != serverId) {
return false;
}
if (static_cast<int>(m_serversController->getDefaultContainer(serverId)) != containerIndex) {
return false;
}
const auto adminConfig = m_serversController->selfHostedAdminConfig(serverId);
if (!adminConfig.has_value()) {
return false;
}
const QString connectionClientId =
adminConfig->containerConfig(static_cast<DockerContainer>(containerIndex)).protocolConfig.clientId();
if (connectionClientId.isEmpty()) {
return false;
}
return connectionClientId == clientId || connectionClientId.contains(clientId);
}
@@ -35,6 +35,8 @@ public slots:
void openConnection(); void openConnection();
void closeConnection(); void closeConnection();
bool isRevokeBlockedDuringActiveConnection(const QString &serverId, int containerIndex, const QString &clientId) const;
ErrorCode getLastConnectionError(); ErrorCode getLastConnectionError();
void onConnectionStateChanged(Vpn::ConnectionState state); void onConnectionStateChanged(Vpn::ConnectionState state);
@@ -48,9 +50,12 @@ signals:
void connectButtonClicked(); void connectButtonClicked();
void preparingConfig(); void preparingConfig();
void prepareConfig(); void prepareConfig();
void unsupportedConnectDrawerRequested();
void noInstalledContainers();
private: private:
Vpn::ConnectionState getCurrentConnectionState(); Vpn::ConnectionState getCurrentConnectionState();
void notifyConnectionBlocked(ErrorCode errorCode);
ConnectionController* m_connectionController; ConnectionController* m_connectionController;
ServersController* m_serversController; ServersController* m_serversController;
@@ -75,13 +75,7 @@ InstallUiController::InstallUiController(InstallController *installController,
m_connectionController(connectionController) m_connectionController(connectionController)
{ {
connect(m_installController, &InstallController::configValidated, this, &InstallUiController::configValidated); connect(m_installController, &InstallController::configValidated, this, &InstallUiController::configValidated);
connect(m_installController, &InstallController::validationErrorOccurred, this, [this](ErrorCode errorCode) { connect(m_installController, &InstallController::validationErrorOccurred, this, &InstallUiController::installationErrorOccurred);
if (errorCode == ErrorCode::NoInstalledContainersError) {
emit noInstalledContainers();
} else {
emit installationErrorOccurred(errorCode);
}
});
} }
InstallUiController::~InstallUiController() InstallUiController::~InstallUiController()
@@ -217,15 +211,13 @@ void InstallUiController::scanServerForInstalledContainers(const QString &server
emit installationErrorOccurred(errorCode); emit installationErrorOccurred(errorCode);
} }
void InstallUiController::updateContainer(const QString &serverId, int containerIndex, int protocolIndex, bool closePage) bool InstallUiController::buildContainerConfigFromModel(int containerIndex, int protocolIndex, ContainerConfig &containerConfig)
{ {
DockerContainer container = static_cast<DockerContainer>(containerIndex); DockerContainer container = static_cast<DockerContainer>(containerIndex);
Proto protocolType = static_cast<Proto>(protocolIndex); Proto protocolType = static_cast<Proto>(protocolIndex);
ContainerConfig containerConfig;
containerConfig.container = container; containerConfig.container = container;
switch (protocolType) { switch (protocolType) {
case Proto::Awg: { case Proto::Awg: {
containerConfig.protocolConfig = m_awgConfigModel->getProtocolConfig(); containerConfig.protocolConfig = m_awgConfigModel->getProtocolConfig();
@@ -271,6 +263,41 @@ void InstallUiController::updateContainer(const QString &serverId, int container
} }
#endif #endif
default: default:
return false;
}
return true;
}
void InstallUiController::updateClientConfig(const QString &serverId, int containerIndex, int protocolIndex, bool closePage)
{
DockerContainer container = static_cast<DockerContainer>(containerIndex);
Proto protocolType = static_cast<Proto>(protocolIndex);
ContainerConfig containerConfig;
if (!buildContainerConfigFromModel(containerIndex, protocolIndex, containerConfig)) {
return;
}
ErrorCode errorCode = m_installController->updateClientConfig(serverId, container, containerConfig);
if (errorCode == ErrorCode::NoError) {
ContainerConfig updatedConfig = m_serversController->getContainerConfig(serverId, container);
m_protocolModel->updateModel(updatedConfig);
updateProtocolConfigModel(serverId, static_cast<int>(container), static_cast<int>(protocolType));
emit updateContainerFinished(tr("Settings updated successfully"), closePage);
return;
}
emit installationErrorOccurred(errorCode);
}
void InstallUiController::updateServerConfig(const QString &serverId, int containerIndex, int protocolIndex, bool closePage)
{
DockerContainer container = static_cast<DockerContainer>(containerIndex);
Proto protocolType = static_cast<Proto>(protocolIndex);
ContainerConfig containerConfig;
if (!buildContainerConfigFromModel(containerIndex, protocolIndex, containerConfig)) {
return; return;
} }
ContainerConfig oldContainerConfig = m_serversController->getContainerConfig(serverId, container); ContainerConfig oldContainerConfig = m_serversController->getContainerConfig(serverId, container);
@@ -305,13 +332,13 @@ void InstallUiController::updateContainer(const QString &serverId, int container
QFuture<ErrorCode> future = QFuture<ErrorCode> future =
QtConcurrent::run([installController, serverId, container, oldConfigCopy, QtConcurrent::run([installController, serverId, container, oldConfigCopy,
newConfigCopy]() mutable -> ErrorCode { newConfigCopy]() mutable -> ErrorCode {
return installController->updateContainer(serverId, container, oldConfigCopy, newConfigCopy); return installController->updateServerConfig(serverId, container, oldConfigCopy, newConfigCopy);
}); });
watcher->setFuture(future); watcher->setFuture(future);
return; return;
} }
ErrorCode errorCode = m_installController->updateContainer(serverId, container, oldContainerConfig, containerConfig); ErrorCode errorCode = m_installController->updateServerConfig(serverId, container, oldContainerConfig, containerConfig);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
ContainerConfig updatedConfig = m_serversController->getContainerConfig(serverId, container); ContainerConfig updatedConfig = m_serversController->getContainerConfig(serverId, container);
@@ -64,7 +64,8 @@ public slots:
void scanServerForInstalledContainers(const QString &serverId); void scanServerForInstalledContainers(const QString &serverId);
void updateContainer(const QString &serverId, int containerIndex, int protocolIndex, bool closePage = true); void updateServerConfig(const QString &serverId, int containerIndex, int protocolIndex, bool closePage = true);
void updateClientConfig(const QString &serverId, int containerIndex, int protocolIndex, bool closePage = true);
void removeServer(const QString &serverId); void removeServer(const QString &serverId);
void rebootServer(const QString &serverId); void rebootServer(const QString &serverId);
@@ -132,7 +133,6 @@ signals:
void cachedProfileCleared(const QString &message); void cachedProfileCleared(const QString &message);
void apiConfigRemoved(const QString &message); void apiConfigRemoved(const QString &message);
void noInstalledContainers();
void configValidated(bool isValid); void configValidated(bool isValid);
private: private:
@@ -162,6 +162,8 @@ private:
QString m_privateKeyPassphrase; QString m_privateKeyPassphrase;
void updateProtocolConfigModel(const QString &serverId, int containerIndex, int protocolIndex); void updateProtocolConfigModel(const QString &serverId, int containerIndex, int protocolIndex);
bool buildContainerConfigFromModel(int containerIndex, int protocolIndex, ContainerConfig &containerConfig);
}; };
#endif // INSTALLUICONTROLLER_H #endif // INSTALLUICONTROLLER_H
+18 -13
View File
@@ -156,7 +156,17 @@ void ServersUiController::updateModel()
m_serversModel->updateModel(m_orderedServerDescriptions, defaultServerId); m_serversModel->updateModel(m_orderedServerDescriptions, defaultServerId);
updateContainersModel(); if (!m_processedServerId.isEmpty()) {
if (isServerFromApi(m_processedServerId)) {
const auto &description = serverDescriptionById(m_processedServerId);
if (description.isApiV2 && description.isCountrySelectionAvailable
&& !description.apiAvailableCountries.isEmpty()) {
emit updateApiCountryModel();
}
} else {
updateContainersModel();
}
}
updateDefaultServerContainersModel(); updateDefaultServerContainersModel();
if (hadServersFromGatewayBefore != hasServersFromGatewayNow) { if (hadServersFromGatewayBefore != hasServersFromGatewayNow) {
@@ -350,19 +360,14 @@ void ServersUiController::setProcessedServerId(const QString &serverId)
m_processedServerId = normalizedServerId; m_processedServerId = normalizedServerId;
if (newIndex >= 0) { if (newIndex >= 0) {
updateContainersModel(); if (isServerFromApi(m_processedServerId)) {
const auto &description = serverDescriptionById(m_processedServerId);
for (const auto &description : m_orderedServerDescriptions) { if (description.isApiV2 && description.isCountrySelectionAvailable
if (description.serverId != normalizedServerId) { && !description.apiAvailableCountries.isEmpty()) {
continue; emit updateApiCountryModel();
} }
if (description.isApiV2) { } else {
if (description.isCountrySelectionAvailable && !description.apiAvailableCountries.isEmpty()) { updateContainersModel();
emit updateApiCountryModel();
}
emit updateApiServicesModel();
}
break;
} }
} }
@@ -113,7 +113,6 @@ signals:
void processedContainerIndexChanged(int index); void processedContainerIndexChanged(int index);
void hasServersFromGatewayApiChanged(); void hasServersFromGatewayApiChanged();
void updateApiCountryModel(); void updateApiCountryModel();
void updateApiServicesModel();
public: public:
void updateModel(); void updateModel();
@@ -22,12 +22,10 @@
SettingsUiController::SettingsUiController(SettingsController* settingsController, SettingsUiController::SettingsUiController(SettingsController* settingsController,
ServersController* serversController, ServersController* serversController,
LanguageUiController* languageUiController,
QObject *parent) QObject *parent)
: QObject(parent), : QObject(parent),
m_settingsController(settingsController), m_settingsController(settingsController),
m_serversController(serversController), m_serversController(serversController)
m_languageUiController(languageUiController)
{ {
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
connect(AndroidController::instance(), &AndroidController::notificationStateChanged, this, &SettingsUiController::onNotificationStateChanged); connect(AndroidController::instance(), &AndroidController::notificationStateChanged, this, &SettingsUiController::onNotificationStateChanged);
@@ -157,13 +155,13 @@ void SettingsUiController::restoreAppConfigFromData(const QByteArray &data)
{ {
ErrorCode errorCode = m_settingsController->restoreAppConfigFromData(data); ErrorCode errorCode = m_settingsController->restoreAppConfigFromData(data);
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
emit appLanguageChanged( emit appLanguageChanged();
static_cast<LanguageSettings::AvailableLanguageEnum>(m_languageUiController->getCurrentLanguageIndex()));
bool amneziaDnsEnabled = m_settingsController->isAmneziaDnsEnabled(); bool amneziaDnsEnabled = m_settingsController->isAmneziaDnsEnabled();
emit amneziaDnsToggled(amneziaDnsEnabled); emit amneziaDnsToggled(amneziaDnsEnabled);
emit restoreBackupFinished(); emit restoreBackupFinished();
emit autoStartChanged();
emit startMinimizedChanged(); emit startMinimizedChanged();
} else { } else {
emit errorOccurred(errorCode); emit errorOccurred(errorCode);
@@ -178,6 +176,7 @@ QString SettingsUiController::getAppVersion()
void SettingsUiController::clearSettings() void SettingsUiController::clearSettings()
{ {
m_settingsController->clearSettings(); m_settingsController->clearSettings();
emit autoStartChanged();
emit startMinimizedChanged(); emit startMinimizedChanged();
emit resetLanguageToSystem(); emit resetLanguageToSystem();
@@ -206,9 +205,8 @@ bool SettingsUiController::isAutoStartEnabled()
void SettingsUiController::toggleAutoStart(bool enable) void SettingsUiController::toggleAutoStart(bool enable)
{ {
m_settingsController->toggleAutoStart(enable); m_settingsController->toggleAutoStart(enable);
if (!enable) { emit autoStartChanged();
emit startMinimizedChanged(); emit startMinimizedChanged();
}
} }
bool SettingsUiController::isStartMinimizedEnabled() bool SettingsUiController::isStartMinimizedEnabled()
+3 -5
View File
@@ -5,8 +5,6 @@
#include "core/controllers/settingsController.h" #include "core/controllers/settingsController.h"
#include "core/controllers/serversController.h" #include "core/controllers/serversController.h"
#include "ui/controllers/languageUiController.h"
#include "ui/models/languageModel.h"
#include "core/utils/errorCodes.h" #include "core/utils/errorCodes.h"
#include "core/utils/routeModes.h" #include "core/utils/routeModes.h"
#include "core/utils/commonStructs.h" #include "core/utils/commonStructs.h"
@@ -17,7 +15,6 @@ class SettingsUiController : public QObject
public: public:
explicit SettingsUiController(SettingsController* settingsController, explicit SettingsUiController(SettingsController* settingsController,
ServersController* serversController, ServersController* serversController,
LanguageUiController* languageUiController,
QObject *parent = nullptr); QObject *parent = nullptr);
Q_PROPERTY(QString primaryDns READ getPrimaryDns WRITE setPrimaryDns NOTIFY primaryDnsChanged) Q_PROPERTY(QString primaryDns READ getPrimaryDns WRITE setPrimaryDns NOTIFY primaryDnsChanged)
@@ -32,6 +29,7 @@ public:
Q_PROPERTY(bool isDevGatewayEnv READ isDevGatewayEnv WRITE toggleDevGatewayEnv NOTIFY devGatewayEnvChanged) Q_PROPERTY(bool isDevGatewayEnv READ isDevGatewayEnv WRITE toggleDevGatewayEnv NOTIFY devGatewayEnvChanged)
Q_PROPERTY(bool isHomeAdLabelVisible READ isHomeAdLabelVisible NOTIFY isHomeAdLabelVisibleChanged) Q_PROPERTY(bool isHomeAdLabelVisible READ isHomeAdLabelVisible NOTIFY isHomeAdLabelVisibleChanged)
Q_PROPERTY(bool autoStartEnabled READ isAutoStartEnabled NOTIFY autoStartChanged)
Q_PROPERTY(bool startMinimized READ isStartMinimizedEnabled NOTIFY startMinimizedChanged) Q_PROPERTY(bool startMinimized READ isStartMinimizedEnabled NOTIFY startMinimizedChanged)
public slots: public slots:
@@ -122,7 +120,7 @@ signals:
void loggingDisableByWatcher(); void loggingDisableByWatcher();
void appLanguageChanged(const LanguageSettings::AvailableLanguageEnum language); void appLanguageChanged();
void resetLanguageToSystem(); void resetLanguageToSystem();
void onNotificationStateChanged(); void onNotificationStateChanged();
@@ -135,12 +133,12 @@ signals:
void activityResumed(); void activityResumed();
void isHomeAdLabelVisibleChanged(bool visible); void isHomeAdLabelVisibleChanged(bool visible);
void autoStartChanged();
void startMinimizedChanged(); void startMinimizedChanged();
private: private:
SettingsController* m_settingsController; SettingsController* m_settingsController;
ServersController* m_serversController; ServersController* m_serversController;
LanguageUiController* m_languageUiController;
}; };
#endif #endif
+1 -1
View File
@@ -30,7 +30,7 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case SubscriptionStatusRole: { case SubscriptionStatusRole: {
if (m_accountInfoData.configType == serverConfigUtils::ConfigType::AmneziaFreeV3) { if (m_accountInfoData.configType == serverConfigUtils::ConfigType::AmneziaFreeV3) {
return tr("Active"); return QStringLiteral("<p><a style=\"color: #28c840;\">%1</a>").arg(tr("Active"));
} }
return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate) return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate)
@@ -27,6 +27,7 @@ QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
auto userData = client.value(configKey::userData).toObject(); auto userData = client.value(configKey::userData).toObject();
switch (role) { switch (role) {
case ClientIdRole: return client.value(configKey::clientId).toString();
case ClientNameRole: return userData.value(configKey::clientName).toString(); case ClientNameRole: return userData.value(configKey::clientName).toString();
case CreationDateRole: return userData.value(configKey::creationDate).toString(); case CreationDateRole: return userData.value(configKey::creationDate).toString();
case LatestHandshakeRole: return userData.value(configKey::latestHandshake).toString(); case LatestHandshakeRole: return userData.value(configKey::latestHandshake).toString();
@@ -62,6 +63,7 @@ void ClientManagementModel::updateClientName(int row, const QString &newName)
QHash<int, QByteArray> ClientManagementModel::roleNames() const QHash<int, QByteArray> ClientManagementModel::roleNames() const
{ {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[ClientIdRole] = "clientId";
roles[ClientNameRole] = "clientName"; roles[ClientNameRole] = "clientName";
roles[CreationDateRole] = "creationDate"; roles[CreationDateRole] = "creationDate";
roles[LatestHandshakeRole] = "latestHandshake"; roles[LatestHandshakeRole] = "latestHandshake";
+2 -1
View File
@@ -10,7 +10,8 @@ class ClientManagementModel : public QAbstractListModel
public: public:
enum Roles { enum Roles {
ClientNameRole = Qt::UserRole + 1, ClientIdRole = Qt::UserRole + 1,
ClientNameRole,
CreationDateRole, CreationDateRole,
LatestHandshakeRole, LatestHandshakeRole,
DataReceivedRole, DataReceivedRole,
+4
View File
@@ -23,6 +23,10 @@ public:
Q_INVOKABLE int containerFromString(const QString &container) const { Q_INVOKABLE int containerFromString(const QString &container) const {
return static_cast<int>(amnezia::ContainerUtils::containerFromString(container)); return static_cast<int>(amnezia::ContainerUtils::containerFromString(container));
} }
Q_INVOKABLE bool isUnsupportedContainer(int containerIndex) const {
return amnezia::ContainerUtils::isUnsupportedContainer(static_cast<amnezia::DockerContainer>(containerIndex));
}
}; };
#endif // CONTAINERPROPS_H #endif // CONTAINERPROPS_H
+4 -1
View File
@@ -67,6 +67,7 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const
case IsCurrentlyProcessedRole: return container == static_cast<DockerContainer>(m_processedContainerIndex); case IsCurrentlyProcessedRole: return container == static_cast<DockerContainer>(m_processedContainerIndex);
case IsSupportedRole: return ContainerUtils::isSupportedByCurrentPlatform(container); case IsSupportedRole: return ContainerUtils::isSupportedByCurrentPlatform(container);
case IsShareableRole: return ContainerUtils::isShareable(container); case IsShareableRole: return ContainerUtils::isShareable(container);
case IsUnsupportedContainerRole: return ContainerUtils::isUnsupportedContainer(container);
case IsVpnContainerRole: return ContainerUtils::containerService(container) == ServiceType::Vpn; case IsVpnContainerRole: return ContainerUtils::containerService(container) == ServiceType::Vpn;
case IsServiceContainerRole: return ContainerUtils::containerService(container) == ServiceType::Other; case IsServiceContainerRole: return ContainerUtils::containerService(container) == ServiceType::Other;
case IsIpsecRole: return container == DockerContainer::Ipsec; case IsIpsecRole: return container == DockerContainer::Ipsec;
@@ -142,7 +143,8 @@ bool ContainersModel::hasInstalledProtocols()
bool ContainersModel::isInstallationAllowed(DockerContainer container) bool ContainersModel::isInstallationAllowed(DockerContainer container)
{ {
return container != DockerContainer::Awg; return container != DockerContainer::Awg
&& !ContainerUtils::isUnsupportedContainer(container);
} }
void ContainersModel::openContainerSettings(int containerIndex) void ContainersModel::openContainerSettings(int containerIndex)
@@ -176,6 +178,7 @@ QHash<int, QByteArray> ContainersModel::roleNames() const
roles[IsCurrentlyProcessedRole] = "isCurrentlyProcessed"; roles[IsCurrentlyProcessedRole] = "isCurrentlyProcessed";
roles[IsSupportedRole] = "isSupported"; roles[IsSupportedRole] = "isSupported";
roles[IsShareableRole] = "isShareable"; roles[IsShareableRole] = "isShareable";
roles[IsUnsupportedContainerRole] = "isUnsupportedContainer";
roles[IsInstallationAllowedRole] = "isInstallationAllowed"; roles[IsInstallationAllowedRole] = "isInstallationAllowed";
roles[InstallPageOrderRole] = "installPageOrder"; roles[InstallPageOrderRole] = "installPageOrder";
+2
View File
@@ -39,6 +39,8 @@ public:
IsSupportedRole, IsSupportedRole,
IsShareableRole, IsShareableRole,
IsUnsupportedContainerRole,
InstallPageOrderRole, InstallPageOrderRole,
// Container type check roles // Container type check roles
@@ -56,14 +56,17 @@ ListViewType {
return return
} }
if (checked) { var containerIndex = proxyDefaultServerContainersModel.mapToSource(index)
containersDropDown.closeTriggered()
ServersUiController.setDefaultContainer(ServersUiController.defaultServerId, proxyDefaultServerContainersModel.mapToSource(index)) if (!isInstalled) {
} else { ServersUiController.processedContainerIndex = containerIndex
ServersUiController.processedContainerIndex = proxyDefaultServerContainersModel.mapToSource(index)
PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings) PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings)
containersDropDown.closeTriggered() containersDropDown.closeTriggered()
return
} }
containersDropDown.closeTriggered()
ServersUiController.setDefaultContainer(ServersUiController.defaultServerId, containerIndex)
} }
MouseArea { MouseArea {
@@ -5,7 +5,6 @@ import QtQuick.Layouts
import SortFilterProxyModel 0.2 import SortFilterProxyModel 0.2
import PageEnum 1.0 import PageEnum 1.0
import ContainerProps 1.0
import "../Controls2" import "../Controls2"
import "../Controls2/TextTypes" import "../Controls2/TextTypes"
+30 -9
View File
@@ -6,8 +6,36 @@ Menu {
popupType: Popup.Native popupType: Popup.Native
onAboutToShow: blocker.enabled = true property Item inputBlocker: null
onClosed: blocker.enabled = false
Component {
id: inputBlockerComponent
MouseArea {
anchors.fill: parent
preventStealing: true
}
}
onAboutToShow: {
if (!textObj || !textObj.window) {
return
}
const contentItem = textObj.window.contentItem
if (!inputBlocker) {
inputBlocker = inputBlockerComponent.createObject(contentItem)
} else {
inputBlocker.parent = contentItem
}
}
onClosed: {
if (inputBlocker) {
inputBlocker.destroy()
inputBlocker = null
}
}
MenuItem { MenuItem {
text: qsTr("C&ut") text: qsTr("C&ut")
@@ -31,11 +59,4 @@ Menu {
enabled: textObj.length > 0 enabled: textObj.length > 0
onTriggered: textObj.selectAll() onTriggered: textObj.selectAll()
} }
MouseArea {
id: blocker
z: 2
enabled: false
preventStealing: true
}
} }
+2 -2
View File
@@ -25,8 +25,8 @@ PageType {
filters: [ filters: [
ValueFilter { ValueFilter {
roleName: "isCurrentlyProcessed" roleName: "serverId"
value: true value: ServersUiController.processedServerId
} }
] ]
} }
@@ -440,8 +440,7 @@ PageType {
return return
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); InstallController.updateClientConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Awg)
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Awg)
} }
var noButtonFunction = function() {} var noButtonFunction = function() {}
@@ -561,7 +561,7 @@ PageType {
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Awg) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Awg)
} }
var noButtonFunction = function() {} var noButtonFunction = function() {}
@@ -434,7 +434,7 @@ PageType {
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.OpenVpn) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.OpenVpn)
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) { if (!GC.isMobile()) {
@@ -128,8 +128,7 @@ PageType {
return return
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); InstallController.updateClientConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.WireGuard)
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.WireGuard)
} }
var noButtonFunction = function() {} var noButtonFunction = function() {}
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
@@ -129,7 +129,7 @@ PageType {
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.WireGuard) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.WireGuard)
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) { if (!GC.isMobile()) {
@@ -112,7 +112,7 @@ PageType {
return return
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling) PageController.goToPage(PageEnum.PageSetupWizardInstalling)
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray)
} }
var noButtonFunction = function () { var noButtonFunction = function () {
if (typeof GC !== "undefined" && !GC.isMobile()) { if (typeof GC !== "undefined" && !GC.isMobile()) {
@@ -279,7 +279,7 @@ PageType {
return return
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling) PageController.goToPage(PageEnum.PageSetupWizardInstalling)
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray)
} }
var noButtonFunction = function () { var noButtonFunction = function () {
if (typeof GC !== "undefined" && !GC.isMobile()) { if (typeof GC !== "undefined" && !GC.isMobile()) {
@@ -213,7 +213,7 @@ PageType {
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling); PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray)
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) saveButton.forceActiveFocus() if (!GC.isMobile()) saveButton.forceActiveFocus()
@@ -742,7 +742,7 @@ PageType {
return return
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling) PageController.goToPage(PageEnum.PageSetupWizardInstalling)
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray)
} }
var noButtonFunction = function () { var noButtonFunction = function () {
if (typeof GC !== "undefined" && !GC.isMobile()) { if (typeof GC !== "undefined" && !GC.isMobile()) {
@@ -95,7 +95,7 @@ PageType {
return return
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling) PageController.goToPage(PageEnum.PageSetupWizardInstalling)
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray)
} }
var noButtonFunction = function () { var noButtonFunction = function () {
if (typeof GC !== "undefined" && !GC.isMobile()) { if (typeof GC !== "undefined" && !GC.isMobile()) {
@@ -211,7 +211,7 @@ PageType {
return return
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling) PageController.goToPage(PageEnum.PageSetupWizardInstalling)
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray)
} }
var noButtonFunction = function () { var noButtonFunction = function () {
if (typeof GC !== "undefined" && !GC.isMobile()) { if (typeof GC !== "undefined" && !GC.isMobile()) {
@@ -208,7 +208,7 @@ PageType {
return return
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling) PageController.goToPage(PageEnum.PageSetupWizardInstalling)
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Xray)
} }
var noButtonFunction = function () { var noButtonFunction = function () {
if (typeof GC !== "undefined" && !GC.isMobile()) { if (typeof GC !== "undefined" && !GC.isMobile()) {
@@ -179,7 +179,7 @@ PageType {
function mtProxyScheduleUpdate(closePage) { function mtProxyScheduleUpdate(closePage) {
var cp = closePage === undefined ? false : closePage var cp = closePage === undefined ? false : closePage
Qt.callLater(function () { Qt.callLater(function () {
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.MtProxy, cp) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.MtProxy, cp)
}) })
} }
@@ -285,7 +285,7 @@ PageType {
} }
PageController.goToPage(PageEnum.PageSetupWizardInstalling) PageController.goToPage(PageEnum.PageSetupWizardInstalling)
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Socks5Proxy) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Socks5Proxy)
tempPort = portTextField.textField.text tempPort = portTextField.textField.text
tempUsername = usernameTextField.textField.text tempUsername = usernameTextField.textField.text
tempPassword = passwordTextField.textField.text tempPassword = passwordTextField.textField.text
@@ -154,7 +154,7 @@ PageType {
function telemtScheduleUpdate(closePage) { function telemtScheduleUpdate(closePage) {
var cp = closePage === undefined ? false : closePage var cp = closePage === undefined ? false : closePage
Qt.callLater(function () { Qt.callLater(function () {
InstallController.updateContainer(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Telemt, cp) InstallController.updateServerConfig(ServersUiController.processedServerId, ServersUiController.processedContainerIndex, ProtocolEnum.Telemt, cp)
}) })
} }
@@ -100,6 +100,12 @@ PageType {
onLinkActivated: Qt.openUrlExternally(link) onLinkActivated: Qt.openUrlExternally(link)
textFormat: Text.RichText textFormat: Text.RichText
text: qsTr("Use <a href=\"https://www.torproject.org/download/\" style=\"color: #FBB26A;\">Tor Browser</a> to open this URL.") text: qsTr("Use <a href=\"https://www.torproject.org/download/\" style=\"color: #FBB26A;\">Tor Browser</a> to open this URL.")
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
} }
ParagraphTextType { ParagraphTextType {
@@ -30,6 +30,16 @@ PageType {
root.isInAppPurchase = ApiAccountInfoModel.data("isInAppPurchase") root.isInAppPurchase = ApiAccountInfoModel.data("isInAppPurchase")
} }
function selectConnectionCountry(countryIndex, countryCode, countryName) {
if (countryIndex === ApiCountryModel.currentIndex) {
return
}
PageController.showBusyIndicator(true)
SubscriptionUiController.updateServiceFromGateway(ServersUiController.processedServerId, countryCode, countryName)
PageController.showBusyIndicator(false)
}
Component.onCompleted: { Component.onCompleted: {
root.updateSubscriptionState() root.updateSubscriptionState()
} }
@@ -83,7 +93,7 @@ PageType {
model: ApiCountryModel model: ApiCountryModel
currentIndex: 0 currentIndex: ApiCountryModel.currentIndex
ButtonGroup { ButtonGroup {
id: containersRadioButtonGroup id: containersRadioButtonGroup
@@ -204,15 +214,7 @@ PageType {
return return
} }
if (index !== ApiCountryModel.currentIndex) { root.selectConnectionCountry(index, countryCode, countryName)
PageController.showBusyIndicator(true)
var prevIndex = ApiCountryModel.currentIndex
ApiCountryModel.currentIndex = index
if (!SubscriptionUiController.updateServiceFromGateway(ServersUiController.processedServerId, countryCode, countryName)) {
ApiCountryModel.currentIndex = prevIndex
}
PageController.showBusyIndicator(false)
}
} }
Keys.onEnterPressed: { Keys.onEnterPressed: {
@@ -108,9 +108,9 @@ PageType {
text: qsTr("Auto start") text: qsTr("Auto start")
descriptionText: qsTr("Launch the application every time the device is starts") descriptionText: qsTr("Launch the application every time the device is starts")
checked: SettingsController.isAutoStartEnabled() checked: SettingsController.autoStartEnabled
onToggled: function() { onToggled: function() {
if (checked !== SettingsController.isAutoStartEnabled()) { if (checked !== SettingsController.autoStartEnabled) {
SettingsController.toggleAutoStart(checked) SettingsController.toggleAutoStart(checked)
} }
} }
@@ -154,10 +154,10 @@ PageType {
text: qsTr("Start minimized") text: qsTr("Start minimized")
descriptionText: qsTr("Launch application minimized (works with autostart option turned on)") descriptionText: qsTr("Launch application minimized (works with autostart option turned on)")
enabled: SettingsController.isAutoStartEnabled() enabled: SettingsController.autoStartEnabled
opacity: enabled ? 1.0 : 0.5 opacity: enabled ? 1.0 : 0.5
checked: SettingsController.isAutoStartEnabled() && SettingsController.startMinimized checked: SettingsController.autoStartEnabled && SettingsController.startMinimized
onToggled: function() { onToggled: function() {
if (checked !== SettingsController.startMinimized) { if (checked !== SettingsController.startMinimized) {
SettingsController.toggleStartMinimized(checked) SettingsController.toggleStartMinimized(checked)
@@ -166,7 +166,7 @@ PageType {
} }
DividerType { DividerType {
visible: !GC.isMobile() visible: !GC.isMobile() && ServersUiController.hasServersFromGatewayApi
} }
SwitcherType { SwitcherType {
@@ -36,17 +36,6 @@ PageType {
function onRebootServerFinished(finishedMessage) { function onRebootServerFinished(finishedMessage) {
PageController.showNotificationMessage(finishedMessage) PageController.showNotificationMessage(finishedMessage)
} }
function onRemoveAllContainersFinished(finishedMessage) {
PageController.closePage() // close deInstalling page
PageController.showNotificationMessage(finishedMessage)
}
function onRemoveContainerFinished(finishedMessage) {
PageController.closePage() // close deInstalling page
PageController.closePage() // close page with remove button
PageController.showNotificationMessage(finishedMessage)
}
} }
Connections { Connections {
@@ -17,7 +17,8 @@ import "../Components"
PageType { PageType {
id: root id: root
property bool isClearCacheVisible: ServersUiController.isProcessedServerHasWriteAccess() && !ContainersModel.isServiceContainer(ServersUiController.processedContainerIndex) property bool isUnsupportedContainer: ContainerProps.isUnsupportedContainer(ServersUiController.processedContainerIndex)
property bool isClearCacheVisible: !isUnsupportedContainer && ServersUiController.isProcessedServerHasWriteAccess() && !ContainersModel.isServiceContainer(ServersUiController.processedContainerIndex)
BackButtonType { BackButtonType {
id: backButton id: backButton
@@ -52,10 +53,11 @@ PageType {
Layout.bottomMargin: 32 Layout.bottomMargin: 32
headerText: ContainersModel.getProcessedContainerName() + qsTr(" settings") headerText: ContainersModel.getProcessedContainerName() + qsTr(" settings")
descriptionText: root.isUnsupportedContainer ? qsTr("This protocol is no longer supported.") : ""
} }
} }
model: ProtocolsModel model: root.isUnsupportedContainer ? null : ProtocolsModel
delegate: ColumnLayout { delegate: ColumnLayout {
id: delegateContent id: delegateContent
@@ -29,6 +29,10 @@ PageType {
ValueFilter { ValueFilter {
roleName: "isInstallationAllowed" roleName: "isInstallationAllowed"
value: true value: true
},
ValueFilter {
roleName: "isUnsupportedContainer"
value: false
} }
] ]
sorters: RoleSorter { sorters: RoleSorter {
+20 -7
View File
@@ -382,6 +382,10 @@ PageType {
ValueFilter { ValueFilter {
roleName: "isShareable" roleName: "isShareable"
value: true value: true
},
ValueFilter {
roleName: "isUnsupportedContainer"
value: false
} }
] ]
} }
@@ -396,9 +400,19 @@ PageType {
target: serverSelector target: serverSelector
function onServerSelectorIndexChanged() { function onServerSelectorIndexChanged() {
var defaultContainer = proxyContainersModel.mapFromSource(ServersUiController.serverDefaultContainer(ServersUiController.processedServerId)) if (!proxyContainersModel.count) {
root.shareButtonEnabled = false
return
}
var defaultContainer = proxyContainersModel.mapFromSource(
ServersUiController.serverDefaultContainer(ServersUiController.processedServerId))
if (defaultContainer < 0) {
defaultContainer = 0
}
containerSelectorListView.selectedIndex = defaultContainer containerSelectorListView.selectedIndex = defaultContainer
containerSelectorListView.positionViewAtIndex(selectedIndex, ListView.Beginning) containerSelectorListView.positionViewAtIndex(defaultContainer, ListView.Beginning)
containerSelectorListView.triggerCurrentItem() containerSelectorListView.triggerCurrentItem()
} }
} }
@@ -837,11 +851,10 @@ PageType {
var noButtonFunction = function() { var noButtonFunction = function() {
} }
var isActiveConfigForCurrentClient = ServersUiController.isDefaultServerCurrentlyProcessed() if (ConnectionController.isRevokeBlockedDuringActiveConnection(
&& ServersUiController.serverDefaultContainer(ServersUiController.defaultServerId) === ServersUiController.processedContainerIndex ServersUiController.processedServerId,
ServersUiController.processedContainerIndex,
if ((ConnectionController.isConnectionInProgress || ConnectionController.isConnected) clientId)) {
&& isActiveConfigForCurrentClient) {
PageController.showNotificationMessage("Unable to revoke current config during active connection") PageController.showNotificationMessage("Unable to revoke current config during active connection")
} else { } else {
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
+25 -4
View File
@@ -105,6 +105,19 @@ PageType {
} }
} }
Connections {
objectName: "connectionControllerConnections"
target: ConnectionController
function onNoInstalledContainers() {
PageController.setTriggeredByConnectButton(true)
ServersUiController.setProcessedServerId(ServersUiController.defaultServerId)
PageController.goToPage(PageEnum.PageSetupWizardEasy)
}
}
Connections { Connections {
objectName: "installControllerConnections" objectName: "installControllerConnections"
@@ -153,11 +166,19 @@ PageType {
PageController.showNotificationMessage(finishedMessage) PageController.showNotificationMessage(finishedMessage)
} }
function onNoInstalledContainers() { function onRemoveAllContainersFinished(finishedMessage) {
PageController.setTriggeredByConnectButton(true) if (tabBarStackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageDeinstalling)) {
PageController.closePage()
}
PageController.showNotificationMessage(finishedMessage)
}
ServersUiController.setProcessedServerId(ServersUiController.defaultServerId) function onRemoveContainerFinished(finishedMessage) {
PageController.goToPage(PageEnum.PageSetupWizardEasy) if (tabBarStackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageDeinstalling)) {
PageController.closePage()
}
PageController.closePage()
PageController.showNotificationMessage(finishedMessage)
} }
} }
+8
View File
@@ -234,6 +234,8 @@ Window {
DrawerType2 { DrawerType2 {
id: privateKeyPassphraseDrawer id: privateKeyPassphraseDrawer
property bool isCloseByUser: false
anchors.fill: parent anchors.fill: parent
expandedHeight: root.height * 0.35 + PageController.safeAreaBottomMargin + PageController.imeHeight expandedHeight: root.height * 0.35 + PageController.safeAreaBottomMargin + PageController.imeHeight
@@ -253,6 +255,11 @@ Window {
} }
function onAboutToHide() { function onAboutToHide() {
if (privateKeyPassphraseDrawer.isCloseByUser === false) {
privateKeyPassphraseDrawer.isCloseByUser = true
PageController.passphraseRequestDrawerClosed("")
}
if (passphrase.textField.text !== "") { if (passphrase.textField.text !== "") {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
} }
@@ -293,6 +300,7 @@ Window {
text: qsTr("Save") text: qsTr("Save")
clickedFunc: function() { clickedFunc: function() {
privateKeyPassphraseDrawer.isCloseByUser = true
privateKeyPassphraseDrawer.closeTriggered() privateKeyPassphraseDrawer.closeTriggered()
PageController.passphraseRequestDrawerClosed(passphrase.textField.text) PageController.passphraseRequestDrawerClosed(passphrase.textField.text)
} }
+4 -4
View File
@@ -19,12 +19,12 @@ class AmneziaVPN(ConanFile):
if has_service: if has_service:
if os == "Windows": if os == "Windows":
self.requires("awg-windows/0.1.8") self.requires("awg-windows/0.1.9")
self.requires("tap-windows6/9.27.0") self.requires("tap-windows6/9.27.0")
self.requires("win-split-tunnel/1.2.5.0") self.requires("win-split-tunnel/1.2.5.0")
self.requires("wintun/0.14.1") self.requires("wintun/0.14.1")
else: else:
self.requires("awg-go/0.2.16") self.requires("awg-go/0.2.18")
self.requires("amnezia-xray-bindings/1.1.0") self.requires("amnezia-xray-bindings/1.1.0")
self.requires("tun2socks/2.6.0") self.requires("tun2socks/2.6.0")
@@ -32,13 +32,13 @@ class AmneziaVPN(ConanFile):
self.requires("v2ray-rules-dat/202603162227") self.requires("v2ray-rules-dat/202603162227")
if has_ne: if has_ne:
self.requires("awg-apple/2.0.1") self.requires("awg-apple/2.0.2")
self.requires("hev-socks5-tunnel/2.15.0", options={"as_framework": True}) self.requires("hev-socks5-tunnel/2.15.0", options={"as_framework": True})
self.requires("openvpnadapter/1.0.0") self.requires("openvpnadapter/1.0.0")
if os == "Android": if os == "Android":
self.requires("amnezia-libxray/1.0.0") self.requires("amnezia-libxray/1.0.0")
self.requires("awg-android/1.1.7") self.requires("awg-android/2.0.1")
self.requires("openvpn-pt-android/1.0.0") self.requires("openvpn-pt-android/1.0.0")
# expicitly use libssh@amnezia to prevent it from being downloaded from conan-center # expicitly use libssh@amnezia to prevent it from being downloaded from conan-center
+1 -1
View File
@@ -9,7 +9,7 @@ import platform
class AwgAndroid(ConanFile): class AwgAndroid(ConanFile):
name = "awg-android" name = "awg-android"
version = "1.1.7" version = "2.0.1"
settings = "os", "arch", "build_type", "compiler" settings = "os", "arch", "build_type", "compiler"
def configure(self): def configure(self):
+2 -2
View File
@@ -9,7 +9,7 @@ import os
class AwgApple(ConanFile): class AwgApple(ConanFile):
name = "awg-apple" name = "awg-apple"
version = "2.0.1" version = "2.0.2"
settings = "os", "arch", "compiler" settings = "os", "arch", "compiler"
@property @property
@@ -39,7 +39,7 @@ class AwgApple(ConanFile):
def source(self): def source(self):
get(self, f"https://github.com/amnezia-vpn/amneziawg-apple/archive/refs/tags/v{self.version}.zip", get(self, f"https://github.com/amnezia-vpn/amneziawg-apple/archive/refs/tags/v{self.version}.zip",
sha256="9fe4f8cfbb6a751558b54b7979db3a5ea46e49731912aae99f093e84a1433e97", strip_root=True sha256="a04f49eac9f82bbf5dd9031bab188d44de2b3482efde1b6e970821de1d5a3c5d", strip_root=True
) )
def generate(self): def generate(self):
+2 -2
View File
@@ -8,7 +8,7 @@ import os
class AwgGo(ConanFile): class AwgGo(ConanFile):
name = "awg-go" name = "awg-go"
version = "0.2.16" version = "0.2.18"
package_type = "application" package_type = "application"
settings = "os", "arch" settings = "os", "arch"
@@ -42,7 +42,7 @@ class AwgGo(ConanFile):
def source(self): def source(self):
get(self, f"https://github.com/amnezia-vpn/amneziawg-go/archive/refs/tags/v{self.version}.zip", get(self, f"https://github.com/amnezia-vpn/amneziawg-go/archive/refs/tags/v{self.version}.zip",
sha256="34da7d4189f215f3930de441548bc2a0c89d54d347a4fb85cb9c715fce6413aa", strip_root=True sha256="58eefbd012e79bd1525f0e02d748979e9480acc1a339df8ceb3b9ffafcedb1ba", strip_root=True
) )
def generate(self): def generate(self):
+2 -2
View File
@@ -8,7 +8,7 @@ import os
class AwgWindows(ConanFile): class AwgWindows(ConanFile):
name = "awg-windows" name = "awg-windows"
version = "0.1.8" version = "0.1.9"
settings = "os", "arch" settings = "os", "arch"
@property @property
@@ -63,7 +63,7 @@ class AwgWindows(ConanFile):
def source(self): def source(self):
get(self, f"https://github.com/amnezia-vpn/amneziawg-windows/archive/refs/tags/v{self.version}.zip", get(self, f"https://github.com/amnezia-vpn/amneziawg-windows/archive/refs/tags/v{self.version}.zip",
sha256="1de472832b332515c96cdf14ea887edde42ed7ad173675280c51baa9a3ef62f2", strip_root=True) sha256="5c29a75cb2beae291cc51b64840a39f838da5f300b9e956f7964813a687ec74c", strip_root=True)
def generate(self): def generate(self):
tc = AutotoolsToolchain(self) tc = AutotoolsToolchain(self)
+3
View File
@@ -650,6 +650,9 @@ class OpenSSLConan(ConanFile):
if self._use_nmake: if self._use_nmake:
self.cpp_info.components["ssl"].libs = ["libssl"] self.cpp_info.components["ssl"].libs = ["libssl"]
self.cpp_info.components["crypto"].libs = ["libcrypto"] self.cpp_info.components["crypto"].libs = ["libcrypto"]
elif self.settings.os == "Android" and self.options.shared:
self.cpp_info.components["ssl"].libs = ["ssl_3"]
self.cpp_info.components["crypto"].libs = ["crypto_3"]
else: else:
self.cpp_info.components["ssl"].libs = ["ssl"] self.cpp_info.components["ssl"].libs = ["ssl"]
self.cpp_info.components["crypto"].libs = ["crypto"] self.cpp_info.components["crypto"].libs = ["crypto"]
+1 -1
View File
@@ -28,7 +28,7 @@ class Openvpn(ConanFile):
def build_requirements(self): def build_requirements(self):
if self._is_windows: if self._is_windows:
self.tool_requires("cmake/[>=3.14 <4]") self.tool_requires("cmake/[>=4.2]")
else: else:
self.tool_requires("libtool/2.4.7") self.tool_requires("libtool/2.4.7")
self.tool_requires("automake/1.16.5") self.tool_requires("automake/1.16.5")