added full access sharing

This commit is contained in:
vladimir.kuznetsov 2023-11-23 00:03:43 +07:00
parent c6a312845a
commit e8ceeb6e20
6 changed files with 376 additions and 139 deletions

View file

@ -222,5 +222,6 @@
<file>server_scripts/awg/configure_container.sh</file> <file>server_scripts/awg/configure_container.sh</file>
<file>server_scripts/awg/run_container.sh</file> <file>server_scripts/awg/run_container.sh</file>
<file>server_scripts/awg/Dockerfile</file> <file>server_scripts/awg/Dockerfile</file>
<file>ui/qml/Pages2/PageShareFullAccess.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View file

@ -51,7 +51,9 @@ namespace PageLoader
PageProtocolWireGuardSettings, PageProtocolWireGuardSettings,
PageProtocolAwgSettings, PageProtocolAwgSettings,
PageProtocolIKev2Settings, PageProtocolIKev2Settings,
PageProtocolRaw PageProtocolRaw,
PageShareFullAccess
}; };
Q_ENUM_NS(PageEnum) Q_ENUM_NS(PageEnum)

View file

@ -4,6 +4,19 @@
#include <QJsonObject> #include <QJsonObject>
#include "core/servercontroller.h" #include "core/servercontroller.h"
#include "logger.h"
namespace
{
Logger logger("ClientManagementModel");
namespace configKey {
constexpr char clientId[] = "clientId";
constexpr char clientName[] = "clientName";
constexpr char container[] = "container";
constexpr char userData[] = "userData";
}
}
ClientManagementModel::ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent) ClientManagementModel::ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent)
: m_settings(settings), QAbstractListModel(parent) : m_settings(settings), QAbstractListModel(parent)
@ -23,13 +36,13 @@ QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
} }
auto client = m_clientsTable.at(index.row()).toObject(); auto client = m_clientsTable.at(index.row()).toObject();
auto userData = client.value("userData").toObject(); auto userData = client.value(configKey::userData).toObject();
switch (role) { switch (role) {
case UserNameRole: return userData.value("clientName").toString(); case ClientNameRole: return userData.value(configKey::clientName).toString();
case ContainerNameRole: case ContainerNameRole:
return ContainerProps::containerHumanNames().value( return ContainerProps::containerHumanNames().value(
static_cast<DockerContainer>(userData.value("container").toInt())); static_cast<DockerContainer>(userData.value(configKey::container).toInt()));
} }
return QVariant(); return QVariant();
@ -40,17 +53,13 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
ServerController serverController(m_settings); ServerController serverController(m_settings);
ErrorCode error = ErrorCode::NoError; ErrorCode error = ErrorCode::NoError;
QString stdOut;
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
stdOut += data + "\n";
return ErrorCode::NoError;
};
const QString clientsTableFile = const QString clientsTableFile =
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container)); QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container));
const QByteArray clientsTableString = const QByteArray clientsTableString =
serverController.getTextFileFromContainer(container, credentials, clientsTableFile, &error); serverController.getTextFileFromContainer(container, credentials, clientsTableFile, &error);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the clientsTable file from the server";
return error; return error;
} }
@ -62,12 +71,44 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks
|| container == DockerContainer::Cloak) { || container == DockerContainer::Cloak) {
error = getOpenVpnClients(serverController, container, credentials, count);
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
error = getWireGuardClients(serverController, container, credentials, count);
}
if (error != ErrorCode::NoError) {
return error;
}
const QByteArray newClientsTableString = QJsonDocument(m_clientsTable).toJson();
if (clientsTableString != newClientsTableString) {
error = serverController.uploadTextFileToContainer(container, credentials, newClientsTableString,
clientsTableFile);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server";
}
}
}
endResetModel();
return error;
}
ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverController, DockerContainer container, ServerCredentials credentials, int &count)
{
ErrorCode error = ErrorCode::NoError;
QString stdOut;
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
stdOut += data + "\n";
return ErrorCode::NoError;
};
const QString getOpenVpnClientsList = const QString getOpenVpnClientsList =
"sudo docker exec -i $CONTAINER_NAME bash -c 'ls /opt/amnezia/openvpn/pki/issued'"; "sudo docker exec -i $CONTAINER_NAME bash -c 'ls /opt/amnezia/openvpn/pki/issued'";
QString script = serverController.replaceVars(getOpenVpnClientsList, QString script = serverController.replaceVars(getOpenVpnClientsList,
serverController.genVarsForScript(credentials, container)); serverController.genVarsForScript(credentials, container));
error = serverController.runScript(credentials, script, cbReadStdOut); error = serverController.runScript(credentials, script, cbReadStdOut);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to retrieve the list of issued certificates on the server";
return error; return error;
} }
@ -79,12 +120,12 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
openvpnCertId.replace(".crt", ""); openvpnCertId.replace(".crt", "");
if (!isClientExists(openvpnCertId)) { if (!isClientExists(openvpnCertId)) {
QJsonObject client; QJsonObject client;
client["userId"] = openvpnCertId; client[configKey::clientId] = openvpnCertId;
QJsonObject userData; QJsonObject userData;
userData["clientName"] = QString("Client %1").arg(count); userData[configKey::clientName] = QString("Client %1").arg(count);
userData["container"] = container; userData[configKey::container] = container;
client["userData"] = userData; client[configKey::userData] = userData;
m_clientsTable.push_back(client); m_clientsTable.push_back(client);
@ -92,12 +133,19 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
} }
} }
} }
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) { return error;
}
ErrorCode ClientManagementModel::getWireGuardClients(ServerController &serverController, DockerContainer container, ServerCredentials credentials, int &count)
{
ErrorCode error = ErrorCode::NoError;
const QString wireGuardConfigFile = const QString wireGuardConfigFile =
QString("opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg"); QString("opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg");
const QString wireguardConfigString = const QString wireguardConfigString =
serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, &error); serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, &error);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the wg conf file from the server";
return error; return error;
} }
@ -113,28 +161,18 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
for (auto &wireguardKey : wireguardKeys) { for (auto &wireguardKey : wireguardKeys) {
if (!isClientExists(wireguardKey)) { if (!isClientExists(wireguardKey)) {
QJsonObject client; QJsonObject client;
client["userId"] = wireguardKey; client[configKey::clientId] = wireguardKey;
QJsonObject userData; QJsonObject userData;
userData["clientName"] = QString("Client %1").arg(count); userData[configKey::clientName] = QString("Client %1").arg(count);
userData["container"] = container; userData[configKey::container] = container;
client["userData"] = userData; client[configKey::userData] = userData;
m_clientsTable.push_back(client); m_clientsTable.push_back(client);
count++; count++;
} }
} }
}
const QByteArray newClientsTableString = QJsonDocument(m_clientsTable).toJson();
if (clientsTableString != newClientsTableString) {
error = serverController.uploadTextFileToContainer(container, credentials, newClientsTableString,
clientsTableFile);
}
}
endResetModel();
return error; return error;
} }
@ -143,7 +181,7 @@ bool ClientManagementModel::isClientExists(const QString &clientId)
for (const QJsonValue &value : qAsConst(m_clientsTable)) { for (const QJsonValue &value : qAsConst(m_clientsTable)) {
if (value.isObject()) { if (value.isObject()) {
QJsonObject obj = value.toObject(); QJsonObject obj = value.toObject();
if (obj.contains("userId") && obj["userId"].toString() == clientId) { if (obj.contains(configKey::clientId) && obj[configKey::clientId].toString() == clientId) {
return true; return true;
} }
} }
@ -155,29 +193,26 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
const DockerContainer container, ServerCredentials credentials) const DockerContainer container, ServerCredentials credentials)
{ {
ErrorCode error; ErrorCode error;
if (m_clientsTable.empty()) {
error = updateModel(container, credentials); error = updateModel(container, credentials);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
return error; return error;
} }
for (int i = 0; i < m_clientsTable.size(); i++) { for (int i = 0; i < m_clientsTable.size(); i++) {
if (m_clientsTable.at(i).toObject().value("userId") == (clientId)) { if (m_clientsTable.at(i).toObject().value(configKey::clientId) == clientId) {
error = renameClient(i, clientName, container, credentials); return renameClient(i, clientName, container, credentials);
if (error != ErrorCode::NoError) {
return error;
} }
} }
}
} else {
beginResetModel(); beginResetModel();
QJsonObject client; QJsonObject client;
client["userId"] = clientId; client[configKey::clientId] = clientId;
QJsonObject userData; QJsonObject userData;
userData["clientName"] = clientName; userData[configKey::clientName] = clientName;
userData["container"] = container; userData[configKey::container] = container;
client["userData"] = userData; client[configKey::userData] = userData;
m_clientsTable.push_back(client); m_clientsTable.push_back(client);
endResetModel(); endResetModel();
@ -188,6 +223,8 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container)); QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container));
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server";
} }
return error; return error;
@ -197,9 +234,9 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie
ServerCredentials credentials) ServerCredentials credentials)
{ {
auto client = m_clientsTable.at(row).toObject(); auto client = m_clientsTable.at(row).toObject();
auto userData = client["userData"].toObject(); auto userData = client[configKey::userData].toObject();
userData["clientName"] = clientName; userData[configKey::clientName] = clientName;
client["userData"] = userData; client[configKey::userData] = userData;
m_clientsTable.replace(row, client); m_clientsTable.replace(row, client);
emit dataChanged(index(row, 0), index(row, 0)); emit dataChanged(index(row, 0), index(row, 0));
@ -212,6 +249,9 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie
ErrorCode error = ErrorCode error =
serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server";
}
return error; return error;
} }
@ -232,7 +272,7 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai
ServerCredentials credentials) ServerCredentials credentials)
{ {
auto client = m_clientsTable.at(row).toObject(); auto client = m_clientsTable.at(row).toObject();
QString clientId = client.value("userId").toString(); QString clientId = client.value(configKey::clientId).toString();
const QString getOpenVpnCertData = QString("sudo docker exec -i $CONTAINER_NAME bash -c '" const QString getOpenVpnCertData = QString("sudo docker exec -i $CONTAINER_NAME bash -c '"
"cd /opt/amnezia/openvpn ;\\" "cd /opt/amnezia/openvpn ;\\"
@ -246,6 +286,7 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai
serverController.replaceVars(getOpenVpnCertData, serverController.genVarsForScript(credentials, container)); serverController.replaceVars(getOpenVpnCertData, serverController.genVarsForScript(credentials, container));
ErrorCode error = serverController.runScript(credentials, script); ErrorCode error = serverController.runScript(credentials, script);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to revoke the certificate";
return error; return error;
} }
@ -259,6 +300,7 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container)); QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container));
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server";
return error; return error;
} }
@ -276,11 +318,12 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
const QString wireguardConfigString = const QString wireguardConfigString =
serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, &error); serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, &error);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the wg conf file from the server";
return error; return error;
} }
auto client = m_clientsTable.at(row).toObject(); auto client = m_clientsTable.at(row).toObject();
QString clientId = client.value("userId").toString(); QString clientId = client.value(configKey::clientId).toString();
auto configSections = wireguardConfigString.split("[", Qt::SkipEmptyParts); auto configSections = wireguardConfigString.split("[", Qt::SkipEmptyParts);
for (auto &section : configSections) { for (auto &section : configSections) {
@ -293,6 +336,7 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
newWireGuardConfig.insert(0, "["); newWireGuardConfig.insert(0, "[");
error = serverController.uploadTextFileToContainer(container, credentials, newWireGuardConfig, wireGuardConfigFile); error = serverController.uploadTextFileToContainer(container, credentials, newWireGuardConfig, wireGuardConfigFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the wg conf file to the server";
return error; return error;
} }
@ -306,6 +350,7 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container)); QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container));
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server";
return error; return error;
} }
@ -315,6 +360,7 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
serverController.replaceVars(script.arg(wireGuardConfigFile), serverController.replaceVars(script.arg(wireGuardConfigFile),
serverController.genVarsForScript(credentials, container))); serverController.genVarsForScript(credentials, container)));
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to execute the command 'wg syncconf' on the server";
return error; return error;
} }
@ -324,7 +370,7 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
QHash<int, QByteArray> ClientManagementModel::roleNames() const QHash<int, QByteArray> ClientManagementModel::roleNames() const
{ {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[UserNameRole] = "userName"; roles[ClientNameRole] = "clientName";
roles[ContainerNameRole] = "containerName"; roles[ContainerNameRole] = "containerName";
return roles; return roles;
} }

View file

@ -4,7 +4,7 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QJsonArray> #include <QJsonArray>
#include "protocols/protocols_defs.h" #include "core/servercontroller.h"
#include "settings.h" #include "settings.h"
class ClientManagementModel : public QAbstractListModel class ClientManagementModel : public QAbstractListModel
@ -29,7 +29,7 @@ class ClientManagementModel : public QAbstractListModel
public: public:
enum Roles { enum Roles {
UserNameRole = Qt::UserRole + 1, ClientNameRole = Qt::UserRole + 1,
ContainerNameRole, ContainerNameRole,
}; };
@ -55,6 +55,9 @@ private:
ErrorCode revokeOpenVpn(const int row, const DockerContainer container, ServerCredentials credentials); ErrorCode revokeOpenVpn(const int row, const DockerContainer container, ServerCredentials credentials);
ErrorCode revokeWireGuard(const int row, const DockerContainer container, ServerCredentials credentials); ErrorCode revokeWireGuard(const int row, const DockerContainer container, ServerCredentials credentials);
ErrorCode getOpenVpnClients(ServerController &serverController, DockerContainer container, ServerCredentials credentials, int &count);
ErrorCode getWireGuardClients(ServerController &serverController, DockerContainer container, ServerCredentials credentials, int &count);
QJsonArray m_clientsTable; QJsonArray m_clientsTable;
std::shared_ptr<Settings> m_settings; std::shared_ptr<Settings> m_settings;

View file

@ -18,7 +18,6 @@ PageType {
enum ConfigType { enum ConfigType {
AmneziaConnection, AmneziaConnection,
AmneziaFullAccess,
OpenVpn, OpenVpn,
WireGuard WireGuard
} }
@ -46,24 +45,16 @@ PageType {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
switch (type) { switch (type) {
case PageShare.ConfigType.AmneziaConnection: ExportController.generateConnectionConfig(userNameTextField.textFieldText); break; case PageShare.ConfigType.AmneziaConnection: ExportController.generateConnectionConfig(clientNameTextField.textFieldText); break;
case PageShare.ConfigType.AmneziaFullAccess: {
if (Qt.platform.os === "android") {
ExportController.generateFullAccessConfigAndroid();
} else {
ExportController.generateFullAccessConfig();
}
break;
}
case PageShare.ConfigType.OpenVpn: { case PageShare.ConfigType.OpenVpn: {
ExportController.generateOpenVpnConfig(userNameTextField.textFieldText) ExportController.generateOpenVpnConfig(clientNameTextField.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(userNameTextField.textFieldText) ExportController.generateWireGuardConfig(clientNameTextField.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"
@ -129,6 +120,51 @@ PageType {
Layout.topMargin: 24 Layout.topMargin: 24
headerText: qsTr("Share VPN Access") headerText: qsTr("Share VPN Access")
actionButtonImage: "qrc:/images/controls/more-vertical.svg"
actionButtonFunction: function() {
shareFullAccessDrawer.open()
}
DrawerType {
id: shareFullAccessDrawer
width: root.width
height: root.height * 0.45
ColumnLayout {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 16
spacing: 0
Header2Type {
Layout.fillWidth: true
Layout.bottomMargin: 16
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: qsTr("Share full access to the server and VPN")
descriptionText: qsTr("Use for your own devices, or share with those you trust to manage the server.")
}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Share")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
PageController.goToPage(PageEnum.PageShareFullAccess)
shareFullAccessDrawer.close()
}
}
}
}
} }
Rectangle { Rectangle {
@ -189,7 +225,7 @@ PageType {
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
id: userNameTextField id: clientNameTextField
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 16 Layout.topMargin: 16
@ -242,11 +278,6 @@ PageType {
serverSelector.severSelectorIndexChanged() serverSelector.severSelectorIndexChanged()
} }
//full access label
// if (accessTypeSelector.currentIndex !== 0) {
// shareConnectionDrawer.headerText = qsTr("Accessing ") + serverSelector.text
// shareConnectionDrawer.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text
// }
serverSelector.menuVisible = false serverSelector.menuVisible = false
} }
@ -419,7 +450,7 @@ PageType {
} }
ListView { ListView {
id: usersListView id: clientsListView
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height Layout.preferredHeight: childrenRect.height
@ -431,7 +462,7 @@ PageType {
interactive: false interactive: false
delegate: Item { delegate: Item {
implicitWidth: usersListView.width implicitWidth: clientsListView.width
implicitHeight: delegateContent.implicitHeight implicitHeight: delegateContent.implicitHeight
ColumnLayout { ColumnLayout {
@ -447,19 +478,19 @@ PageType {
LabelWithButtonType { LabelWithButtonType {
Layout.fillWidth: true Layout.fillWidth: true
text: userName text: clientName
descriptionText: containerName descriptionText: containerName
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() { clickedFunction: function() {
userInfoDrower.open() clientInfoDrawer.open()
} }
} }
DividerType {} DividerType {}
DrawerType { DrawerType {
id: userInfoDrower id: clientInfoDrawer
width: root.width width: root.width
height: root.height * 0.45 height: root.height * 0.45
@ -478,7 +509,7 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.bottomMargin: 24 Layout.bottomMargin: 24
headerText: userName headerText: clientName
descriptionText: serverSelector.text + ", " + containerName descriptionText: serverSelector.text + ", " + containerName
} }
@ -507,7 +538,7 @@ PageType {
onVisibleChanged: { onVisibleChanged: {
if (clientNameEditDrawer.visible) { if (clientNameEditDrawer.visible) {
clientName.textField.forceActiveFocus() clientNameEditor.textField.forceActiveFocus()
} }
} }
@ -520,11 +551,10 @@ PageType {
anchors.rightMargin: 16 anchors.rightMargin: 16
TextFieldWithHeaderType { TextFieldWithHeaderType {
id: clientName id: clientNameEditor
Layout.fillWidth: true Layout.fillWidth: true
headerText: qsTr("Client name") headerText: qsTr("Client name")
textFieldText: userName textFieldText: clientName
} }
BasicButtonType { BasicButtonType {
@ -533,10 +563,10 @@ PageType {
text: qsTr("Save") text: qsTr("Save")
onClicked: { onClicked: {
if (clientName.textFieldText !== userName) { if (clientNameEditor.textFieldText !== clientName) {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
ExportController.renameClient(index, ExportController.renameClient(index,
clientName.textFieldText, clientNameEditor.textFieldText,
ContainersModel.getCurrentlyProcessedContainerIndex(), ContainersModel.getCurrentlyProcessedContainerIndex(),
ServersModel.getCurrentlyProcessedServerCredentials()) ServersModel.getCurrentlyProcessedServerCredentials())
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
@ -561,14 +591,14 @@ PageType {
text: qsTr("Revoke") text: qsTr("Revoke")
onClicked: function() { onClicked: function() {
questionDrawer.headerText = qsTr("Revoke the config for a user - ") + userName + "?" questionDrawer.headerText = qsTr("Revoke the config for a user - ") + clientName + "?"
questionDrawer.descriptionText = qsTr("The user will no longer be able to connect to your server.") questionDrawer.descriptionText = qsTr("The user will no longer be able to connect to your server.")
questionDrawer.yesButtonText = qsTr("Continue") questionDrawer.yesButtonText = qsTr("Continue")
questionDrawer.noButtonText = qsTr("Cancel") questionDrawer.noButtonText = qsTr("Cancel")
questionDrawer.yesButtonFunction = function() { questionDrawer.yesButtonFunction = function() {
questionDrawer.close() questionDrawer.close()
userInfoDrower.close() clientInfoDrawer.close()
root.revokeConfig(index) root.revokeConfig(index)
} }
questionDrawer.noButtonFunction = function() { questionDrawer.noButtonFunction = function() {

View file

@ -0,0 +1,155 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import SortFilterProxyModel 0.2
import PageEnum 1.0
import ContainerProps 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Components"
PageType {
id: root
BackButtonType {
id: backButton
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
}
FlickableType {
anchors.top: backButton.bottom
anchors.bottom: parent.bottom
contentHeight: content.height
ColumnLayout {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 16
anchors.leftMargin: 16
spacing: 0
HeaderType {
Layout.fillWidth: true
Layout.topMargin: 24
headerText: qsTr("Full access to the server and VPN")
}
ParagraphTextType {
Layout.fillWidth: true
Layout.topMargin: 24
Layout.bottomMargin: 24
text: qsTr("We recommend that you use full access to the server only for your own additional devices.\n") +
qsTr("If you share full access with other people, they can remove and add protocols and services to the server, which will cause the VPN to work incorrectly for all users. ")
color: "#878B91"
}
DropDownType {
id: serverSelector
signal severSelectorIndexChanged
property int currentIndex: 0
Layout.fillWidth: true
Layout.topMargin: 16
drawerHeight: 0.4375
descriptionText: qsTr("Server")
headerText: qsTr("Server")
listView: ListViewWithRadioButtonType {
id: serverSelectorListView
rootWidth: root.width
imageSource: "qrc:/images/controls/check.svg"
model: SortFilterProxyModel {
id: proxyServersModel
sourceModel: ServersModel
filters: [
ValueFilter {
roleName: "hasWriteAccess"
value: true
}
]
}
currentIndex: 0
clickedFunction: function() {
handler()
if (serverSelector.currentIndex !== serverSelectorListView.currentIndex) {
serverSelector.currentIndex = serverSelectorListView.currentIndex
}
shareConnectionDrawer.headerText = qsTr("Accessing ") + serverSelector.text
shareConnectionDrawer.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text
serverSelector.menuVisible = false
}
Component.onCompleted: {
handler()
}
function handler() {
serverSelector.text = selectedText
ServersModel.currentlyProcessedIndex = proxyServersModel.mapToSource(currentIndex)
}
}
}
BasicButtonType {
Layout.fillWidth: true
Layout.topMargin: 40
text: qsTr("Share")
imageSource: "qrc:/images/controls/share-2.svg"
onClicked: function() {
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
shareConnectionDrawer.needCloseButton = false
shareConnectionDrawer.open()
shareConnectionDrawer.contentVisible = false
PageController.showBusyIndicator(true)
if (Qt.platform.os === "android") {
ExportController.generateFullAccessConfigAndroid();
} else {
ExportController.generateFullAccessConfig();
}
PageController.showBusyIndicator(false)
shareConnectionDrawer.needCloseButton = true
PageController.showTopCloseButton(true)
shareConnectionDrawer.contentVisible = true
}
}
ShareConnectionDrawer {
id: shareConnectionDrawer
}
}
}
}