added client management panel
- added classes for displaying the client management panel - added class for displaying the client info - added page to display a list of clients - added page to display OpenVpn client information - added diagram with OpenVpn certificate revocation process
This commit is contained in:
parent
3f257af7a9
commit
a42beb86c0
19 changed files with 771 additions and 102 deletions
|
|
@ -796,6 +796,59 @@ SshConnection *ServerController::connectToHost(const SshConnectionParameters &ss
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorCode ServerController::getClientsList(const ServerCredentials &credentials, DockerContainer container, Proto mainProtocol, QJsonObject &clietns)
|
||||||
|
{
|
||||||
|
QString stdOut;
|
||||||
|
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||||
|
stdOut += data + "\n";
|
||||||
|
};
|
||||||
|
|
||||||
|
ErrorCode error = ErrorCode::NoError;
|
||||||
|
if (mainProtocol == Proto::OpenVpn) {
|
||||||
|
error = runScript(credentials,
|
||||||
|
replaceVars(QString("sudo docker exec -i $CONTAINER_NAME bash -c 'ls /opt/amnezia/openvpn/pki/issued'"),
|
||||||
|
genVarsForScript(credentials, container)), cbReadStdOut);
|
||||||
|
// TODO error processing
|
||||||
|
if (!stdOut.isEmpty()) {
|
||||||
|
QStringList clietnsNames = stdOut.split("\n", Qt::SkipEmptyParts);
|
||||||
|
clietnsNames.removeAll("AmneziaReq.crt");
|
||||||
|
|
||||||
|
QByteArray clientsTableString = getTextFileFromContainer(container, credentials, "opt/amnezia/openvpn/clientsTable");
|
||||||
|
QJsonObject clientsTable = QJsonDocument::fromJson(clientsTableString).object();
|
||||||
|
for (auto &clietnId : clietnsNames) {
|
||||||
|
clietnId.replace(".crt", "");
|
||||||
|
if (!clientsTable.contains(clietnId)) {
|
||||||
|
stdOut.clear();
|
||||||
|
error = runScript(credentials,
|
||||||
|
replaceVars(QString("sudo docker exec -i $CONTAINER_NAME bash -c 'cat /opt/amnezia/openvpn/pki/issued/%1.crt'").arg(clietnId),
|
||||||
|
genVarsForScript(credentials, container)), cbReadStdOut);
|
||||||
|
// TODO error processing
|
||||||
|
QJsonObject client;
|
||||||
|
client["name"] = "";
|
||||||
|
client["certificate"] = stdOut;
|
||||||
|
clientsTable[clietnId] = client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QByteArray newClientsTableString = QJsonDocument(clientsTable).toJson();
|
||||||
|
if (clientsTableString != newClientsTableString) {
|
||||||
|
error = uploadTextFileToContainer(container, credentials, newClientsTableString, "opt/amnezia/openvpn/clientsTable");
|
||||||
|
}
|
||||||
|
// TODO error processing
|
||||||
|
clietns = clientsTable;
|
||||||
|
}
|
||||||
|
} else if (mainProtocol == Proto::WireGuard) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode ServerController::setClientsList(const ServerCredentials &credentials, DockerContainer container, Proto mainProtocol, QJsonObject &clietns)
|
||||||
|
{
|
||||||
|
auto error = uploadTextFileToContainer(container, credentials, QJsonDocument(clietns).toJson(), "opt/amnezia/openvpn/clientsTable");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
void ServerController::disconnectFromHost(const ServerCredentials &credentials)
|
void ServerController::disconnectFromHost(const ServerCredentials &credentials)
|
||||||
{
|
{
|
||||||
SshConnection *client = acquireConnection(sshParams(credentials));
|
SshConnection *client = acquireConnection(sshParams(credentials));
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@ public:
|
||||||
QString checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr);
|
QString checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr);
|
||||||
QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams);
|
QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams);
|
||||||
|
|
||||||
|
ErrorCode getClientsList(const ServerCredentials &credentials, DockerContainer container, Proto mainProtocol, QJsonObject &clietns);
|
||||||
|
ErrorCode setClientsList(const ServerCredentials &credentials, DockerContainer container, Proto mainProtocol, QJsonObject &clietns);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container);
|
ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container);
|
||||||
|
|
|
||||||
|
|
@ -160,5 +160,9 @@
|
||||||
<file>ui/qml/Pages/PageQrDecoderIos.qml</file>
|
<file>ui/qml/Pages/PageQrDecoderIos.qml</file>
|
||||||
<file>server_scripts/website_tor/Dockerfile</file>
|
<file>server_scripts/website_tor/Dockerfile</file>
|
||||||
<file>ui/qml/Pages/PageViewConfig.qml</file>
|
<file>ui/qml/Pages/PageViewConfig.qml</file>
|
||||||
|
<file>ui/qml/Pages/PageClientManagement.qml</file>
|
||||||
|
<file>ui/qml/Pages/ClientInfo/PageClientInfoBase.qml</file>
|
||||||
|
<file>ui/qml/Pages/ClientInfo/PageClientInfoOpenVPN.qml</file>
|
||||||
|
<file>ui/qml/Pages/ClientInfo/PageClientInfoWireGuard.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
||||||
75
client/ui/models/clientManagementModel.cpp
Normal file
75
client/ui/models/clientManagementModel.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
#include "clientManagementModel.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<ClientInfo> &data)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_content = data;
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ClientManagementModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
return static_cast<int>(m_content.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid() || index.row() < 0
|
||||||
|
|| index.row() >= static_cast<int>(m_content.size())) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == NameRole) {
|
||||||
|
return m_content[index.row()].name;
|
||||||
|
}
|
||||||
|
if (role == CertIdRole) {
|
||||||
|
return m_content[index.row()].certId;
|
||||||
|
}
|
||||||
|
if (role == CertDataRole) {
|
||||||
|
return m_content[index.row()].certData;
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientManagementModel::setData(const QModelIndex &index, QVariant data, int role)
|
||||||
|
{
|
||||||
|
if (!index.isValid() || index.row() < 0
|
||||||
|
|| index.row() >= static_cast<int>(m_content.size())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == NameRole) {
|
||||||
|
m_content[index.row()].name = data.toString();
|
||||||
|
}
|
||||||
|
if (role == CertIdRole) {
|
||||||
|
m_content[index.row()].certId = data.toString();
|
||||||
|
}
|
||||||
|
if (role == CertDataRole) {
|
||||||
|
m_content[index.row()].certData = data.toString();
|
||||||
|
}
|
||||||
|
emit dataChanged(index, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> ClientManagementModel::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles[NameRole] = "clientName";
|
||||||
|
roles[CertIdRole] = "certId";
|
||||||
|
roles[CertDataRole] = "certData";
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
42
client/ui/models/clientManagementModel.h
Normal file
42
client/ui/models/clientManagementModel.h
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef CLIENTMANAGEMENTMODEL_H
|
||||||
|
#define CLIENTMANAGEMENTMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
|
class ClientManagementModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum ClientRoles {
|
||||||
|
NameRole = Qt::UserRole + 1,
|
||||||
|
CertIdRole,
|
||||||
|
CertDataRole
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClientInfo
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
QString certId;
|
||||||
|
QString certData;
|
||||||
|
};
|
||||||
|
|
||||||
|
ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
void clearData();
|
||||||
|
void setContent(const QVector<ClientInfo> &data);
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
void setData(const QModelIndex &index, QVariant data, int role = Qt::DisplayRole);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Settings> m_settings; //TODO remove this?
|
||||||
|
QVector<ClientInfo> m_content;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CLIENTMANAGEMENTMODEL_H
|
||||||
|
|
@ -12,7 +12,8 @@ public:
|
||||||
enum Type {
|
enum Type {
|
||||||
Basic,
|
Basic,
|
||||||
Proto,
|
Proto,
|
||||||
ShareProto
|
ShareProto,
|
||||||
|
ClientInfo
|
||||||
};
|
};
|
||||||
Q_ENUM(Type)
|
Q_ENUM(Type)
|
||||||
};
|
};
|
||||||
|
|
@ -24,7 +25,7 @@ enum class Page {Start = 0, NewServer, NewServerProtocols, Vpn,
|
||||||
Wizard, WizardLow, WizardMedium, WizardHigh, WizardVpnMode, ServerConfiguringProgress,
|
Wizard, WizardLow, WizardMedium, WizardHigh, WizardVpnMode, ServerConfiguringProgress,
|
||||||
GeneralSettings, AppSettings, NetworkSettings, ServerSettings,
|
GeneralSettings, AppSettings, NetworkSettings, ServerSettings,
|
||||||
ServerContainers, ServersList, ShareConnection, Sites,
|
ServerContainers, ServersList, ShareConnection, Sites,
|
||||||
ProtocolSettings, ProtocolShare, QrDecoder, QrDecoderIos, About, ViewConfig};
|
ProtocolSettings, ProtocolShare, QrDecoder, QrDecoderIos, About, ViewConfig, ClientManagement, ClientInfo};
|
||||||
Q_ENUM_NS(Page)
|
Q_ENUM_NS(Page)
|
||||||
|
|
||||||
static void declareQmlPageEnum() {
|
static void declareQmlPageEnum() {
|
||||||
|
|
|
||||||
43
client/ui/pages_logic/ClientInfoLogic.cpp
Normal file
43
client/ui/pages_logic/ClientInfoLogic.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include "ClientInfoLogic.h"
|
||||||
|
|
||||||
|
#include "core/servercontroller.h"
|
||||||
|
#include "ui/models/clientManagementModel.h"
|
||||||
|
#include "ui/uilogic.h"
|
||||||
|
|
||||||
|
ClientInfoLogic::ClientInfoLogic(UiLogic *logic, QObject *parent):
|
||||||
|
PageLogicBase(logic, parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientInfoLogic::setCurrentClientId(int index)
|
||||||
|
{
|
||||||
|
m_currentClientIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientInfoLogic::onUpdatePage()
|
||||||
|
{
|
||||||
|
DockerContainer selectedContainer = m_settings->defaultContainer(uiLogic()->selectedServerIndex);
|
||||||
|
QString selectedContainerName = ContainerProps::containerHumanNames().value(selectedContainer);
|
||||||
|
set_labelCurrentVpnProtocolText(tr("Service: ") + selectedContainerName);
|
||||||
|
|
||||||
|
auto model = qobject_cast<ClientManagementModel*>(uiLogic()->clientManagementModel());
|
||||||
|
auto modelIndex = model->index(m_currentClientIndex);
|
||||||
|
set_lineEditNameAliasText(model->data(modelIndex, ClientManagementModel::ClientRoles::NameRole).toString());
|
||||||
|
set_labelCertId(model->data(modelIndex, ClientManagementModel::ClientRoles::CertIdRole).toString());
|
||||||
|
set_textAreaCertificate(model->data(modelIndex, ClientManagementModel::ClientRoles::CertDataRole).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientInfoLogic::onLineEditNameAliasEditingFinished()
|
||||||
|
{
|
||||||
|
auto model = qobject_cast<ClientManagementModel*>(uiLogic()->clientManagementModel());
|
||||||
|
auto modelIndex = model->index(m_currentClientIndex);
|
||||||
|
model->setData(modelIndex, m_lineEditNameAliasText, ClientManagementModel::ClientRoles::NameRole);
|
||||||
|
|
||||||
|
m_serverController->setClientsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientInfoLogic::onRevokeCertificateClicked()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
32
client/ui/pages_logic/ClientInfoLogic.h
Normal file
32
client/ui/pages_logic/ClientInfoLogic.h
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef CLIENTINFOLOGIC_H
|
||||||
|
#define CLIENTINFOLOGIC_H
|
||||||
|
|
||||||
|
#include "PageLogicBase.h"
|
||||||
|
|
||||||
|
class UiLogic;
|
||||||
|
|
||||||
|
class ClientInfoLogic : public PageLogicBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
AUTO_PROPERTY(QString, lineEditNameAliasText)
|
||||||
|
AUTO_PROPERTY(QString, labelCertId)
|
||||||
|
AUTO_PROPERTY(QString, textAreaCertificate)
|
||||||
|
AUTO_PROPERTY(QString, labelCurrentVpnProtocolText)
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClientInfoLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||||
|
~ClientInfoLogic() = default;
|
||||||
|
|
||||||
|
void setCurrentClientId(int index);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onUpdatePage() override;
|
||||||
|
void onLineEditNameAliasEditingFinished();
|
||||||
|
void onRevokeCertificateClicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_currentClientIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CLIENTINFOLOGIC_H
|
||||||
44
client/ui/pages_logic/ClientManagementLogic.cpp
Normal file
44
client/ui/pages_logic/ClientManagementLogic.cpp
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "ClientManagementLogic.h"
|
||||||
|
|
||||||
|
#include "core/servercontroller.h"
|
||||||
|
#include "ui/pages_logic/ClientInfoLogic.h"
|
||||||
|
#include "ui/models/clientManagementModel.h"
|
||||||
|
#include "ui/uilogic.h"
|
||||||
|
|
||||||
|
ClientManagementLogic::ClientManagementLogic(UiLogic *logic, QObject *parent):
|
||||||
|
PageLogicBase(logic, parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientManagementLogic::onUpdatePage()
|
||||||
|
{
|
||||||
|
DockerContainer selectedContainer = m_settings->defaultContainer(uiLogic()->selectedServerIndex);
|
||||||
|
QString selectedContainerName = ContainerProps::containerHumanNames().value(selectedContainer);
|
||||||
|
set_labelCurrentVpnProtocolText(tr("Service: ") + selectedContainerName);
|
||||||
|
|
||||||
|
QJsonObject clients;
|
||||||
|
|
||||||
|
auto protocols = ContainerProps::protocolsForContainer(selectedContainer);
|
||||||
|
if (!protocols.empty()) {
|
||||||
|
m_currentMainProtocol = protocols.front();
|
||||||
|
|
||||||
|
ErrorCode e = m_serverController->getClientsList(m_settings->serverCredentials(uiLogic()->selectedServerIndex),
|
||||||
|
selectedContainer, m_currentMainProtocol, clients);
|
||||||
|
}
|
||||||
|
QVector<ClientManagementModel::ClientInfo> clientsArray;
|
||||||
|
for (auto &clientId : clients.keys()) {
|
||||||
|
ClientManagementModel::ClientInfo clientInfo;
|
||||||
|
clientInfo.certId = clientId;
|
||||||
|
clientInfo.name = clients[clientId].toObject()["name"].toString();
|
||||||
|
clientInfo.certData = clients[clientId].toObject()["certificate"].toString();
|
||||||
|
clientsArray.push_back(clientInfo);
|
||||||
|
}
|
||||||
|
qobject_cast<ClientManagementModel*>(uiLogic()->clientManagementModel())->setContent(clientsArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientManagementLogic::onClientItemClicked(int index)
|
||||||
|
{
|
||||||
|
uiLogic()->pageLogic<ClientInfoLogic>()->setCurrentClientId(index);
|
||||||
|
emit uiLogic()->goToClientInfoPage(m_currentMainProtocol);
|
||||||
|
}
|
||||||
28
client/ui/pages_logic/ClientManagementLogic.h
Normal file
28
client/ui/pages_logic/ClientManagementLogic.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef CLIENTMANAGMENTLOGIC_H
|
||||||
|
#define CLIENTMANAGMENTLOGIC_H
|
||||||
|
|
||||||
|
#include "PageLogicBase.h"
|
||||||
|
|
||||||
|
#include "protocols/protocols_defs.h"
|
||||||
|
|
||||||
|
class UiLogic;
|
||||||
|
|
||||||
|
class ClientManagementLogic : public PageLogicBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
AUTO_PROPERTY(QString, labelCurrentVpnProtocolText)
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClientManagementLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||||
|
~ClientManagementLogic() = default;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onUpdatePage() override;
|
||||||
|
void onClientItemClicked(int index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
amnezia::Proto m_currentMainProtocol;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CLIENTMANAGMENTLOGIC_H
|
||||||
15
client/ui/qml/Pages/ClientInfo/PageClientInfoBase.qml
Normal file
15
client/ui/qml/Pages/ClientInfo/PageClientInfoBase.qml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import PageEnum 1.0
|
||||||
|
import ProtocolEnum 1.0
|
||||||
|
import "../"
|
||||||
|
import "../../Controls"
|
||||||
|
import "../../Config"
|
||||||
|
|
||||||
|
PageBase {
|
||||||
|
id: root
|
||||||
|
property var protocol: ProtocolEnum.Any
|
||||||
|
page: PageEnum.ClientInfo
|
||||||
|
logic: ClientInfoLogic
|
||||||
|
}
|
||||||
103
client/ui/qml/Pages/ClientInfo/PageClientInfoOpenVPN.qml
Normal file
103
client/ui/qml/Pages/ClientInfo/PageClientInfoOpenVPN.qml
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import ProtocolEnum 1.0
|
||||||
|
import "../"
|
||||||
|
import "../../Controls"
|
||||||
|
import "../../Config"
|
||||||
|
|
||||||
|
PageClientInfoBase {
|
||||||
|
id: root
|
||||||
|
protocol: ProtocolEnum.OpenVpn
|
||||||
|
|
||||||
|
BackButton {
|
||||||
|
id: back
|
||||||
|
}
|
||||||
|
|
||||||
|
Caption {
|
||||||
|
id: caption
|
||||||
|
text: qsTr("Client Info")
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: fl
|
||||||
|
width: root.width
|
||||||
|
anchors.top: caption.bottom
|
||||||
|
anchors.topMargin: 20
|
||||||
|
anchors.bottom: root.bottom
|
||||||
|
anchors.bottomMargin: 20
|
||||||
|
anchors.left: root.left
|
||||||
|
anchors.leftMargin: 30
|
||||||
|
anchors.right: root.right
|
||||||
|
anchors.rightMargin: 30
|
||||||
|
|
||||||
|
contentHeight: content.height
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: content
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
LabelType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pixelSize: 20
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
text: ClientInfoLogic.labelCurrentVpnProtocolText
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelType {
|
||||||
|
height: 21
|
||||||
|
text: qsTr("Client name")
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFieldType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 31
|
||||||
|
text: ClientInfoLogic.lineEditNameAliasText
|
||||||
|
onEditingFinished: {
|
||||||
|
ClientInfoLogic.lineEditNameAliasText = text
|
||||||
|
ClientInfoLogic.onLineEditNameAliasEditingFinished()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelType {
|
||||||
|
Layout.topMargin: 20
|
||||||
|
height: 21
|
||||||
|
text: qsTr("Certificate id")
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
text: ClientInfoLogic.labelCertId
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelType {
|
||||||
|
Layout.topMargin: 20
|
||||||
|
height: 21
|
||||||
|
text: qsTr("Certificate")
|
||||||
|
}
|
||||||
|
|
||||||
|
TextAreaType {
|
||||||
|
Layout.preferredHeight: 200
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
textArea.readOnly: true
|
||||||
|
textArea.wrapMode: TextEdit.WrapAnywhere
|
||||||
|
textArea.verticalAlignment: Text.AlignTop
|
||||||
|
textArea.text: ClientInfoLogic.textAreaCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 41
|
||||||
|
text: qsTr("Revoke Certificate")
|
||||||
|
onClicked: {
|
||||||
|
ClientInfoLogic.onRevokeCertificateClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
client/ui/qml/Pages/ClientInfo/PageClientInfoWireGuard.qml
Normal file
11
client/ui/qml/Pages/ClientInfo/PageClientInfoWireGuard.qml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import ProtocolEnum 1.0
|
||||||
|
import "../"
|
||||||
|
import "../../Controls"
|
||||||
|
import "../../Config"
|
||||||
|
|
||||||
|
PageClientInfoBase {
|
||||||
|
|
||||||
|
}
|
||||||
121
client/ui/qml/Pages/PageClientManagement.qml
Normal file
121
client/ui/qml/Pages/PageClientManagement.qml
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Shapes 1.4
|
||||||
|
import PageEnum 1.0
|
||||||
|
import "./"
|
||||||
|
import "../Controls"
|
||||||
|
import "../Config"
|
||||||
|
|
||||||
|
PageBase {
|
||||||
|
id: root
|
||||||
|
page: PageEnum.ClientManagement
|
||||||
|
logic: ClientManagementLogic
|
||||||
|
|
||||||
|
BackButton {
|
||||||
|
id: back
|
||||||
|
}
|
||||||
|
|
||||||
|
Caption {
|
||||||
|
id: caption
|
||||||
|
text: qsTr("Clients Management")
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: fl
|
||||||
|
width: root.width
|
||||||
|
anchors.top: caption.bottom
|
||||||
|
anchors.topMargin: 20
|
||||||
|
anchors.bottom: root.bottom
|
||||||
|
anchors.bottomMargin: 20
|
||||||
|
|
||||||
|
contentHeight: content.height
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: content
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
LabelType {
|
||||||
|
anchors.left: parent.left
|
||||||
|
font.pixelSize: 20
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
text: ServerSettingsLogic.labelCurrentVpnProtocolText
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: lv_clients
|
||||||
|
width: parent.width
|
||||||
|
implicitHeight: contentHeight + 20
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
anchors.rightMargin: 10
|
||||||
|
topMargin: 10
|
||||||
|
spacing: 10
|
||||||
|
clip: true
|
||||||
|
model: UiLogic.clientManagementModel
|
||||||
|
highlightRangeMode: ListView.ApplyRange
|
||||||
|
highlightMoveVelocity: -1
|
||||||
|
delegate: Item {
|
||||||
|
implicitWidth: lv_clients.width
|
||||||
|
implicitHeight: 60
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: ms
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
ClientManagementLogic.onClientItemClicked(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
gradient: ms.containsMouse ? gradient_containsMouse : gradient_notContainsMouse
|
||||||
|
LinearGradient {
|
||||||
|
id: gradient_notContainsMouse
|
||||||
|
x1: 0 ; y1:0
|
||||||
|
x2: 0 ; y2: height
|
||||||
|
stops: [
|
||||||
|
GradientStop { position: 0.0; color: "#FAFBFE" },
|
||||||
|
GradientStop { position: 1.0; color: "#ECEEFF" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
LinearGradient {
|
||||||
|
id: gradient_containsMouse
|
||||||
|
x1: 0 ; y1:0
|
||||||
|
x2: 0 ; y2: height
|
||||||
|
stops: [
|
||||||
|
GradientStop { position: 0.0; color: "#FAFBFE" },
|
||||||
|
GradientStop { position: 1.0; color: "#DCDEDF" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
x: 10
|
||||||
|
y: 10
|
||||||
|
font.family: "Lato"
|
||||||
|
font.styleName: "normal"
|
||||||
|
color: "#181922"
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
text: clientName
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelType {
|
||||||
|
x: 20
|
||||||
|
y: 40
|
||||||
|
// width: 141
|
||||||
|
height: 16
|
||||||
|
text: certId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
import PageEnum 1.0
|
import PageEnum 1.0
|
||||||
import "./"
|
import "./"
|
||||||
import "../Controls"
|
import "../Controls"
|
||||||
|
|
@ -15,33 +16,48 @@ PageBase {
|
||||||
BackButton {
|
BackButton {
|
||||||
id: back
|
id: back
|
||||||
}
|
}
|
||||||
|
|
||||||
Caption {
|
Caption {
|
||||||
|
id: caption
|
||||||
text: qsTr("Server settings")
|
text: qsTr("Server settings")
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
LabelType {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
Flickable {
|
||||||
y: 150
|
id: fl
|
||||||
width: 341
|
width: root.width
|
||||||
height: 31
|
anchors.top: caption.bottom
|
||||||
font.pixelSize: 20
|
anchors.topMargin: 20
|
||||||
horizontalAlignment: Text.AlignHCenter
|
anchors.bottom: logo.top
|
||||||
text: ServerSettingsLogic.labelCurrentVpnProtocolText
|
anchors.bottomMargin: 20
|
||||||
}
|
anchors.left: root.left
|
||||||
// LabelType {
|
anchors.leftMargin: 30
|
||||||
// anchors.horizontalCenter: parent.horizontalCenter
|
anchors.right: root.right
|
||||||
// y: 120
|
anchors.rightMargin: 30
|
||||||
// width: 341
|
|
||||||
// height: 31
|
contentHeight: content.height
|
||||||
// font.pixelSize: 20
|
clip: true
|
||||||
// horizontalAlignment: Text.AlignHCenter
|
|
||||||
// text: ServerSettingsLogic.labelServerText
|
ColumnLayout {
|
||||||
// }
|
id: content
|
||||||
|
enabled: logic.pageEnabled
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
TextFieldType {
|
TextFieldType {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
y: 120
|
Layout.preferredWidth: 251
|
||||||
width: 341
|
Layout.preferredHeight: 31
|
||||||
height: 31
|
text: ServerSettingsLogic.lineEditDescriptionText
|
||||||
|
onEditingFinished: {
|
||||||
|
ServerSettingsLogic.lineEditDescriptionText = text
|
||||||
|
ServerSettingsLogic.onLineEditDescriptionEditingFinished()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFieldType {
|
||||||
|
Layout.fillWidth: true
|
||||||
font.pixelSize: 20
|
font.pixelSize: 20
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
text: ServerSettingsLogic.labelServerText
|
text: ServerSettingsLogic.labelServerText
|
||||||
|
|
@ -50,71 +66,26 @@ PageBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelType {
|
LabelType {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
Layout.fillWidth: true
|
||||||
y: 530
|
font.pixelSize: 20
|
||||||
width: 301
|
horizontalAlignment: Text.AlignHCenter
|
||||||
height: 41
|
text: ServerSettingsLogic.labelCurrentVpnProtocolText
|
||||||
text: ServerSettingsLogic.labelWaitInfoText
|
|
||||||
visible: ServerSettingsLogic.labelWaitInfoVisible
|
|
||||||
}
|
|
||||||
TextFieldType {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
y: 80
|
|
||||||
width: 251
|
|
||||||
height: 31
|
|
||||||
text: ServerSettingsLogic.lineEditDescriptionText
|
|
||||||
onEditingFinished: {
|
|
||||||
ServerSettingsLogic.lineEditDescriptionText = text
|
|
||||||
ServerSettingsLogic.onLineEditDescriptionEditingFinished()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlueButtonType {
|
BlueButtonType {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
Layout.topMargin: 15
|
||||||
y: 410
|
Layout.fillWidth: true
|
||||||
width: parent.width - 40
|
Layout.preferredHeight: 41
|
||||||
height: 40
|
|
||||||
text: ServerSettingsLogic.pushButtonClearText
|
|
||||||
visible: ServerSettingsLogic.pushButtonClearVisible
|
|
||||||
onClicked: {
|
|
||||||
ServerSettingsLogic.onPushButtonClearServer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BlueButtonType {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
y: 350
|
|
||||||
width: parent.width - 40
|
|
||||||
height: 40
|
|
||||||
text: ServerSettingsLogic.pushButtonClearClientCacheText
|
|
||||||
visible: ServerSettingsLogic.pushButtonClearClientCacheVisible
|
|
||||||
onClicked: {
|
|
||||||
ServerSettingsLogic.onPushButtonClearClientCacheClicked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BlueButtonType {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
y: 470
|
|
||||||
width: parent.width - 40
|
|
||||||
height: 40
|
|
||||||
text: qsTr("Forget this server")
|
|
||||||
onClicked: {
|
|
||||||
ServerSettingsLogic.onPushButtonForgetServer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BlueButtonType {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
y: 210
|
|
||||||
width: parent.width - 40
|
|
||||||
height: 40
|
|
||||||
text: qsTr("Protocols and Services")
|
text: qsTr("Protocols and Services")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
UiLogic.goToPage(PageEnum.ServerContainers)
|
UiLogic.goToPage(PageEnum.ServerContainers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BlueButtonType {
|
BlueButtonType {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
Layout.topMargin: 10
|
||||||
y: 260
|
Layout.fillWidth: true
|
||||||
width: parent.width - 40
|
Layout.preferredHeight: 41
|
||||||
height: 40
|
|
||||||
text: qsTr("Share Server (FULL ACCESS)")
|
text: qsTr("Share Server (FULL ACCESS)")
|
||||||
visible: ServerSettingsLogic.pushButtonShareFullVisible
|
visible: ServerSettingsLogic.pushButtonShareFullVisible
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
|
@ -122,7 +93,58 @@ PageBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlueButtonType {
|
||||||
|
Layout.topMargin: 10
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 41
|
||||||
|
text: qsTr("Clients Management")
|
||||||
|
onClicked: {
|
||||||
|
UiLogic.goToPage(PageEnum.ClientManagement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButtonType {
|
||||||
|
Layout.topMargin: 30
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 41
|
||||||
|
text: ServerSettingsLogic.pushButtonClearClientCacheText
|
||||||
|
visible: ServerSettingsLogic.pushButtonClearClientCacheVisible
|
||||||
|
onClicked: {
|
||||||
|
ServerSettingsLogic.onPushButtonClearClientCacheClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButtonType {
|
||||||
|
Layout.topMargin: 10
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 41
|
||||||
|
text: ServerSettingsLogic.pushButtonClearText
|
||||||
|
visible: ServerSettingsLogic.pushButtonClearVisible
|
||||||
|
onClicked: {
|
||||||
|
ServerSettingsLogic.onPushButtonClearServer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButtonType {
|
||||||
|
Layout.topMargin: 10
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 41
|
||||||
|
text: qsTr("Forget this server")
|
||||||
|
onClicked: {
|
||||||
|
ServerSettingsLogic.onPushButtonForgetServer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: ServerSettingsLogic.labelWaitInfoText
|
||||||
|
visible: ServerSettingsLogic.labelWaitInfoVisible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Logo {
|
Logo {
|
||||||
|
id: logo
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,14 @@ import "Controls"
|
||||||
import "Pages"
|
import "Pages"
|
||||||
import "Pages/Protocols"
|
import "Pages/Protocols"
|
||||||
import "Pages/Share"
|
import "Pages/Share"
|
||||||
|
import "Pages/ClientInfo"
|
||||||
import "Config"
|
import "Config"
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
property var pages: ({})
|
property var pages: ({})
|
||||||
property var protocolPages: ({})
|
property var protocolPages: ({})
|
||||||
property var sharePages: ({})
|
property var sharePages: ({})
|
||||||
|
property var clientInfoPages: ({})
|
||||||
|
|
||||||
id: root
|
id: root
|
||||||
visible: true
|
visible: true
|
||||||
|
|
@ -39,6 +41,7 @@ Window {
|
||||||
if (type === PageType.Basic) p_obj = pages[page]
|
if (type === PageType.Basic) p_obj = pages[page]
|
||||||
else if (type === PageType.Proto) p_obj = protocolPages[page]
|
else if (type === PageType.Proto) p_obj = protocolPages[page]
|
||||||
else if (type === PageType.ShareProto) p_obj = sharePages[page]
|
else if (type === PageType.ShareProto) p_obj = sharePages[page]
|
||||||
|
else if (type === PageType.ClientInfo) p_obj = clientInfoPages[page]
|
||||||
else return
|
else return
|
||||||
|
|
||||||
//console.debug("QML gotoPage " + type + " " + page + " " + p_obj)
|
//console.debug("QML gotoPage " + type + " " + page + " " + p_obj)
|
||||||
|
|
@ -175,6 +178,19 @@ Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FolderListModel {
|
||||||
|
id: folderModelClientInfo
|
||||||
|
folder: "qrc:/ui/qml/Pages/ClientInfo/"
|
||||||
|
nameFilters: ["*.qml"]
|
||||||
|
showDirs: false
|
||||||
|
|
||||||
|
onStatusChanged: if (status == FolderListModel.Ready) {
|
||||||
|
for (var i=0; i<folderModelClientInfo.count; i++) {
|
||||||
|
createPagesObjects(folderModelClientInfo.get(i, "filePath"), PageType.ClientInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createPagesObjects(file, type) {
|
function createPagesObjects(file, type) {
|
||||||
if (file.indexOf("Base") !== -1) return; // skip Base Pages
|
if (file.indexOf("Base") !== -1) return; // skip Base Pages
|
||||||
//console.debug("Creating compenent " + file + " for " + type);
|
//console.debug("Creating compenent " + file + " for " + type);
|
||||||
|
|
@ -198,6 +214,9 @@ Window {
|
||||||
else if (type === PageType.ShareProto) {
|
else if (type === PageType.ShareProto) {
|
||||||
sharePages[obj.protocol] = obj
|
sharePages[obj.protocol] = obj
|
||||||
}
|
}
|
||||||
|
else if (type === PageType.ClientInfo) {
|
||||||
|
clientInfoPages[obj.protocol] = obj
|
||||||
|
}
|
||||||
|
|
||||||
// console.debug("Created compenent " + component.url + " for " + type);
|
// console.debug("Created compenent " + component.url + " for " + type);
|
||||||
}
|
}
|
||||||
|
|
@ -227,7 +246,10 @@ Window {
|
||||||
//console.debug("Qml Connections onGoToShareProtocolPage " + protocol);
|
//console.debug("Qml Connections onGoToShareProtocolPage " + protocol);
|
||||||
root.gotoPage(PageType.ShareProto, protocol, reset, slide)
|
root.gotoPage(PageType.ShareProto, protocol, reset, slide)
|
||||||
}
|
}
|
||||||
|
function onGoToClientInfoPage(protocol, reset, slide) {
|
||||||
|
//console.debug("Qml Connections onGoToClientInfoPage " + protocol);
|
||||||
|
root.gotoPage(PageType.ClientInfo, protocol, reset, slide)
|
||||||
|
}
|
||||||
|
|
||||||
function onClosePage() {
|
function onClosePage() {
|
||||||
root.close_page()
|
root.close_page()
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,8 @@
|
||||||
#include "pages_logic/ViewConfigLogic.h"
|
#include "pages_logic/ViewConfigLogic.h"
|
||||||
#include "pages_logic/VpnLogic.h"
|
#include "pages_logic/VpnLogic.h"
|
||||||
#include "pages_logic/WizardLogic.h"
|
#include "pages_logic/WizardLogic.h"
|
||||||
|
#include "pages_logic/ClientManagementLogic.h"
|
||||||
|
#include "pages_logic/ClientInfoLogic.h"
|
||||||
|
|
||||||
#include "pages_logic/protocols/CloakLogic.h"
|
#include "pages_logic/protocols/CloakLogic.h"
|
||||||
#include "pages_logic/protocols/OpenVpnLogic.h"
|
#include "pages_logic/protocols/OpenVpnLogic.h"
|
||||||
|
|
@ -87,6 +89,7 @@ UiLogic::UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigur
|
||||||
{
|
{
|
||||||
m_containersModel = new ContainersModel(settings, this);
|
m_containersModel = new ContainersModel(settings, this);
|
||||||
m_protocolsModel = new ProtocolsModel(settings, this);
|
m_protocolsModel = new ProtocolsModel(settings, this);
|
||||||
|
m_clientManagementModel = new ClientManagementModel(settings, this);
|
||||||
m_vpnConnection = new VpnConnection(settings, configurator, serverController);
|
m_vpnConnection = new VpnConnection(settings, configurator, serverController);
|
||||||
m_vpnConnection->moveToThread(&m_vpnConnectionThread);
|
m_vpnConnection->moveToThread(&m_vpnConnectionThread);
|
||||||
m_vpnConnectionThread.start();
|
m_vpnConnectionThread.start();
|
||||||
|
|
@ -676,4 +679,6 @@ void UiLogic::registerPagesLogic()
|
||||||
registerPageLogic<ViewConfigLogic>();
|
registerPageLogic<ViewConfigLogic>();
|
||||||
registerPageLogic<VpnLogic>();
|
registerPageLogic<VpnLogic>();
|
||||||
registerPageLogic<WizardLogic>();
|
registerPageLogic<WizardLogic>();
|
||||||
|
registerPageLogic<ClientManagementLogic>();
|
||||||
|
registerPageLogic<ClientInfoLogic>();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "models/containers_model.h"
|
#include "models/containers_model.h"
|
||||||
#include "models/protocols_model.h"
|
#include "models/protocols_model.h"
|
||||||
|
#include "models/clientManagementModel.h"
|
||||||
|
|
||||||
#include "notificationhandler.h"
|
#include "notificationhandler.h"
|
||||||
|
|
||||||
|
|
@ -42,6 +43,8 @@ class StartPageLogic;
|
||||||
class ViewConfigLogic;
|
class ViewConfigLogic;
|
||||||
class VpnLogic;
|
class VpnLogic;
|
||||||
class WizardLogic;
|
class WizardLogic;
|
||||||
|
class ClientManagementLogic;
|
||||||
|
class ClientInfoLogic;
|
||||||
|
|
||||||
class PageProtocolLogicBase;
|
class PageProtocolLogicBase;
|
||||||
class OpenVpnLogic;
|
class OpenVpnLogic;
|
||||||
|
|
@ -64,6 +67,7 @@ class UiLogic : public QObject
|
||||||
|
|
||||||
READONLY_PROPERTY(QObject *, containersModel)
|
READONLY_PROPERTY(QObject *, containersModel)
|
||||||
READONLY_PROPERTY(QObject *, protocolsModel)
|
READONLY_PROPERTY(QObject *, protocolsModel)
|
||||||
|
READONLY_PROPERTY(QObject *, clientManagementModel)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigurator> configurator,
|
explicit UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigurator> configurator,
|
||||||
|
|
@ -87,6 +91,8 @@ public:
|
||||||
friend class ViewConfigLogic;
|
friend class ViewConfigLogic;
|
||||||
friend class VpnLogic;
|
friend class VpnLogic;
|
||||||
friend class WizardLogic;
|
friend class WizardLogic;
|
||||||
|
friend class ClientManagementLogic;
|
||||||
|
friend class ClientInfoLogic;
|
||||||
|
|
||||||
friend class PageProtocolLogicBase;
|
friend class PageProtocolLogicBase;
|
||||||
friend class OpenVpnLogic;
|
friend class OpenVpnLogic;
|
||||||
|
|
@ -120,6 +126,7 @@ signals:
|
||||||
void goToPage(PageEnumNS::Page page, bool reset = true, bool slide = true);
|
void goToPage(PageEnumNS::Page page, bool reset = true, bool slide = true);
|
||||||
void goToProtocolPage(Proto protocol, bool reset = true, bool slide = true);
|
void goToProtocolPage(Proto protocol, bool reset = true, bool slide = true);
|
||||||
void goToShareProtocolPage(Proto protocol, bool reset = true, bool slide = true);
|
void goToShareProtocolPage(Proto protocol, bool reset = true, bool slide = true);
|
||||||
|
void goToClientInfoPage(Proto protocol, bool reset = true, bool slide = true);
|
||||||
|
|
||||||
void closePage();
|
void closePage();
|
||||||
void setStartPage(PageEnumNS::Page page, bool slide = true);
|
void setStartPage(PageEnumNS::Page page, bool slide = true);
|
||||||
|
|
|
||||||
38
docs/openvpnRevokeClientCertificate.plantuml
Normal file
38
docs/openvpnRevokeClientCertificate.plantuml
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
@startuml openvpnRevokeClientCertificate
|
||||||
|
actor Admin as adm
|
||||||
|
participant "Amnezia Client" as cli
|
||||||
|
participant "Amnezia Container" as cont
|
||||||
|
participant "OpenVpn Service" as ovpn
|
||||||
|
|
||||||
|
adm -> cli: revoke the selected client certificate
|
||||||
|
cli -> cli: start progress bar
|
||||||
|
cli -> cont: execute script "revoke openvpn client"
|
||||||
|
|
||||||
|
cont -> cont: easyrsa revoke clientName
|
||||||
|
note right
|
||||||
|
clientName is the clientId field
|
||||||
|
of the ConnectionData structure
|
||||||
|
end note
|
||||||
|
|
||||||
|
cont -> cont: easyrsa gen-crl
|
||||||
|
cont -> cont: cp crl.pem
|
||||||
|
cont -> ovpn: restart openvpn service
|
||||||
|
note right
|
||||||
|
In the OpenVpn config
|
||||||
|
there should be a line "crl-verify crl.pem".
|
||||||
|
After that, the service will ignore
|
||||||
|
the certificates contained in the crl.pem file
|
||||||
|
end note
|
||||||
|
|
||||||
|
|
||||||
|
group#lightgreen #lightgreen if [successful case]
|
||||||
|
ovpn --> cont: restart result
|
||||||
|
cont --> cli: display that the selected certificate has been revoked
|
||||||
|
else #pink some kind of failure
|
||||||
|
cont --> cli: display an error depending on when it occurred
|
||||||
|
end
|
||||||
|
|
||||||
|
cli -> cli: stop progress bar
|
||||||
|
cli --> adm: return control to the user
|
||||||
|
|
||||||
|
@enduml
|
||||||
Loading…
Add table
Add a link
Reference in a new issue