diff --git a/client/ui/controllers/exportController.cpp b/client/ui/controllers/exportController.cpp index 04264624..5cd9a83d 100644 --- a/client/ui/controllers/exportController.cpp +++ b/client/ui/controllers/exportController.cpp @@ -9,6 +9,8 @@ #include #include +#include "configurators/openvpn_configurator.h" +#include "configurators/wireguard_configurator.h" #include "qrcodegen.hpp" #include "core/errorstrings.h" @@ -27,14 +29,17 @@ ExportController::ExportController(const QSharedPointer &serversMo void ExportController::generateFullAccessConfig() { + clearPreviousConfig(); + int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex(); QJsonObject config = m_settings->server(serverIndex); QByteArray compressedConfig = QJsonDocument(config).toJson(); compressedConfig = qCompress(compressedConfig, 8); - m_amneziaCode = QString("vpn://%1") - .arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding - | QByteArray::OmitTrailingEquals))); + m_rawConfig = QString("vpn://%1") + .arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding + | QByteArray::OmitTrailingEquals))); + m_formattedConfig = m_rawConfig; m_qrCodes = generateQrCodeImageSeries(compressedConfig); emit exportConfigChanged(); @@ -42,6 +47,8 @@ void ExportController::generateFullAccessConfig() void ExportController::generateConnectionConfig() { + clearPreviousConfig(); + int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex(); ServerCredentials credentials = qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); @@ -81,17 +88,86 @@ void ExportController::generateConnectionConfig() QByteArray compressedConfig = QJsonDocument(config).toJson(); compressedConfig = qCompress(compressedConfig, 8); - m_amneziaCode = QString("vpn://%1") - .arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding - | QByteArray::OmitTrailingEquals))); + m_rawConfig = QString("vpn://%1") + .arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding + | QByteArray::OmitTrailingEquals))); + m_formattedConfig = m_rawConfig; m_qrCodes = generateQrCodeImageSeries(compressedConfig); emit exportConfigChanged(); } -QString ExportController::getAmneziaCode() +void ExportController::generateOpenVpnConfig() { - return m_amneziaCode; + clearPreviousConfig(); + + int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex(); + ServerCredentials credentials = + qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); + + DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); + QModelIndex containerModelIndex = m_containersModel->index(container); + QJsonObject containerConfig = + qvariant_cast(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole)); + containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); + + ErrorCode errorCode = ErrorCode::NoError; + QString config = + m_configurator->openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, &errorCode); + if (errorCode) { + emit exportErrorOccurred(errorString(errorCode)); + return; + } + config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::OpenVpn, config); + + m_rawConfig = config; + + auto configJson = QJsonDocument::fromJson(config.toUtf8()).object(); + QStringList lines = configJson.value(config_key::config).toString().replace("\r", "").split("\n"); + for (const QString &line : lines) { + m_formattedConfig.append(line + "\n"); + } + + emit exportConfigChanged(); +} + +void ExportController::generateWireGuardConfig() +{ + clearPreviousConfig(); + + int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex(); + ServerCredentials credentials = + qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); + + DockerContainer container = static_cast(m_containersModel->getCurrentlyProcessedContainerIndex()); + QModelIndex containerModelIndex = m_containersModel->index(container); + QJsonObject containerConfig = + qvariant_cast(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole)); + containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); + + ErrorCode errorCode = ErrorCode::NoError; + QString config = m_configurator->wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, + &errorCode); + if (errorCode) { + emit exportErrorOccurred(errorString(errorCode)); + return; + } + config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::WireGuard, config); + + m_rawConfig = config; + + auto configJson = QJsonDocument::fromJson(config.toUtf8()).object(); + QStringList lines = configJson.value(config_key::config).toString().replace("\r", "").split("\n"); + for (const QString &line : lines) { + m_formattedConfig.append(line + "\n"); + } + + emit exportConfigChanged(); +} + +QString ExportController::getFormattedConfig() +{ + return m_formattedConfig; } QList ExportController::getQrCodes() @@ -117,7 +193,7 @@ void ExportController::saveFile() QFile save(fileName.toLocalFile()); save.open(QIODevice::WriteOnly); - save.write(m_amneziaCode.toUtf8()); + save.write(m_rawConfig.toUtf8()); save.close(); QFileInfo fi(fileName.toLocalFile()); @@ -154,3 +230,10 @@ int ExportController::getQrCodesCount() { return m_qrCodes.size(); } + +void ExportController::clearPreviousConfig() +{ + m_rawConfig.clear(); + m_formattedConfig.clear(); + m_qrCodes.clear(); +} diff --git a/client/ui/controllers/exportController.h b/client/ui/controllers/exportController.h index 63997efd..85144978 100644 --- a/client/ui/controllers/exportController.h +++ b/client/ui/controllers/exportController.h @@ -14,24 +14,25 @@ public: explicit ExportController(const QSharedPointer &serversModel, const QSharedPointer &containersModel, const std::shared_ptr &settings, - const std::shared_ptr &configurator, - QObject *parent = nullptr); + const std::shared_ptr &configurator, QObject *parent = nullptr); Q_PROPERTY(QList qrCodes READ getQrCodes NOTIFY exportConfigChanged) Q_PROPERTY(int qrCodesCount READ getQrCodesCount NOTIFY exportConfigChanged) - Q_PROPERTY(QString amneziaCode READ getAmneziaCode NOTIFY exportConfigChanged) + Q_PROPERTY(QString formattedConfig READ getFormattedConfig NOTIFY exportConfigChanged) public slots: void generateFullAccessConfig(); void generateConnectionConfig(); + void generateOpenVpnConfig(); + void generateWireGuardConfig(); - QString getAmneziaCode(); + QString getFormattedConfig(); QList getQrCodes(); void saveFile(); signals: - void generateConfig(bool isFullAccess); + void generateConfig(int type); void exportErrorOccurred(QString errorMessage); void exportConfigChanged(); @@ -42,12 +43,15 @@ private: int getQrCodesCount(); + void clearPreviousConfig(); + QSharedPointer m_serversModel; QSharedPointer m_containersModel; std::shared_ptr m_settings; std::shared_ptr m_configurator; - QString m_amneziaCode; + QString m_rawConfig; + QString m_formattedConfig; QList m_qrCodes; }; diff --git a/client/ui/qml/Components/ConnectButton.qml b/client/ui/qml/Components/ConnectButton.qml index f8e29c47..85cc345a 100644 --- a/client/ui/qml/Components/ConnectButton.qml +++ b/client/ui/qml/Components/ConnectButton.qml @@ -55,7 +55,7 @@ Button { fillColor: "transparent" strokeColor: { if (ConnectionController.isConnectionInProgress) { - return Qt.rgba(251/255, 178/255, 106/255, 1) + return "#261E1A" } else if (ConnectionController.isConnected) { return connectedButtonColor } else { diff --git a/client/ui/qml/Components/ShareConnectionDrawer.qml b/client/ui/qml/Components/ShareConnectionDrawer.qml index b677c5b1..d5ed1029 100644 --- a/client/ui/qml/Components/ShareConnectionDrawer.qml +++ b/client/ui/qml/Components/ShareConnectionDrawer.qml @@ -137,7 +137,7 @@ DrawerType { Layout.topMargin: 16 } - TextField { + TextArea { Layout.fillWidth: true Layout.topMargin: 16 Layout.bottomMargin: 16 @@ -147,16 +147,17 @@ DrawerType { height: 24 color: "#D7D8DB" + selectionColor: "#412102" + selectedTextColor: "#D7D8DB" font.pixelSize: 16 font.weight: Font.Medium font.family: "PT Root UI VF" - text: ExportController.amneziaCode + text: ExportController.formattedConfig wrapMode: Text.Wrap - readOnly: true background: Rectangle { color: "transparent" } @@ -186,11 +187,13 @@ DrawerType { running: ExportController.qrCodesCount > 0 repeat: true onTriggered: { - index++ - if (index >= ExportController.qrCodesCount) { - index = 0 + if (ExportController.qrCodesCount > 0) { + index++ + if (index >= ExportController.qrCodesCount) { + index = 0 + } + parent.source = ExportController.qrCodes[index] } - parent.source = ExportController.qrCodes[index] } } @@ -205,6 +208,8 @@ DrawerType { Layout.topMargin: 24 Layout.bottomMargin: 32 + visible: ExportController.qrCodesCount > 0 + horizontalAlignment: Text.AlignHCenter text: qsTr("To read the QR code in the Amnezia app, select \"Add Server\" → \"I have connection details\"") } diff --git a/client/ui/qml/Pages2/PageShare.qml b/client/ui/qml/Pages2/PageShare.qml index decd461a..c83b59d5 100644 --- a/client/ui/qml/Pages2/PageShare.qml +++ b/client/ui/qml/Pages2/PageShare.qml @@ -16,18 +16,30 @@ import "../Components" PageType { id: root + enum ConfigType { + AmneziaConnection, + AmenziaFullAccess, + OpenVpn, + WireGuard + } + Connections { target: ExportController - function onGenerateConfig(isFullAccess) { + function onGenerateConfig(type) { shareConnectionDrawer.open() shareConnectionDrawer.contentVisible = false PageController.showBusyIndicator(true) - if (isFullAccess) { - ExportController.generateFullAccessConfig() - } else { - ExportController.generateConnectionConfig() + + console.log(type) + + switch (type) { + case PageShare.ConfigType.AmneziaConnection: ExportController.generateConnectionConfig(); break; + case PageShare.ConfigType.AmenziaFullAccess: ExportController.generateFullAccessConfig(); break; + case PageShare.ConfigType.OpenVpn: ExportController.generateOpenVpnConfig(); break; + case PageShare.ConfigType.WireGuard: ExportController.generateWireGuardConfig(); break; } + PageController.showBusyIndicator(false) shareConnectionDrawer.contentVisible = true } @@ -46,23 +58,17 @@ PageType { QtObject { id: amneziaConnectionFormat property string name: qsTr("For the AmnesiaVPN app") - property var func: function() { - ExportController.generateConfig(false) - } + property var type: PageShare.ConfigType.AmneziaConnection } QtObject { id: openVpnConnectionFormat property string name: qsTr("OpenVpn native format") - property var func: function() { - console.log("Item 3 clicked") - } + property var type: PageShare.ConfigType.OpenVpn } QtObject { id: wireGuardConnectionFormat property string name: qsTr("WireGuard native format") - property var func: function() { - console.log("Item 3 clicked") - } + property var type: PageShare.ConfigType.WireGuard } FlickableType { @@ -334,9 +340,9 @@ PageType { onClicked: { if (accessTypeSelector.currentIndex === 0) { - root.connectionTypesModel[accessTypeSelector.currentIndex].func() + ExportController.generateConfig(root.connectionTypesModel[exportTypeSelector.currentIndex].type) } else { - ExportController.generateConfig(true) + ExportController.generateConfig(PageShare.ConfigType.AmneziaFullAccess) } } }