added client management
This commit is contained in:
parent
282f159311
commit
c6a312845a
19 changed files with 675 additions and 157 deletions
|
@ -279,7 +279,7 @@ void AmneziaApplication::initModels()
|
||||||
{
|
{
|
||||||
m_containersModel.reset(new ContainersModel(m_settings, this));
|
m_containersModel.reset(new ContainersModel(m_settings, this));
|
||||||
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
|
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
|
||||||
connect(m_vpnConnection.get(), &VpnConnection::newVpnConfigurationCreated, m_containersModel.get(),
|
connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, m_containersModel.get(),
|
||||||
&ContainersModel::updateContainersConfig);
|
&ContainersModel::updateContainersConfig);
|
||||||
|
|
||||||
m_serversModel.reset(new ServersModel(m_settings, this));
|
m_serversModel.reset(new ServersModel(m_settings, this));
|
||||||
|
@ -322,6 +322,11 @@ void AmneziaApplication::initModels()
|
||||||
|
|
||||||
m_sftpConfigModel.reset(new SftpConfigModel(this));
|
m_sftpConfigModel.reset(new SftpConfigModel(this));
|
||||||
m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get());
|
m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get());
|
||||||
|
|
||||||
|
m_clientManagementModel.reset(new ClientManagementModel(m_settings, this));
|
||||||
|
m_engine->rootContext()->setContextProperty("ClientManagementModel", m_clientManagementModel.get());
|
||||||
|
connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, m_clientManagementModel.get(),
|
||||||
|
&ClientManagementModel::appendClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmneziaApplication::initControllers()
|
void AmneziaApplication::initControllers()
|
||||||
|
@ -347,7 +352,7 @@ void AmneziaApplication::initControllers()
|
||||||
m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings));
|
m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings));
|
||||||
m_engine->rootContext()->setContextProperty("ImportController", m_importController.get());
|
m_engine->rootContext()->setContextProperty("ImportController", m_importController.get());
|
||||||
|
|
||||||
m_exportController.reset(new ExportController(m_serversModel, m_containersModel, m_settings, m_configurator));
|
m_exportController.reset(new ExportController(m_serversModel, m_containersModel, m_clientManagementModel, m_settings, m_configurator));
|
||||||
m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get());
|
m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get());
|
||||||
|
|
||||||
m_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_settings));
|
m_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_settings));
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "ui/models/servers_model.h"
|
#include "ui/models/servers_model.h"
|
||||||
#include "ui/models/services/sftpConfigModel.h"
|
#include "ui/models/services/sftpConfigModel.h"
|
||||||
#include "ui/models/sites_model.h"
|
#include "ui/models/sites_model.h"
|
||||||
|
#include "ui/models/clientManagementModel.h"
|
||||||
|
|
||||||
#define amnApp (static_cast<AmneziaApplication *>(QCoreApplication::instance()))
|
#define amnApp (static_cast<AmneziaApplication *>(QCoreApplication::instance()))
|
||||||
|
|
||||||
|
@ -94,6 +95,7 @@ private:
|
||||||
QSharedPointer<LanguageModel> m_languageModel;
|
QSharedPointer<LanguageModel> m_languageModel;
|
||||||
QSharedPointer<ProtocolsModel> m_protocolsModel;
|
QSharedPointer<ProtocolsModel> m_protocolsModel;
|
||||||
QSharedPointer<SitesModel> m_sitesModel;
|
QSharedPointer<SitesModel> m_sitesModel;
|
||||||
|
QSharedPointer<ClientManagementModel> m_clientManagementModel;
|
||||||
|
|
||||||
QScopedPointer<OpenVpnConfigModel> m_openVpnConfigModel;
|
QScopedPointer<OpenVpnConfigModel> m_openVpnConfigModel;
|
||||||
QScopedPointer<ShadowSocksConfigModel> m_shadowSocksConfigModel;
|
QScopedPointer<ShadowSocksConfigModel> m_shadowSocksConfigModel;
|
||||||
|
|
|
@ -10,11 +10,10 @@ AwgConfigurator::AwgConfigurator(std::shared_ptr<Settings> settings, QObject *pa
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AwgConfigurator::genAwgConfig(const ServerCredentials &credentials,
|
QString AwgConfigurator::genAwgConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
DockerContainer container,
|
const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode)
|
||||||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
|
||||||
{
|
{
|
||||||
QString config = WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, errorCode);
|
QString config = WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, clientId, errorCode);
|
||||||
|
|
||||||
QJsonObject jsonConfig = QJsonDocument::fromJson(config.toUtf8()).object();
|
QJsonObject jsonConfig = QJsonDocument::fromJson(config.toUtf8()).object();
|
||||||
QString awgConfig = jsonConfig.value(config_key::config).toString();
|
QString awgConfig = jsonConfig.value(config_key::config).toString();
|
||||||
|
|
|
@ -12,7 +12,7 @@ public:
|
||||||
AwgConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
AwgConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||||
|
|
||||||
QString genAwgConfig(const ServerCredentials &credentials, DockerContainer container,
|
QString genAwgConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AWGCONFIGURATOR_H
|
#endif // AWGCONFIGURATOR_H
|
||||||
|
|
|
@ -83,7 +83,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
|
||||||
}
|
}
|
||||||
|
|
||||||
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
|
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
QString config =
|
QString config =
|
||||||
|
@ -131,13 +131,13 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(QString jsonConfig)
|
||||||
config.append("block-ipv6\n");
|
config.append("block-ipv6\n");
|
||||||
}
|
}
|
||||||
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
||||||
|
|
||||||
// no redirect-gateway
|
// no redirect-gateway
|
||||||
}
|
}
|
||||||
if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
|
if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
config.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n");
|
config.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n");
|
||||||
#endif
|
#endif
|
||||||
// Prevent ipv6 leak
|
// Prevent ipv6 leak
|
||||||
config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n");
|
config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n");
|
||||||
config.append("block-ipv6\n");
|
config.append("block-ipv6\n");
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
QString genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
|
QString genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode = nullptr);
|
||||||
|
|
||||||
QString processConfigWithLocalSettings(QString jsonConfig);
|
QString processConfigWithLocalSettings(QString jsonConfig);
|
||||||
QString processConfigWithExportSettings(QString jsonConfig);
|
QString processConfigWithExportSettings(QString jsonConfig);
|
||||||
|
|
|
@ -28,11 +28,11 @@ VpnConfigurator::VpnConfigurator(std::shared_ptr<Settings> settings, QObject *pa
|
||||||
}
|
}
|
||||||
|
|
||||||
QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
|
QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode)
|
const QJsonObject &containerConfig, Proto proto, QString &clientId, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
switch (proto) {
|
switch (proto) {
|
||||||
case Proto::OpenVpn:
|
case Proto::OpenVpn:
|
||||||
return openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, errorCode);
|
return openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, clientId, errorCode);
|
||||||
|
|
||||||
case Proto::ShadowSocks:
|
case Proto::ShadowSocks:
|
||||||
return shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, errorCode);
|
return shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, errorCode);
|
||||||
|
@ -40,10 +40,10 @@ QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentia
|
||||||
case Proto::Cloak: return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode);
|
case Proto::Cloak: return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode);
|
||||||
|
|
||||||
case Proto::WireGuard:
|
case Proto::WireGuard:
|
||||||
return wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, errorCode);
|
return wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, clientId, errorCode);
|
||||||
|
|
||||||
case Proto::Awg:
|
case Proto::Awg:
|
||||||
return awgConfigurator->genAwgConfig(credentials, container, containerConfig, errorCode);
|
return awgConfigurator->genAwgConfig(credentials, container, containerConfig, clientId, errorCode);
|
||||||
|
|
||||||
case Proto::Ikev2: return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode);
|
case Proto::Ikev2: return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "configurator_base.h"
|
#include "configurator_base.h"
|
||||||
#include "core/defs.h"
|
#include "core/defs.h"
|
||||||
|
|
||||||
|
|
||||||
class OpenVpnConfigurator;
|
class OpenVpnConfigurator;
|
||||||
class ShadowSocksConfigurator;
|
class ShadowSocksConfigurator;
|
||||||
class CloakConfigurator;
|
class CloakConfigurator;
|
||||||
|
@ -16,14 +15,15 @@ class SshConfigurator;
|
||||||
class AwgConfigurator;
|
class AwgConfigurator;
|
||||||
|
|
||||||
// Retrieve connection settings from server
|
// Retrieve connection settings from server
|
||||||
class VpnConfigurator : ConfiguratorBase
|
class VpnConfigurator : public ConfiguratorBase
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit VpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
explicit VpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||||
|
|
||||||
QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
|
QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode = nullptr);
|
const QJsonObject &containerConfig, Proto proto, QString &clientId,
|
||||||
|
ErrorCode *errorCode = nullptr);
|
||||||
|
|
||||||
QPair<QString, QString> getDnsForConfig(int serverIndex);
|
QPair<QString, QString> getDnsForConfig(int serverIndex);
|
||||||
QString &processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
|
QString &processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
|
||||||
|
@ -32,8 +32,8 @@ public:
|
||||||
QString &processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
|
QString &processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
|
||||||
|
|
||||||
// workaround for containers which is not support normal configuration
|
// workaround for containers which is not support normal configuration
|
||||||
void updateContainerConfigAfterInstallation(DockerContainer container,
|
void updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig,
|
||||||
QJsonObject &containerConfig, const QString &stdOut);
|
const QString &stdOut);
|
||||||
|
|
||||||
std::shared_ptr<OpenVpnConfigurator> openVpnConfigurator;
|
std::shared_ptr<OpenVpnConfigurator> openVpnConfigurator;
|
||||||
std::shared_ptr<ShadowSocksConfigurator> shadowSocksConfigurator;
|
std::shared_ptr<ShadowSocksConfigurator> shadowSocksConfigurator;
|
||||||
|
@ -42,6 +42,10 @@ public:
|
||||||
std::shared_ptr<Ikev2Configurator> ikev2Configurator;
|
std::shared_ptr<Ikev2Configurator> ikev2Configurator;
|
||||||
std::shared_ptr<SshConfigurator> sshConfigurator;
|
std::shared_ptr<SshConfigurator> sshConfigurator;
|
||||||
std::shared_ptr<AwgConfigurator> awgConfigurator;
|
std::shared_ptr<AwgConfigurator> awgConfigurator;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void newVpnConfigCreated(const QString &clientId, const QString &clientName, const DockerContainer container,
|
||||||
|
ServerCredentials credentials);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VPN_CONFIGURATOR_H
|
#endif // VPN_CONFIGURATOR_H
|
||||||
|
|
|
@ -177,7 +177,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
||||||
}
|
}
|
||||||
|
|
||||||
QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
QString scriptData = amnezia::scriptData(m_configTemplate, container);
|
QString scriptData = amnezia::scriptData(m_configTemplate, container);
|
||||||
|
@ -205,6 +205,8 @@ QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &crede
|
||||||
jConfig[config_key::psk_key] = connData.pskKey;
|
jConfig[config_key::psk_key] = connData.pskKey;
|
||||||
jConfig[config_key::server_pub_key] = connData.serverPubKey;
|
jConfig[config_key::server_pub_key] = connData.serverPubKey;
|
||||||
|
|
||||||
|
clientId = connData.clientPubKey;
|
||||||
|
|
||||||
return QJsonDocument(jConfig).toJson();
|
return QJsonDocument(jConfig).toJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
QString genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
QString genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode = nullptr);
|
||||||
|
|
||||||
QString processConfigWithLocalSettings(QString config);
|
QString processConfigWithLocalSettings(QString config);
|
||||||
QString processConfigWithExportSettings(QString config);
|
QString processConfigWithExportSettings(QString config);
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#include "configurators/cloak_configurator.h"
|
||||||
#include "configurators/openvpn_configurator.h"
|
#include "configurators/openvpn_configurator.h"
|
||||||
|
#include "configurators/shadowsocks_configurator.h"
|
||||||
#include "configurators/wireguard_configurator.h"
|
#include "configurators/wireguard_configurator.h"
|
||||||
#include "core/errorstrings.h"
|
#include "core/errorstrings.h"
|
||||||
#include "systemController.h"
|
#include "systemController.h"
|
||||||
|
@ -19,11 +21,13 @@
|
||||||
|
|
||||||
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel,
|
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel,
|
||||||
const QSharedPointer<ContainersModel> &containersModel,
|
const QSharedPointer<ContainersModel> &containersModel,
|
||||||
|
const QSharedPointer<ClientManagementModel> &clientManagementModel,
|
||||||
const std::shared_ptr<Settings> &settings,
|
const std::shared_ptr<Settings> &settings,
|
||||||
const std::shared_ptr<VpnConfigurator> &configurator, QObject *parent)
|
const std::shared_ptr<VpnConfigurator> &configurator, QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
m_serversModel(serversModel),
|
m_serversModel(serversModel),
|
||||||
m_containersModel(containersModel),
|
m_containersModel(containersModel),
|
||||||
|
m_clientManagementModel(clientManagementModel),
|
||||||
m_settings(settings),
|
m_settings(settings),
|
||||||
m_configurator(configurator)
|
m_configurator(configurator)
|
||||||
{
|
{
|
||||||
|
@ -75,13 +79,12 @@ void ExportController::generateFullAccessConfigAndroid()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ExportController::generateConnectionConfig()
|
void ExportController::generateConnectionConfig(const QString &clientName)
|
||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
||||||
ServerCredentials credentials =
|
ServerCredentials credentials = m_serversModel->getCurrentlyProcessedServerCredentials();
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
QModelIndex containerModelIndex = m_containersModel->index(container);
|
QModelIndex containerModelIndex = m_containersModel->index(container);
|
||||||
|
@ -93,17 +96,25 @@ void ExportController::generateConnectionConfig()
|
||||||
for (Proto protocol : ContainerProps::protocolsForContainer(container)) {
|
for (Proto protocol : ContainerProps::protocolsForContainer(container)) {
|
||||||
QJsonObject protocolConfig = m_settings->protocolConfig(serverIndex, container, protocol);
|
QJsonObject protocolConfig = m_settings->protocolConfig(serverIndex, container, protocol);
|
||||||
|
|
||||||
QString vpnConfig =
|
QString clientId;
|
||||||
m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, protocol, &errorCode);
|
QString vpnConfig = m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, protocol,
|
||||||
|
clientId, &errorCode);
|
||||||
if (errorCode) {
|
if (errorCode) {
|
||||||
emit exportErrorOccurred(errorString(errorCode));
|
emit exportErrorOccurred(errorString(errorCode));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
protocolConfig.insert(config_key::last_config, vpnConfig);
|
protocolConfig.insert(config_key::last_config, vpnConfig);
|
||||||
containerConfig.insert(ProtocolProps::protoToString(protocol), protocolConfig);
|
containerConfig.insert(ProtocolProps::protoToString(protocol), protocolConfig);
|
||||||
|
if (protocol == Proto::OpenVpn || protocol == Proto::Awg || protocol == Proto::WireGuard) {
|
||||||
|
errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
|
||||||
|
if (errorCode) {
|
||||||
|
emit exportErrorOccurred(errorString(errorCode));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject config = m_settings->server(serverIndex);
|
QJsonObject config = m_settings->server(serverIndex); // todo change to servers_model
|
||||||
if (!errorCode) {
|
if (!errorCode) {
|
||||||
config.remove(config_key::userName);
|
config.remove(config_key::userName);
|
||||||
config.remove(config_key::password);
|
config.remove(config_key::password);
|
||||||
|
@ -126,13 +137,12 @@ void ExportController::generateConnectionConfig()
|
||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportController::generateOpenVpnConfig()
|
void ExportController::generateOpenVpnConfig(const QString &clientName)
|
||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
||||||
ServerCredentials credentials =
|
ServerCredentials credentials = m_serversModel->getCurrentlyProcessedServerCredentials();
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
QModelIndex containerModelIndex = m_containersModel->index(container);
|
QModelIndex containerModelIndex = m_containersModel->index(container);
|
||||||
|
@ -141,8 +151,9 @@ void ExportController::generateOpenVpnConfig()
|
||||||
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
|
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
|
||||||
|
|
||||||
ErrorCode errorCode = ErrorCode::NoError;
|
ErrorCode errorCode = ErrorCode::NoError;
|
||||||
QString config =
|
QString clientId;
|
||||||
m_configurator->openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, &errorCode);
|
QString config = m_configurator->openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig,
|
||||||
|
clientId, &errorCode);
|
||||||
if (errorCode) {
|
if (errorCode) {
|
||||||
emit exportErrorOccurred(errorString(errorCode));
|
emit exportErrorOccurred(errorString(errorCode));
|
||||||
return;
|
return;
|
||||||
|
@ -155,16 +166,23 @@ void ExportController::generateOpenVpnConfig()
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_qrCodes = generateQrCodeImageSeries(m_config.toUtf8());
|
||||||
|
|
||||||
|
errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
|
||||||
|
if (errorCode) {
|
||||||
|
emit exportErrorOccurred(errorString(errorCode));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportController::generateWireGuardConfig()
|
void ExportController::generateWireGuardConfig(const QString &clientName)
|
||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
||||||
ServerCredentials credentials =
|
ServerCredentials credentials = m_serversModel->getCurrentlyProcessedServerCredentials();
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
QModelIndex containerModelIndex = m_containersModel->index(container);
|
QModelIndex containerModelIndex = m_containersModel->index(container);
|
||||||
|
@ -172,9 +190,10 @@ void ExportController::generateWireGuardConfig()
|
||||||
qvariant_cast<QJsonObject>(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole));
|
qvariant_cast<QJsonObject>(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole));
|
||||||
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
|
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
|
||||||
|
|
||||||
|
QString clientId;
|
||||||
ErrorCode errorCode = ErrorCode::NoError;
|
ErrorCode errorCode = ErrorCode::NoError;
|
||||||
QString config = m_configurator->wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig,
|
QString config = m_configurator->wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig,
|
||||||
&errorCode);
|
clientId, &errorCode);
|
||||||
if (errorCode) {
|
if (errorCode) {
|
||||||
emit exportErrorOccurred(errorString(errorCode));
|
emit exportErrorOccurred(errorString(errorCode));
|
||||||
return;
|
return;
|
||||||
|
@ -187,6 +206,14 @@ void ExportController::generateWireGuardConfig()
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_qrCodes = generateQrCodeImageSeries(m_config.toUtf8());
|
||||||
|
|
||||||
|
errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
|
||||||
|
if (errorCode) {
|
||||||
|
emit exportErrorOccurred(errorString(errorCode));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +232,22 @@ void ExportController::exportConfig(const QString &fileName)
|
||||||
SystemController::saveFile(fileName, m_config);
|
SystemController::saveFile(fileName, m_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExportController::revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials)
|
||||||
|
{
|
||||||
|
ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials);
|
||||||
|
if (errorCode != ErrorCode::NoError) {
|
||||||
|
emit exportErrorOccurred(errorString(errorCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExportController::renameClient(const int row, const QString &clientName, const DockerContainer container, ServerCredentials credentials)
|
||||||
|
{
|
||||||
|
ErrorCode errorCode = m_clientManagementModel->renameClient(row, clientName, container, credentials);
|
||||||
|
if (errorCode != ErrorCode::NoError) {
|
||||||
|
emit exportErrorOccurred(errorString(errorCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QList<QString> ExportController::generateQrCodeImageSeries(const QByteArray &data)
|
QList<QString> ExportController::generateQrCodeImageSeries(const QByteArray &data)
|
||||||
{
|
{
|
||||||
double k = 850;
|
double k = 850;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "configurators/vpn_configurator.h"
|
#include "configurators/vpn_configurator.h"
|
||||||
#include "ui/models/containers_model.h"
|
#include "ui/models/containers_model.h"
|
||||||
#include "ui/models/servers_model.h"
|
#include "ui/models/servers_model.h"
|
||||||
|
#include "ui/models/clientManagementModel.h"
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
#include "platforms/android/authResultReceiver.h"
|
#include "platforms/android/authResultReceiver.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,6 +17,7 @@ class ExportController : public QObject
|
||||||
public:
|
public:
|
||||||
explicit ExportController(const QSharedPointer<ServersModel> &serversModel,
|
explicit ExportController(const QSharedPointer<ServersModel> &serversModel,
|
||||||
const QSharedPointer<ContainersModel> &containersModel,
|
const QSharedPointer<ContainersModel> &containersModel,
|
||||||
|
const QSharedPointer<ClientManagementModel> &clientManagementModel,
|
||||||
const std::shared_ptr<Settings> &settings,
|
const std::shared_ptr<Settings> &settings,
|
||||||
const std::shared_ptr<VpnConfigurator> &configurator, QObject *parent = nullptr);
|
const std::shared_ptr<VpnConfigurator> &configurator, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
@ -28,15 +30,18 @@ public slots:
|
||||||
#if defined(Q_OS_ANDROID)
|
#if defined(Q_OS_ANDROID)
|
||||||
void generateFullAccessConfigAndroid();
|
void generateFullAccessConfigAndroid();
|
||||||
#endif
|
#endif
|
||||||
void generateConnectionConfig();
|
void generateConnectionConfig(const QString &clientName);
|
||||||
void generateOpenVpnConfig();
|
void generateOpenVpnConfig(const QString &clientName);
|
||||||
void generateWireGuardConfig();
|
void generateWireGuardConfig(const QString &clientName);
|
||||||
|
|
||||||
QString getConfig();
|
QString getConfig();
|
||||||
QList<QString> getQrCodes();
|
QList<QString> getQrCodes();
|
||||||
|
|
||||||
void exportConfig(const QString &fileName);
|
void exportConfig(const QString &fileName);
|
||||||
|
|
||||||
|
void revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials);
|
||||||
|
void renameClient(const int row, const QString &clientName, const DockerContainer container, ServerCredentials credentials);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void generateConfig(int type);
|
void generateConfig(int type);
|
||||||
void exportErrorOccurred(const QString &errorMessage);
|
void exportErrorOccurred(const QString &errorMessage);
|
||||||
|
@ -55,6 +60,7 @@ private:
|
||||||
|
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
QSharedPointer<ServersModel> m_serversModel;
|
||||||
QSharedPointer<ContainersModel> m_containersModel;
|
QSharedPointer<ContainersModel> m_containersModel;
|
||||||
|
QSharedPointer<ClientManagementModel> m_clientManagementModel;
|
||||||
std::shared_ptr<Settings> m_settings;
|
std::shared_ptr<Settings> m_settings;
|
||||||
std::shared_ptr<VpnConfigurator> m_configurator;
|
std::shared_ptr<VpnConfigurator> m_configurator;
|
||||||
|
|
||||||
|
|
|
@ -1,104 +1,330 @@
|
||||||
#include "clientManagementModel.h"
|
#include "clientManagementModel.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
ClientManagementModel::ClientManagementModel(QObject *parent) : QAbstractListModel(parent)
|
#include "core/servercontroller.h"
|
||||||
{
|
|
||||||
|
|
||||||
}
|
ClientManagementModel::ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent)
|
||||||
|
: m_settings(settings), QAbstractListModel(parent)
|
||||||
void ClientManagementModel::clearData()
|
|
||||||
{
|
{
|
||||||
beginResetModel();
|
|
||||||
m_content.clear();
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientManagementModel::setContent(const QVector<QVariant> &data)
|
|
||||||
{
|
|
||||||
beginResetModel();
|
|
||||||
m_content = data;
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject ClientManagementModel::getContent(amnezia::Proto protocol)
|
|
||||||
{
|
|
||||||
QJsonObject clientsTable;
|
|
||||||
for (const auto &item : m_content) {
|
|
||||||
if (protocol == amnezia::Proto::OpenVpn) {
|
|
||||||
clientsTable[item.toJsonObject()["openvpnCertId"].toString()] = item.toJsonObject();
|
|
||||||
} else if (protocol == amnezia::Proto::WireGuard) {
|
|
||||||
clientsTable[item.toJsonObject()["wireguardPublicKey"].toString()] = item.toJsonObject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return clientsTable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClientManagementModel::rowCount(const QModelIndex &parent) const
|
int ClientManagementModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(parent);
|
Q_UNUSED(parent);
|
||||||
return static_cast<int>(m_content.size());
|
return static_cast<int>(m_clientsTable.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
|
QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid() || index.row() < 0
|
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(m_clientsTable.size())) {
|
||||||
|| index.row() >= static_cast<int>(m_content.size())) {
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == NameRole) {
|
auto client = m_clientsTable.at(index.row()).toObject();
|
||||||
return m_content[index.row()].toJsonObject()["clientName"].toString();
|
auto userData = client.value("userData").toObject();
|
||||||
} else if (role == OpenVpnCertIdRole) {
|
|
||||||
return m_content[index.row()].toJsonObject()["openvpnCertId"].toString();
|
switch (role) {
|
||||||
} else if (role == OpenVpnCertDataRole) {
|
case UserNameRole: return userData.value("clientName").toString();
|
||||||
return m_content[index.row()].toJsonObject()["openvpnCertData"].toString();
|
case ContainerNameRole:
|
||||||
} else if (role == WireGuardPublicKey) {
|
return ContainerProps::containerHumanNames().value(
|
||||||
return m_content[index.row()].toJsonObject()["wireguardPublicKey"].toString();
|
static_cast<DockerContainer>(userData.value("container").toInt()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManagementModel::setData(const QModelIndex &index, QVariant data, int role)
|
ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCredentials credentials)
|
||||||
{
|
{
|
||||||
if (!index.isValid() || index.row() < 0
|
ServerController serverController(m_settings);
|
||||||
|| index.row() >= static_cast<int>(m_content.size())) {
|
|
||||||
return;
|
ErrorCode error = ErrorCode::NoError;
|
||||||
|
QString stdOut;
|
||||||
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
||||||
|
stdOut += data + "\n";
|
||||||
|
return ErrorCode::NoError;
|
||||||
|
};
|
||||||
|
|
||||||
|
const QString clientsTableFile =
|
||||||
|
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container));
|
||||||
|
const QByteArray clientsTableString =
|
||||||
|
serverController.getTextFileFromContainer(container, credentials, clientsTableFile, &error);
|
||||||
|
if (error != ErrorCode::NoError) {
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto client = m_content[index.row()].toJsonObject();
|
beginResetModel();
|
||||||
if (role == NameRole) {
|
m_clientsTable = QJsonDocument::fromJson(clientsTableString).array();
|
||||||
client["clientName"] = data.toString();
|
|
||||||
} else if (role == OpenVpnCertIdRole) {
|
if (m_clientsTable.isEmpty()) {
|
||||||
client["openvpnCertId"] = data.toString();
|
int count = 0;
|
||||||
} else if (role == OpenVpnCertDataRole) {
|
|
||||||
client["openvpnCertData"] = data.toString();
|
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks
|
||||||
} else if (role == WireGuardPublicKey) {
|
|| container == DockerContainer::Cloak) {
|
||||||
client["wireguardPublicKey"] = data.toString();
|
const QString getOpenVpnClientsList =
|
||||||
} else {
|
"sudo docker exec -i $CONTAINER_NAME bash -c 'ls /opt/amnezia/openvpn/pki/issued'";
|
||||||
return;
|
QString script = serverController.replaceVars(getOpenVpnClientsList,
|
||||||
}
|
serverController.genVarsForScript(credentials, container));
|
||||||
if (m_content[index.row()] != client) {
|
error = serverController.runScript(credentials, script, cbReadStdOut);
|
||||||
m_content[index.row()] = client;
|
if (error != ErrorCode::NoError) {
|
||||||
emit dataChanged(index, index);
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stdOut.isEmpty()) {
|
||||||
|
QStringList certsIds = stdOut.split("\n", Qt::SkipEmptyParts);
|
||||||
|
certsIds.removeAll("AmneziaReq.crt");
|
||||||
|
|
||||||
|
for (auto &openvpnCertId : certsIds) {
|
||||||
|
openvpnCertId.replace(".crt", "");
|
||||||
|
if (!isClientExists(openvpnCertId)) {
|
||||||
|
QJsonObject client;
|
||||||
|
client["userId"] = openvpnCertId;
|
||||||
|
|
||||||
|
QJsonObject userData;
|
||||||
|
userData["clientName"] = QString("Client %1").arg(count);
|
||||||
|
userData["container"] = container;
|
||||||
|
client["userData"] = userData;
|
||||||
|
|
||||||
|
m_clientsTable.push_back(client);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||||
|
const QString wireGuardConfigFile =
|
||||||
|
QString("opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg");
|
||||||
|
const QString wireguardConfigString =
|
||||||
|
serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, &error);
|
||||||
|
if (error != ErrorCode::NoError) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto configLines = wireguardConfigString.split("\n", Qt::SkipEmptyParts);
|
||||||
|
QStringList wireguardKeys;
|
||||||
|
for (const auto &line : configLines) {
|
||||||
|
auto configPair = line.split(" = ", Qt::SkipEmptyParts);
|
||||||
|
if (configPair.front() == "PublicKey") {
|
||||||
|
wireguardKeys.push_back(configPair.back());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &wireguardKey : wireguardKeys) {
|
||||||
|
if (!isClientExists(wireguardKey)) {
|
||||||
|
QJsonObject client;
|
||||||
|
client["userId"] = wireguardKey;
|
||||||
|
|
||||||
|
QJsonObject userData;
|
||||||
|
userData["clientName"] = QString("Client %1").arg(count);
|
||||||
|
userData["container"] = container;
|
||||||
|
client["userData"] = userData;
|
||||||
|
|
||||||
|
m_clientsTable.push_back(client);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QByteArray newClientsTableString = QJsonDocument(m_clientsTable).toJson();
|
||||||
|
if (clientsTableString != newClientsTableString) {
|
||||||
|
error = serverController.uploadTextFileToContainer(container, credentials, newClientsTableString,
|
||||||
|
clientsTableFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientManagementModel::removeRows(int row)
|
bool ClientManagementModel::isClientExists(const QString &clientId)
|
||||||
{
|
{
|
||||||
|
for (const QJsonValue &value : qAsConst(m_clientsTable)) {
|
||||||
|
if (value.isObject()) {
|
||||||
|
QJsonObject obj = value.toObject();
|
||||||
|
if (obj.contains("userId") && obj["userId"].toString() == clientId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QString &clientName,
|
||||||
|
const DockerContainer container, ServerCredentials credentials)
|
||||||
|
{
|
||||||
|
ErrorCode error;
|
||||||
|
if (m_clientsTable.empty()) {
|
||||||
|
error = updateModel(container, credentials);
|
||||||
|
if (error != ErrorCode::NoError) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < m_clientsTable.size(); i++) {
|
||||||
|
if (m_clientsTable.at(i).toObject().value("userId") == (clientId)) {
|
||||||
|
error = renameClient(i, clientName, container, credentials);
|
||||||
|
if (error != ErrorCode::NoError) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
beginResetModel();
|
||||||
|
QJsonObject client;
|
||||||
|
client["userId"] = clientId;
|
||||||
|
|
||||||
|
QJsonObject userData;
|
||||||
|
userData["clientName"] = clientName;
|
||||||
|
userData["container"] = container;
|
||||||
|
client["userData"] = userData;
|
||||||
|
m_clientsTable.push_back(client);
|
||||||
|
endResetModel();
|
||||||
|
|
||||||
|
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
|
||||||
|
|
||||||
|
ServerController serverController(m_settings);
|
||||||
|
const QString clientsTableFile =
|
||||||
|
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container));
|
||||||
|
|
||||||
|
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode ClientManagementModel::renameClient(const int row, const QString &clientName, const DockerContainer container,
|
||||||
|
ServerCredentials credentials)
|
||||||
|
{
|
||||||
|
auto client = m_clientsTable.at(row).toObject();
|
||||||
|
auto userData = client["userData"].toObject();
|
||||||
|
userData["clientName"] = clientName;
|
||||||
|
client["userData"] = userData;
|
||||||
|
|
||||||
|
m_clientsTable.replace(row, client);
|
||||||
|
emit dataChanged(index(row, 0), index(row, 0));
|
||||||
|
|
||||||
|
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
|
||||||
|
|
||||||
|
ServerController serverController(m_settings);
|
||||||
|
const QString clientsTableFile =
|
||||||
|
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container));
|
||||||
|
|
||||||
|
ErrorCode error =
|
||||||
|
serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContainer container,
|
||||||
|
ServerCredentials credentials)
|
||||||
|
{
|
||||||
|
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks
|
||||||
|
|| container == DockerContainer::Cloak) {
|
||||||
|
return revokeOpenVpn(row, container, credentials);
|
||||||
|
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||||
|
return revokeWireGuard(row, container, credentials);
|
||||||
|
}
|
||||||
|
return ErrorCode::NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContainer container,
|
||||||
|
ServerCredentials credentials)
|
||||||
|
{
|
||||||
|
auto client = m_clientsTable.at(row).toObject();
|
||||||
|
QString clientId = client.value("userId").toString();
|
||||||
|
|
||||||
|
const QString getOpenVpnCertData = QString("sudo docker exec -i $CONTAINER_NAME bash -c '"
|
||||||
|
"cd /opt/amnezia/openvpn ;\\"
|
||||||
|
"easyrsa revoke %1 ;\\"
|
||||||
|
"easyrsa gen-crl ;\\"
|
||||||
|
"cp pki/crl.pem .'")
|
||||||
|
.arg(clientId);
|
||||||
|
|
||||||
|
ServerController serverController(m_settings);
|
||||||
|
const QString script =
|
||||||
|
serverController.replaceVars(getOpenVpnCertData, serverController.genVarsForScript(credentials, container));
|
||||||
|
ErrorCode error = serverController.runScript(credentials, script);
|
||||||
|
if (error != ErrorCode::NoError) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
beginRemoveRows(QModelIndex(), row, row);
|
beginRemoveRows(QModelIndex(), row, row);
|
||||||
m_content.removeAt(row);
|
m_clientsTable.removeAt(row);
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
return true;
|
|
||||||
|
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
|
||||||
|
|
||||||
|
const QString clientsTableFile =
|
||||||
|
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container));
|
||||||
|
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||||
|
if (error != ErrorCode::NoError) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorCode::NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerContainer container,
|
||||||
|
ServerCredentials credentials)
|
||||||
|
{
|
||||||
|
ErrorCode error;
|
||||||
|
ServerController serverController(m_settings);
|
||||||
|
|
||||||
|
const QString wireGuardConfigFile =
|
||||||
|
QString("/opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg");
|
||||||
|
const QString wireguardConfigString =
|
||||||
|
serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, &error);
|
||||||
|
if (error != ErrorCode::NoError) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto client = m_clientsTable.at(row).toObject();
|
||||||
|
QString clientId = client.value("userId").toString();
|
||||||
|
|
||||||
|
auto configSections = wireguardConfigString.split("[", Qt::SkipEmptyParts);
|
||||||
|
for (auto §ion : configSections) {
|
||||||
|
if (section.contains(clientId)) {
|
||||||
|
configSections.removeOne(section);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QString newWireGuardConfig = configSections.join("[");
|
||||||
|
newWireGuardConfig.insert(0, "[");
|
||||||
|
error = serverController.uploadTextFileToContainer(container, credentials, newWireGuardConfig, wireGuardConfigFile);
|
||||||
|
if (error != ErrorCode::NoError) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
beginRemoveRows(QModelIndex(), row, row);
|
||||||
|
m_clientsTable.removeAt(row);
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
|
||||||
|
|
||||||
|
const QString clientsTableFile =
|
||||||
|
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container));
|
||||||
|
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||||
|
if (error != ErrorCode::NoError) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString script = "sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'";
|
||||||
|
error = serverController.runScript(
|
||||||
|
credentials,
|
||||||
|
serverController.replaceVars(script.arg(wireGuardConfigFile),
|
||||||
|
serverController.genVarsForScript(credentials, container)));
|
||||||
|
if (error != ErrorCode::NoError) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorCode::NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> ClientManagementModel::roleNames() const
|
QHash<int, QByteArray> ClientManagementModel::roleNames() const
|
||||||
{
|
{
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
roles[NameRole] = "clientName";
|
roles[UserNameRole] = "userName";
|
||||||
roles[OpenVpnCertIdRole] = "openvpnCertId";
|
roles[ContainerNameRole] = "containerName";
|
||||||
roles[OpenVpnCertDataRole] = "openvpnCertData";
|
|
||||||
roles[WireGuardPublicKey] = "wireguardPublicKey";
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,36 +2,62 @@
|
||||||
#define CLIENTMANAGEMENTMODEL_H
|
#define CLIENTMANAGEMENTMODEL_H
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
#include "protocols/protocols_defs.h"
|
#include "protocols/protocols_defs.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
class ClientManagementModel : public QAbstractListModel
|
class ClientManagementModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
struct ClientManagementData
|
||||||
enum ClientRoles {
|
{
|
||||||
NameRole = Qt::UserRole + 1,
|
QString userId;
|
||||||
OpenVpnCertIdRole,
|
QJsonObject userData;
|
||||||
OpenVpnCertDataRole,
|
|
||||||
WireGuardPublicKey,
|
bool operator==(const ClientManagementData &r) const
|
||||||
|
{
|
||||||
|
return userId == r.userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const QString &otherUserId) const
|
||||||
|
{
|
||||||
|
return userId == otherUserId;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ClientManagementModel(QObject *parent = nullptr);
|
public:
|
||||||
|
enum Roles {
|
||||||
|
UserNameRole = Qt::UserRole + 1,
|
||||||
|
ContainerNameRole,
|
||||||
|
};
|
||||||
|
|
||||||
|
ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||||
|
|
||||||
void clearData();
|
|
||||||
void setContent(const QVector<QVariant> &data);
|
|
||||||
QJsonObject getContent(amnezia::Proto protocol);
|
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
void setData(const QModelIndex &index, QVariant data, int role = Qt::DisplayRole);
|
|
||||||
bool removeRows(int row);
|
public slots:
|
||||||
|
ErrorCode updateModel(DockerContainer container, ServerCredentials credentials);
|
||||||
|
ErrorCode appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
|
||||||
|
ServerCredentials credentials);
|
||||||
|
ErrorCode renameClient(const int row, const QString &userName, const DockerContainer container,
|
||||||
|
ServerCredentials credentials);
|
||||||
|
ErrorCode revokeClient(const int index, const DockerContainer container, ServerCredentials credentials);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<QVariant> m_content;
|
bool isClientExists(const QString &clientId);
|
||||||
|
|
||||||
|
ErrorCode revokeOpenVpn(const int row, const DockerContainer container, ServerCredentials credentials);
|
||||||
|
ErrorCode revokeWireGuard(const int row, const DockerContainer container, ServerCredentials credentials);
|
||||||
|
|
||||||
|
QJsonArray m_clientsTable;
|
||||||
|
|
||||||
|
std::shared_ptr<Settings> m_settings;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLIENTMANAGEMENTMODEL_H
|
#endif // CLIENTMANAGEMENTMODEL_H
|
||||||
|
|
|
@ -145,6 +145,11 @@ QString ServersModel::getCurrentlyProcessedServerHostName()
|
||||||
return qvariant_cast<QString>(data(m_currentlyProcessedServerIndex, HostNameRole));
|
return qvariant_cast<QString>(data(m_currentlyProcessedServerIndex, HostNameRole));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ServerCredentials ServersModel::getCurrentlyProcessedServerCredentials()
|
||||||
|
{
|
||||||
|
return serverCredentials(m_currentlyProcessedServerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
bool ServersModel::isDefaultServerCurrentlyProcessed()
|
bool ServersModel::isDefaultServerCurrentlyProcessed()
|
||||||
{
|
{
|
||||||
return m_defaultServerIndex == m_currentlyProcessedServerIndex;
|
return m_defaultServerIndex == m_currentlyProcessedServerIndex;
|
||||||
|
|
|
@ -53,6 +53,7 @@ public slots:
|
||||||
int getCurrentlyProcessedServerIndex();
|
int getCurrentlyProcessedServerIndex();
|
||||||
|
|
||||||
QString getCurrentlyProcessedServerHostName();
|
QString getCurrentlyProcessedServerHostName();
|
||||||
|
const ServerCredentials getCurrentlyProcessedServerCredentials();
|
||||||
|
|
||||||
void addServer(const QJsonObject &server);
|
void addServer(const QJsonObject &server);
|
||||||
void removeServer();
|
void removeServer();
|
||||||
|
|
|
@ -23,10 +23,22 @@ PageType {
|
||||||
WireGuard
|
WireGuard
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signal revokeConfig(int index)
|
||||||
|
onRevokeConfig: function(index) {
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
ExportController.revokeConfig(index,
|
||||||
|
ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
|
ServersModel.getCurrentlyProcessedServerCredentials())
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: ExportController
|
target: ExportController
|
||||||
|
|
||||||
function onGenerateConfig(type) {
|
function onGenerateConfig(type) {
|
||||||
|
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
||||||
|
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
||||||
|
|
||||||
shareConnectionDrawer.needCloseButton = false
|
shareConnectionDrawer.needCloseButton = false
|
||||||
|
|
||||||
shareConnectionDrawer.open()
|
shareConnectionDrawer.open()
|
||||||
|
@ -34,7 +46,7 @@ PageType {
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PageShare.ConfigType.AmneziaConnection: ExportController.generateConnectionConfig(); break;
|
case PageShare.ConfigType.AmneziaConnection: ExportController.generateConnectionConfig(userNameTextField.textFieldText); break;
|
||||||
case PageShare.ConfigType.AmneziaFullAccess: {
|
case PageShare.ConfigType.AmneziaFullAccess: {
|
||||||
if (Qt.platform.os === "android") {
|
if (Qt.platform.os === "android") {
|
||||||
ExportController.generateFullAccessConfigAndroid();
|
ExportController.generateFullAccessConfigAndroid();
|
||||||
|
@ -44,14 +56,14 @@ PageType {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PageShare.ConfigType.OpenVpn: {
|
case PageShare.ConfigType.OpenVpn: {
|
||||||
ExportController.generateOpenVpnConfig();
|
ExportController.generateOpenVpnConfig(userNameTextField.textFieldText)
|
||||||
shareConnectionDrawer.configCaption = qsTr("Save OpenVPN config")
|
shareConnectionDrawer.configCaption = qsTr("Save OpenVPN config")
|
||||||
shareConnectionDrawer.configExtension = ".ovpn"
|
shareConnectionDrawer.configExtension = ".ovpn"
|
||||||
shareConnectionDrawer.configFileName = "amnezia_for_openvpn"
|
shareConnectionDrawer.configFileName = "amnezia_for_openvpn"
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PageShare.ConfigType.WireGuard: {
|
case PageShare.ConfigType.WireGuard: {
|
||||||
ExportController.generateWireGuardConfig();
|
ExportController.generateWireGuardConfig(userNameTextField.textFieldText)
|
||||||
shareConnectionDrawer.configCaption = qsTr("Save WireGuard config")
|
shareConnectionDrawer.configCaption = qsTr("Save WireGuard config")
|
||||||
shareConnectionDrawer.configExtension = ".conf"
|
shareConnectionDrawer.configExtension = ".conf"
|
||||||
shareConnectionDrawer.configFileName = "amnezia_for_wireguard"
|
shareConnectionDrawer.configFileName = "amnezia_for_wireguard"
|
||||||
|
@ -73,8 +85,6 @@ PageType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property string fullConfigServerSelectorText
|
|
||||||
property string connectionServerSelectorText
|
|
||||||
property bool showContent: false
|
property bool showContent: false
|
||||||
property bool shareButtonEnabled: true
|
property bool shareButtonEnabled: true
|
||||||
property list<QtObject> connectionTypesModel: [
|
property list<QtObject> connectionTypesModel: [
|
||||||
|
@ -147,20 +157,21 @@ PageType {
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
accessTypeSelector.currentIndex = 0
|
accessTypeSelector.currentIndex = 0
|
||||||
serverSelector.text = root.connectionServerSelectorText
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HorizontalRadioButton {
|
HorizontalRadioButton {
|
||||||
checked: root.currentIndex === 1
|
checked: accessTypeSelector.currentIndex === 1
|
||||||
|
|
||||||
implicitWidth: (root.width - 32) / 2
|
implicitWidth: (root.width - 32) / 2
|
||||||
text: qsTr("Full access")
|
text: qsTr("Users")
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
accessTypeSelector.currentIndex = 1
|
accessTypeSelector.currentIndex = 1
|
||||||
serverSelector.text = root.fullConfigServerSelectorText
|
PageController.showBusyIndicator(true)
|
||||||
root.shareButtonEnabled = true
|
ClientManagementModel.updateModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
|
ServersModel.getCurrentlyProcessedServerCredentials())
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,11 +182,25 @@ PageType {
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
text: accessTypeSelector.currentIndex === 0 ? qsTr("Share VPN access without the ability to manage the server") :
|
visible: accessTypeSelector.currentIndex === 0
|
||||||
qsTr("Share access to server management. The user with whom you share full access to the server will be able to add and remove any protocols and services to the server, as well as change settings.")
|
|
||||||
|
text: qsTr("Share VPN access without the ability to manage the server")
|
||||||
color: "#878B91"
|
color: "#878B91"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextFieldWithHeaderType {
|
||||||
|
id: userNameTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
|
visible: accessTypeSelector.currentIndex === 0
|
||||||
|
|
||||||
|
headerText: qsTr("User name")
|
||||||
|
textFieldText: "New client"
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
|
}
|
||||||
|
|
||||||
DropDownType {
|
DropDownType {
|
||||||
id: serverSelector
|
id: serverSelector
|
||||||
|
|
||||||
|
@ -217,10 +242,11 @@ PageType {
|
||||||
serverSelector.severSelectorIndexChanged()
|
serverSelector.severSelectorIndexChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accessTypeSelector.currentIndex !== 0) {
|
//full access label
|
||||||
shareConnectionDrawer.headerText = qsTr("Accessing ") + serverSelector.text
|
// if (accessTypeSelector.currentIndex !== 0) {
|
||||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text
|
// shareConnectionDrawer.headerText = qsTr("Accessing ") + serverSelector.text
|
||||||
}
|
// shareConnectionDrawer.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text
|
||||||
|
// }
|
||||||
serverSelector.menuVisible = false
|
serverSelector.menuVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,8 +257,6 @@ PageType {
|
||||||
|
|
||||||
function handler() {
|
function handler() {
|
||||||
serverSelector.text = selectedText
|
serverSelector.text = selectedText
|
||||||
root.fullConfigServerSelectorText = selectedText
|
|
||||||
root.connectionServerSelectorText = selectedText
|
|
||||||
ServersModel.currentlyProcessedIndex = proxyServersModel.mapToSource(currentIndex)
|
ServersModel.currentlyProcessedIndex = proxyServersModel.mapToSource(currentIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,8 +265,6 @@ PageType {
|
||||||
DropDownType {
|
DropDownType {
|
||||||
id: protocolSelector
|
id: protocolSelector
|
||||||
|
|
||||||
visible: accessTypeSelector.currentIndex === 0
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
|
@ -280,12 +302,6 @@ PageType {
|
||||||
protocolSelector.menuVisible = false
|
protocolSelector.menuVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (accessTypeSelector.currentIndex === 0) {
|
|
||||||
handler()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: serverSelector
|
target: serverSelector
|
||||||
|
|
||||||
|
@ -304,13 +320,17 @@ PageType {
|
||||||
}
|
}
|
||||||
|
|
||||||
protocolSelector.text = selectedText
|
protocolSelector.text = selectedText
|
||||||
root.connectionServerSelectorText = serverSelector.text
|
|
||||||
|
|
||||||
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
|
||||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
|
||||||
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(currentIndex))
|
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(currentIndex))
|
||||||
|
|
||||||
fillConnectionTypeModel()
|
if (accessTypeSelector.currentIndex === 0) {
|
||||||
|
fillConnectionTypeModel()
|
||||||
|
} else {
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
ClientManagementModel.updateModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
|
ServersModel.getCurrentlyProcessedServerCredentials())
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fillConnectionTypeModel() {
|
function fillConnectionTypeModel() {
|
||||||
|
@ -378,18 +398,196 @@ PageType {
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
|
|
||||||
enabled: shareButtonEnabled
|
enabled: shareButtonEnabled
|
||||||
|
visible: accessTypeSelector.currentIndex === 0
|
||||||
|
|
||||||
text: qsTr("Share")
|
text: qsTr("Share")
|
||||||
imageSource: "qrc:/images/controls/share-2.svg"
|
imageSource: "qrc:/images/controls/share-2.svg"
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (accessTypeSelector.currentIndex === 0) {
|
ExportController.generateConfig(root.connectionTypesModel[exportTypeSelector.currentIndex].type)
|
||||||
ExportController.generateConfig(root.connectionTypesModel[exportTypeSelector.currentIndex].type)
|
}
|
||||||
} else {
|
}
|
||||||
ExportController.generateConfig(PageShare.ConfigType.AmneziaFullAccess)
|
|
||||||
|
Header2Type {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 24
|
||||||
|
Layout.bottomMargin: 16
|
||||||
|
|
||||||
|
visible: accessTypeSelector.currentIndex === 1
|
||||||
|
|
||||||
|
headerText: qsTr("Users")
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: usersListView
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: childrenRect.height
|
||||||
|
|
||||||
|
visible: accessTypeSelector.currentIndex === 1
|
||||||
|
|
||||||
|
model: ClientManagementModel
|
||||||
|
|
||||||
|
clip: true
|
||||||
|
interactive: false
|
||||||
|
|
||||||
|
delegate: Item {
|
||||||
|
implicitWidth: usersListView.width
|
||||||
|
implicitHeight: delegateContent.implicitHeight
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: delegateContent
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
anchors.rightMargin: -16
|
||||||
|
anchors.leftMargin: -16
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
text: userName
|
||||||
|
descriptionText: containerName
|
||||||
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
userInfoDrower.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {}
|
||||||
|
|
||||||
|
DrawerType {
|
||||||
|
id: userInfoDrower
|
||||||
|
|
||||||
|
width: root.width
|
||||||
|
height: root.height * 0.45
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 16
|
||||||
|
anchors.leftMargin: 16
|
||||||
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Header2Type {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
|
headerText: userName
|
||||||
|
descriptionText: serverSelector.text + ", " + containerName
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 24
|
||||||
|
|
||||||
|
defaultColor: "transparent"
|
||||||
|
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||||
|
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||||
|
disabledColor: "#878B91"
|
||||||
|
textColor: "#D7D8DB"
|
||||||
|
borderWidth: 1
|
||||||
|
|
||||||
|
text: qsTr("Rename")
|
||||||
|
|
||||||
|
onClicked: function() {
|
||||||
|
clientNameEditDrawer.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawerType {
|
||||||
|
id: clientNameEditDrawer
|
||||||
|
|
||||||
|
width: root.width
|
||||||
|
height: root.height * 0.35
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (clientNameEditDrawer.visible) {
|
||||||
|
clientName.textField.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 16
|
||||||
|
anchors.leftMargin: 16
|
||||||
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
TextFieldWithHeaderType {
|
||||||
|
id: clientName
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
headerText: qsTr("Client name")
|
||||||
|
textFieldText: userName
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
text: qsTr("Save")
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (clientName.textFieldText !== userName) {
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
ExportController.renameClient(index,
|
||||||
|
clientName.textFieldText,
|
||||||
|
ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
|
ServersModel.getCurrentlyProcessedServerCredentials())
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
clientNameEditDrawer.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
defaultColor: "transparent"
|
||||||
|
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||||
|
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||||
|
disabledColor: "#878B91"
|
||||||
|
textColor: "#D7D8DB"
|
||||||
|
borderWidth: 1
|
||||||
|
|
||||||
|
text: qsTr("Revoke")
|
||||||
|
|
||||||
|
onClicked: function() {
|
||||||
|
questionDrawer.headerText = qsTr("Revoke the config for a user - ") + userName + "?"
|
||||||
|
questionDrawer.descriptionText = qsTr("The user will no longer be able to connect to your server.")
|
||||||
|
questionDrawer.yesButtonText = qsTr("Continue")
|
||||||
|
questionDrawer.noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
|
questionDrawer.yesButtonFunction = function() {
|
||||||
|
questionDrawer.close()
|
||||||
|
userInfoDrower.close()
|
||||||
|
root.revokeConfig(index)
|
||||||
|
}
|
||||||
|
questionDrawer.noButtonFunction = function() {
|
||||||
|
questionDrawer.close()
|
||||||
|
}
|
||||||
|
questionDrawer.open()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
QuestionDrawer {
|
||||||
|
id: questionDrawer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,12 +227,15 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex, const Ser
|
||||||
configData = lastVpnConfig.value(proto);
|
configData = lastVpnConfig.value(proto);
|
||||||
configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData);
|
configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData);
|
||||||
} else {
|
} else {
|
||||||
configData = m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, proto, errorCode);
|
QString clientId;
|
||||||
|
configData = m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, proto, clientId, errorCode);
|
||||||
|
|
||||||
if (errorCode && *errorCode) {
|
if (errorCode && *errorCode) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit m_configurator->newVpnConfigCreated(clientId, "unnamed client", container, credentials);
|
||||||
|
|
||||||
QString configDataBeforeLocalProcessing = configData;
|
QString configDataBeforeLocalProcessing = configData;
|
||||||
|
|
||||||
configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData);
|
configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData);
|
||||||
|
@ -323,7 +326,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede
|
||||||
ErrorCode e = ErrorCode::NoError;
|
ErrorCode e = ErrorCode::NoError;
|
||||||
|
|
||||||
m_vpnConfiguration = createVpnConfiguration(serverIndex, credentials, container, containerConfig, &e);
|
m_vpnConfiguration = createVpnConfiguration(serverIndex, credentials, container, containerConfig, &e);
|
||||||
emit newVpnConfigurationCreated();
|
|
||||||
if (e) {
|
if (e) {
|
||||||
emit connectionStateChanged(Vpn::ConnectionState::Error);
|
emit connectionStateChanged(Vpn::ConnectionState::Error);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -79,8 +79,6 @@ signals:
|
||||||
|
|
||||||
void serviceIsNotReady();
|
void serviceIsNotReady();
|
||||||
|
|
||||||
void newVpnConfigurationCreated();
|
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||||
void onConnectionStateChanged(Vpn::ConnectionState state);
|
void onConnectionStateChanged(Vpn::ConnectionState state);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue