amnezia-client/client/ui/pages_logic/ClientInfoLogic.cpp
2023-01-19 17:49:17 +03:00

208 lines
9.6 KiB
C++

#include "ClientInfoLogic.h"
#include <QMessageBox>
#include "defines.h"
#include "core/errorstrings.h"
#include "core/servercontroller.h"
#include "ui/models/clientManagementModel.h"
#include "ui/uilogic.h"
namespace {
bool isErrorOccured(ErrorCode error) {
if (error != ErrorCode::NoError) {
QMessageBox::warning(nullptr, APPLICATION_NAME,
QObject::tr("An error occurred while saving the list of clients.") + "\n" + errorString(error));
return true;
}
return false;
}
}
ClientInfoLogic::ClientInfoLogic(UiLogic *logic, QObject *parent):
PageLogicBase(logic, parent)
{
}
void ClientInfoLogic::setCurrentClientId(int index)
{
m_currentClientIndex = index;
}
void ClientInfoLogic::onUpdatePage()
{
set_pageContentVisible(false);
set_busyIndicatorIsRunning(true);
const ServerCredentials credentials = m_settings->serverCredentials(uiLogic()->selectedServerIndex);
const DockerContainer container = m_settings->defaultContainer(uiLogic()->selectedServerIndex);
const QString containerNameString = ContainerProps::containerHumanNames().value(container);
set_labelCurrentVpnProtocolText(tr("Service: ") + containerNameString);
const QVector<amnezia::Proto> protocols = ContainerProps::protocolsForContainer(container);
if (!protocols.empty()) {
const Proto currentMainProtocol = protocols.front();
auto model = qobject_cast<ClientManagementModel*>(uiLogic()->clientManagementModel());
const QModelIndex modelIndex = model->index(m_currentClientIndex);
set_lineEditNameAliasText(model->data(modelIndex, ClientManagementModel::ClientRoles::NameRole).toString());
if (currentMainProtocol == Proto::OpenVpn) {
const QString certId = model->data(modelIndex, ClientManagementModel::ClientRoles::OpenVpnCertIdRole).toString();
QString certData = model->data(modelIndex, ClientManagementModel::ClientRoles::OpenVpnCertDataRole).toString();
if (certData.isEmpty() && !certId.isEmpty()) {
QString stdOut;
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
stdOut += data + "\n";
};
const QString getOpenVpnCertData = QString("sudo docker exec -i $CONTAINER_NAME bash -c 'cat /opt/amnezia/openvpn/pki/issued/%1.crt'")
.arg(certId);
const QString script = m_serverController->replaceVars(getOpenVpnCertData, m_serverController->genVarsForScript(credentials, container));
ErrorCode error = m_serverController->runScript(credentials, script, cbReadStdOut);
certData = stdOut;
m_serverController->disconnectFromHost(credentials);
if (isErrorOccured(error)) {
set_busyIndicatorIsRunning(false);
emit uiLogic()->closePage();
return;
}
}
set_labelOpenVpnCertId(certId);
set_textAreaOpenVpnCertData(certData);
} else if (currentMainProtocol == Proto::WireGuard) {
set_textAreaWireGuardKeyData(model->data(modelIndex, ClientManagementModel::ClientRoles::WireGuardPublicKey).toString());
}
}
set_pageContentVisible(true);
set_busyIndicatorIsRunning(false);
}
void ClientInfoLogic::onLineEditNameAliasEditingFinished()
{
set_busyIndicatorIsRunning(true);
auto model = qobject_cast<ClientManagementModel*>(uiLogic()->clientManagementModel());
const QModelIndex modelIndex = model->index(m_currentClientIndex);
model->setData(modelIndex, m_lineEditNameAliasText, ClientManagementModel::ClientRoles::NameRole);
const DockerContainer selectedContainer = m_settings->defaultContainer(uiLogic()->selectedServerIndex);
const ServerCredentials credentials = m_settings->serverCredentials(uiLogic()->selectedServerIndex);
const QVector<amnezia::Proto> protocols = ContainerProps::protocolsForContainer(selectedContainer);
if (!protocols.empty()) {
const Proto currentMainProtocol = protocols.front();
const QJsonObject clientsTable = model->getContent(currentMainProtocol);
ErrorCode error = setClientsList(credentials,
selectedContainer,
currentMainProtocol,
clientsTable);
isErrorOccured(error);
}
m_serverController->disconnectFromHost(credentials);
set_busyIndicatorIsRunning(false);
}
void ClientInfoLogic::onRevokeOpenVpnCertificateClicked()
{
set_busyIndicatorIsRunning(true);
const DockerContainer container = m_settings->defaultContainer(uiLogic()->selectedServerIndex);
const ServerCredentials credentials = m_settings->serverCredentials(uiLogic()->selectedServerIndex);
auto model = qobject_cast<ClientManagementModel*>(uiLogic()->clientManagementModel());
const QModelIndex modelIndex = model->index(m_currentClientIndex);
const QString certId = model->data(modelIndex, ClientManagementModel::ClientRoles::OpenVpnCertIdRole).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(certId);
const QString script = m_serverController->replaceVars(getOpenVpnCertData,
m_serverController->genVarsForScript(credentials, container));
auto error = m_serverController->runScript(credentials, script);
if (isErrorOccured(error)) {
set_busyIndicatorIsRunning(false);
emit uiLogic()->goToPage(Page::ServerSettings);
return;
}
model->removeRows(m_currentClientIndex);
const QJsonObject clientsTable = model->getContent(Proto::OpenVpn);
error = setClientsList(credentials, container, Proto::OpenVpn, clientsTable);
if (isErrorOccured(error)) {
set_busyIndicatorIsRunning(false);
return;
}
const QJsonObject &containerConfig = m_settings->containerConfig(uiLogic()->selectedServerIndex, container);
error = m_serverController->startupContainerWorker(credentials, container, containerConfig);
if (isErrorOccured(error)) {
set_busyIndicatorIsRunning(false);
return;
}
m_serverController->disconnectFromHost(credentials);
set_busyIndicatorIsRunning(false);
}
void ClientInfoLogic::onRevokeWireGuardKeyClicked()
{
set_busyIndicatorIsRunning(true);
ErrorCode error;
const DockerContainer container = m_settings->defaultContainer(uiLogic()->selectedServerIndex);
const ServerCredentials credentials = m_settings->serverCredentials(uiLogic()->selectedServerIndex);
const QString wireGuardConfigFile = "opt/amnezia/wireguard/wg0.conf";
const QString wireguardConfigString = m_serverController->getTextFileFromContainer(container, credentials, wireGuardConfigFile, &error);
if (isErrorOccured(error)) {
set_busyIndicatorIsRunning(false);
return;
}
auto model = qobject_cast<ClientManagementModel*>(uiLogic()->clientManagementModel());
const QModelIndex modelIndex = model->index(m_currentClientIndex);
const QString key = model->data(modelIndex, ClientManagementModel::ClientRoles::WireGuardPublicKey).toString();
auto configSections = wireguardConfigString.split("[", Qt::SkipEmptyParts);
for (auto &section : configSections) {
if (section.contains(key)) {
configSections.removeOne(section);
}
}
QString newWireGuardConfig = configSections.join("[");
newWireGuardConfig.insert(0, "[");
error = m_serverController->uploadTextFileToContainer(container, credentials, newWireGuardConfig,
protocols::wireguard::serverConfigPath,
QSsh::SftpOverwriteMode::SftpOverwriteExisting);
if (isErrorOccured(error)) {
set_busyIndicatorIsRunning(false);
return;
}
model->removeRows(m_currentClientIndex);
const QJsonObject clientsTable = model->getContent(Proto::WireGuard);
error = setClientsList(credentials, container, Proto::WireGuard, clientsTable);
if (isErrorOccured(error)) {
set_busyIndicatorIsRunning(false);
return;
}
error = m_serverController->runScript(credentials,
m_serverController->replaceVars("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip /opt/amnezia/wireguard/wg0.conf)'",
m_serverController->genVarsForScript(credentials, container)));
if (isErrorOccured(error)) {
set_busyIndicatorIsRunning(false);
return;
}
m_serverController->disconnectFromHost(credentials);
set_busyIndicatorIsRunning(false);
}
ErrorCode ClientInfoLogic::setClientsList(const ServerCredentials &credentials, DockerContainer container, Proto mainProtocol, const QJsonObject &clietns)
{
const QString mainProtocolString = ProtocolProps::protoToString(mainProtocol);
const QString clientsTableFile = QString("opt/amnezia/%1/clientsTable").arg(mainProtocolString);
ErrorCode error = m_serverController->uploadTextFileToContainer(container, credentials, QJsonDocument(clietns).toJson(), clientsTableFile);
return error;
}