mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-17 08:16:06 +03:00
* refactor: remove serverConfig struct * refactor: add warnings for api v1 configs * refactor: moved the server type definition to a separate namespace * refactor: simplified gateway stacks * fix: fixed server description * fix: fixed postAsync reply usage * fix: fixed validateConfig call * fix: fixed server name in notifications * fix: fixed initPrepareConfigHandler for lagacy configs
415 lines
14 KiB
C++
415 lines
14 KiB
C++
#include "serversController.h"
|
|
#include "core/utils/serverConfigUtils.h"
|
|
#include "core/utils/protocolEnum.h"
|
|
#include "core/protocols/protocolUtils.h"
|
|
#include "core/utils/constants/configKeys.h"
|
|
#include "core/models/containerConfig.h"
|
|
|
|
#include "core/models/serverDescription.h"
|
|
|
|
#if defined(Q_OS_IOS) || defined(MACOS_NE)
|
|
#include <AmneziaVPN-Swift.h>
|
|
#endif
|
|
|
|
|
|
ServersController::ServersController(SecureServersRepository *serversRepository,
|
|
SecureAppSettingsRepository *appSettingsRepository, QObject *parent)
|
|
: QObject(parent), m_serversRepository(serversRepository), m_appSettingsRepository(appSettingsRepository)
|
|
{
|
|
ensureDefaultServerValid();
|
|
}
|
|
|
|
void ServersController::ensureDefaultServerValid()
|
|
{
|
|
if (!getServersCount()) {
|
|
return;
|
|
}
|
|
|
|
const QString defaultId = getDefaultServerId();
|
|
if (!defaultId.isEmpty() && indexOfServerId(defaultId) >= 0) {
|
|
return;
|
|
}
|
|
|
|
const QString firstId = getServerId(0);
|
|
if (!firstId.isEmpty()) {
|
|
setDefaultServer(firstId);
|
|
}
|
|
}
|
|
|
|
bool ServersController::renameServer(const QString &serverId, const QString &name)
|
|
{
|
|
const serverConfigUtils::ConfigType kind = m_serversRepository->serverKind(serverId);
|
|
switch (kind) {
|
|
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
|
|
auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
|
|
if (!cfg.has_value()) return false;
|
|
cfg->description = name;
|
|
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
|
|
return true;
|
|
}
|
|
case serverConfigUtils::ConfigType::SelfHostedUser: {
|
|
auto cfg = m_serversRepository->selfHostedUserConfig(serverId);
|
|
if (!cfg.has_value()) return false;
|
|
cfg->description = name;
|
|
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
|
|
return true;
|
|
}
|
|
case serverConfigUtils::ConfigType::Native: {
|
|
auto cfg = m_serversRepository->nativeConfig(serverId);
|
|
if (!cfg.has_value()) return false;
|
|
cfg->description = name;
|
|
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
|
|
return true;
|
|
}
|
|
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
|
|
case serverConfigUtils::ConfigType::AmneziaFreeV3:
|
|
case serverConfigUtils::ConfigType::ExternalPremium: {
|
|
auto cfg = m_serversRepository->apiV2Config(serverId);
|
|
if (!cfg.has_value()) return false;
|
|
cfg->name = name;
|
|
cfg->nameOverriddenByUser = true;
|
|
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
|
|
return true;
|
|
}
|
|
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
|
|
case serverConfigUtils::ConfigType::AmneziaFreeV2:
|
|
case serverConfigUtils::ConfigType::Invalid:
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void ServersController::removeServer(const QString &serverId)
|
|
{
|
|
m_serversRepository->removeServer(serverId);
|
|
}
|
|
|
|
void ServersController::setDefaultServer(const QString &serverId)
|
|
{
|
|
m_serversRepository->setDefaultServer(serverId);
|
|
}
|
|
|
|
void ServersController::setDefaultContainer(const QString &serverId, DockerContainer container)
|
|
{
|
|
const serverConfigUtils::ConfigType kind = m_serversRepository->serverKind(serverId);
|
|
switch (kind) {
|
|
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
|
|
auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
|
|
if (!cfg.has_value()) return;
|
|
cfg->defaultContainer = container;
|
|
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
|
|
return;
|
|
}
|
|
case serverConfigUtils::ConfigType::SelfHostedUser: {
|
|
auto cfg = m_serversRepository->selfHostedUserConfig(serverId);
|
|
if (!cfg.has_value()) return;
|
|
cfg->defaultContainer = container;
|
|
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
|
|
return;
|
|
}
|
|
case serverConfigUtils::ConfigType::Native: {
|
|
auto cfg = m_serversRepository->nativeConfig(serverId);
|
|
if (!cfg.has_value()) return;
|
|
cfg->defaultContainer = container;
|
|
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
|
|
return;
|
|
}
|
|
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
|
|
case serverConfigUtils::ConfigType::AmneziaFreeV3:
|
|
case serverConfigUtils::ConfigType::ExternalPremium: {
|
|
auto cfg = m_serversRepository->apiV2Config(serverId);
|
|
if (!cfg.has_value()) return;
|
|
cfg->defaultContainer = container;
|
|
m_serversRepository->editServer(serverId, cfg->toJson(), kind);
|
|
return;
|
|
}
|
|
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
|
|
case serverConfigUtils::ConfigType::AmneziaFreeV2:
|
|
case serverConfigUtils::ConfigType::Invalid:
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
QVector<ServerDescription> ServersController::buildServerDescriptions(bool isAmneziaDnsEnabled) const
|
|
{
|
|
QVector<ServerDescription> out;
|
|
const QVector<QString> ids = m_serversRepository->orderedServerIds();
|
|
out.reserve(ids.size());
|
|
|
|
for (const QString &id : ids) {
|
|
ServerDescription d;
|
|
using Kind = serverConfigUtils::ConfigType;
|
|
const Kind kind = m_serversRepository->serverKind(id);
|
|
switch (kind) {
|
|
case Kind::SelfHostedAdmin: {
|
|
const auto cfg = m_serversRepository->selfHostedAdminConfig(id);
|
|
if (!cfg) {
|
|
continue;
|
|
}
|
|
d = buildServerDescription(*cfg, isAmneziaDnsEnabled);
|
|
break;
|
|
}
|
|
case Kind::SelfHostedUser: {
|
|
const auto cfg = m_serversRepository->selfHostedUserConfig(id);
|
|
if (!cfg) {
|
|
continue;
|
|
}
|
|
d = buildServerDescription(*cfg, isAmneziaDnsEnabled);
|
|
break;
|
|
}
|
|
case Kind::Native: {
|
|
const auto cfg = m_serversRepository->nativeConfig(id);
|
|
if (!cfg) {
|
|
continue;
|
|
}
|
|
d = buildServerDescription(*cfg, isAmneziaDnsEnabled);
|
|
break;
|
|
}
|
|
case Kind::AmneziaPremiumV2:
|
|
case Kind::AmneziaFreeV3:
|
|
case Kind::ExternalPremium: {
|
|
const auto cfg = m_serversRepository->apiV2Config(id);
|
|
if (!cfg) {
|
|
continue;
|
|
}
|
|
d = buildServerDescription(*cfg, isAmneziaDnsEnabled);
|
|
break;
|
|
}
|
|
case Kind::AmneziaPremiumV1:
|
|
case Kind::AmneziaFreeV2: {
|
|
const auto cfg = m_serversRepository->legacyApiConfig(id);
|
|
if (!cfg) {
|
|
continue;
|
|
}
|
|
d = buildServerDescription(*cfg, isAmneziaDnsEnabled);
|
|
break;
|
|
}
|
|
case Kind::Invalid:
|
|
default:
|
|
continue;
|
|
}
|
|
|
|
d.serverId = id;
|
|
out.append(d);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
QMap<DockerContainer, ContainerConfig> ServersController::getServerContainersMap(const QString &serverId) const
|
|
{
|
|
switch (m_serversRepository->serverKind(serverId)) {
|
|
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
|
|
const auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
|
|
return cfg.has_value() ? cfg->containers : QMap<DockerContainer, ContainerConfig>{};
|
|
}
|
|
case serverConfigUtils::ConfigType::SelfHostedUser: {
|
|
const auto cfg = m_serversRepository->selfHostedUserConfig(serverId);
|
|
return cfg.has_value() ? cfg->containers : QMap<DockerContainer, ContainerConfig>{};
|
|
}
|
|
case serverConfigUtils::ConfigType::Native: {
|
|
const auto cfg = m_serversRepository->nativeConfig(serverId);
|
|
return cfg.has_value() ? cfg->containers : QMap<DockerContainer, ContainerConfig>{};
|
|
}
|
|
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
|
|
case serverConfigUtils::ConfigType::AmneziaFreeV3:
|
|
case serverConfigUtils::ConfigType::ExternalPremium: {
|
|
const auto cfg = m_serversRepository->apiV2Config(serverId);
|
|
return cfg.has_value() ? cfg->containers : QMap<DockerContainer, ContainerConfig>{};
|
|
}
|
|
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
|
|
case serverConfigUtils::ConfigType::AmneziaFreeV2: {
|
|
const auto cfg = m_serversRepository->legacyApiConfig(serverId);
|
|
return cfg.has_value() ? cfg->containers : QMap<DockerContainer, ContainerConfig>{};
|
|
}
|
|
case serverConfigUtils::ConfigType::Invalid:
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
|
|
DockerContainer ServersController::getDefaultContainer(const QString &serverId) const
|
|
{
|
|
switch (m_serversRepository->serverKind(serverId)) {
|
|
case serverConfigUtils::ConfigType::SelfHostedAdmin: {
|
|
const auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
|
|
return cfg.has_value() ? cfg->defaultContainer : DockerContainer::None;
|
|
}
|
|
case serverConfigUtils::ConfigType::SelfHostedUser: {
|
|
const auto cfg = m_serversRepository->selfHostedUserConfig(serverId);
|
|
return cfg.has_value() ? cfg->defaultContainer : DockerContainer::None;
|
|
}
|
|
case serverConfigUtils::ConfigType::Native: {
|
|
const auto cfg = m_serversRepository->nativeConfig(serverId);
|
|
return cfg.has_value() ? cfg->defaultContainer : DockerContainer::None;
|
|
}
|
|
case serverConfigUtils::ConfigType::AmneziaPremiumV2:
|
|
case serverConfigUtils::ConfigType::AmneziaFreeV3:
|
|
case serverConfigUtils::ConfigType::ExternalPremium: {
|
|
const auto cfg = m_serversRepository->apiV2Config(serverId);
|
|
return cfg.has_value() ? cfg->defaultContainer : DockerContainer::None;
|
|
}
|
|
case serverConfigUtils::ConfigType::AmneziaPremiumV1:
|
|
case serverConfigUtils::ConfigType::AmneziaFreeV2: {
|
|
const auto cfg = m_serversRepository->legacyApiConfig(serverId);
|
|
return cfg.has_value() ? cfg->defaultContainer : DockerContainer::None;
|
|
}
|
|
case serverConfigUtils::ConfigType::Invalid:
|
|
default:
|
|
return DockerContainer::None;
|
|
}
|
|
}
|
|
|
|
ContainerConfig ServersController::getContainerConfig(const QString &serverId, DockerContainer container) const
|
|
{
|
|
return getServerContainersMap(serverId).value(container);
|
|
}
|
|
|
|
int ServersController::getDefaultServerIndex() const
|
|
{
|
|
return m_serversRepository->defaultServerIndex();
|
|
}
|
|
|
|
QString ServersController::getDefaultServerId() const
|
|
{
|
|
return m_serversRepository->defaultServerId();
|
|
}
|
|
|
|
int ServersController::getServersCount() const
|
|
{
|
|
return m_serversRepository->serversCount();
|
|
}
|
|
|
|
QString ServersController::getServerId(int serverIndex) const
|
|
{
|
|
return m_serversRepository->serverIdAt(serverIndex);
|
|
}
|
|
|
|
int ServersController::indexOfServerId(const QString &serverId) const
|
|
{
|
|
return m_serversRepository->indexOfServerId(serverId);
|
|
}
|
|
|
|
QString ServersController::notificationDisplayName(const QString &serverId) const
|
|
{
|
|
if (serverId.isEmpty()) {
|
|
return {};
|
|
}
|
|
|
|
using Kind = serverConfigUtils::ConfigType;
|
|
switch (m_serversRepository->serverKind(serverId)) {
|
|
case Kind::SelfHostedAdmin: {
|
|
if (const auto cfg = m_serversRepository->selfHostedAdminConfig(serverId)) {
|
|
if (!cfg->displayName.isEmpty()) {
|
|
return cfg->displayName;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case Kind::SelfHostedUser: {
|
|
if (const auto cfg = m_serversRepository->selfHostedUserConfig(serverId)) {
|
|
if (!cfg->displayName.isEmpty()) {
|
|
return cfg->displayName;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case Kind::Native: {
|
|
if (const auto cfg = m_serversRepository->nativeConfig(serverId)) {
|
|
if (!cfg->displayName.isEmpty()) {
|
|
return cfg->displayName;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case Kind::AmneziaPremiumV2:
|
|
case Kind::AmneziaFreeV3:
|
|
case Kind::ExternalPremium: {
|
|
if (const auto cfg = m_serversRepository->apiV2Config(serverId)) {
|
|
if (!cfg->displayName.isEmpty()) {
|
|
return cfg->displayName;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case Kind::AmneziaPremiumV1:
|
|
case Kind::AmneziaFreeV2: {
|
|
if (const auto cfg = m_serversRepository->legacyApiConfig(serverId)) {
|
|
if (!cfg->displayName.isEmpty()) {
|
|
return cfg->displayName;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
const int idx = indexOfServerId(serverId);
|
|
if (idx >= 0) {
|
|
return QString::number(idx + 1);
|
|
}
|
|
return serverId;
|
|
}
|
|
|
|
std::optional<ApiV2ServerConfig> ServersController::apiV2Config(const QString &serverId) const
|
|
{
|
|
return m_serversRepository->apiV2Config(serverId);
|
|
}
|
|
|
|
std::optional<SelfHostedAdminServerConfig> ServersController::selfHostedAdminConfig(const QString &serverId) const
|
|
{
|
|
return m_serversRepository->selfHostedAdminConfig(serverId);
|
|
}
|
|
|
|
ServerCredentials ServersController::getServerCredentials(const QString &serverId) const
|
|
{
|
|
const auto cfg = m_serversRepository->selfHostedAdminConfig(serverId);
|
|
if (cfg.has_value()) {
|
|
const ServerCredentials creds = cfg->credentials();
|
|
if (creds.isValid()) {
|
|
return creds;
|
|
}
|
|
}
|
|
return ServerCredentials {};
|
|
}
|
|
|
|
bool ServersController::isServerFromApiAlreadyExists(const QString &userCountryCode, const QString &serviceType,
|
|
const QString &serviceProtocol) const
|
|
{
|
|
const QVector<QString> ids = m_serversRepository->orderedServerIds();
|
|
for (const QString &id : ids) {
|
|
const auto apiV2 = m_serversRepository->apiV2Config(id);
|
|
if (!apiV2.has_value()) {
|
|
continue;
|
|
}
|
|
if (apiV2->apiConfig.userCountryCode == userCountryCode && apiV2->serviceType() == serviceType
|
|
&& apiV2->serviceProtocol() == serviceProtocol) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ServersController::hasInstalledContainers(const QString &serverId) const
|
|
{
|
|
const QMap<DockerContainer, ContainerConfig> containers = getServerContainersMap(serverId);
|
|
|
|
for (auto it = containers.begin(); it != containers.end(); ++it) {
|
|
DockerContainer container = it.key();
|
|
if (ContainerUtils::containerService(container) == ServiceType::Vpn) {
|
|
return true;
|
|
}
|
|
if (container == DockerContainer::SSXray) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ServersController::isLegacyApiV1Server(const QString &serverId) const
|
|
{
|
|
return !serverId.isEmpty()
|
|
&& serverConfigUtils::isLegacyApiSubscription(m_serversRepository->serverKind(serverId));
|
|
}
|