File indexing completed on 2024-07-21 07:58:07

0001 /*
0002     SPDX-FileCopyrightText: 2019 Bruce Anderson <banderson19com@san.rr.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "wireguardtabwidget.h"
0007 #include "ui_wireguardpeerwidget.h"
0008 #include "ui_wireguardtabwidget.h"
0009 #include "wireguardpeerwidget.h"
0010 
0011 #include <QStandardItemModel>
0012 
0013 #include <KColorScheme>
0014 #include <KConfig>
0015 #include <KConfigGroup>
0016 #include <NetworkManagerQt/Ipv4Setting>
0017 #include <NetworkManagerQt/Ipv6Setting>
0018 #include <NetworkManagerQt/Utils>
0019 
0020 // Keys for the NetworkManager configuration
0021 #define PNM_SETTING_WIREGUARD_SETTING_NAME "wireguard"
0022 
0023 #define PNM_WG_KEY_PEERS "peers"
0024 #define PNM_WG_KEY_MTU "mtu"
0025 #define PNM_WG_KEY_PEER_ROUTES "peer-routes"
0026 #define PNM_WG_PEER_KEY_ALLOWED_IPS "allowed-ips"
0027 #define PNM_WG_PEER_KEY_ENDPOINT "endpoint"
0028 #define PNM_WG_PEER_KEY_PERSISTENT_KEEPALIVE "persistent-keepalive"
0029 #define PNM_WG_PEER_KEY_PRESHARED_KEY "preshared-key"
0030 #define PNM_WG_PEER_KEY_PRESHARED_KEY_FLAGS "preshared-key-flags"
0031 #define PNM_WG_PEER_KEY_PUBLIC_KEY "public-key"
0032 
0033 class WireGuardTabWidget::Private
0034 {
0035 public:
0036     Private();
0037     ~Private();
0038 
0039     Ui_WireGuardTabWidget ui;
0040     NetworkManager::WireGuardSetting::Ptr setting;
0041     KSharedConfigPtr config;
0042     NMVariantMapList peers;
0043     int currentIndex;
0044     bool currentPeerValid;
0045     bool otherPeersValid;
0046 };
0047 
0048 WireGuardTabWidget::Private::Private() = default;
0049 
0050 WireGuardTabWidget::Private::~Private() = default;
0051 
0052 WireGuardTabWidget::WireGuardTabWidget(const NMVariantMapList &peerData, QWidget *parent, Qt::WindowFlags f)
0053     : QDialog(parent, f)
0054     , d(new Private)
0055 {
0056     d->ui.setupUi(this);
0057 
0058     d->config = KSharedConfig::openConfig();
0059     setWindowTitle(i18nc("@title: window wireguard peers properties", "WireGuard peers properties"));
0060     connect(d->ui.btnAdd, &QPushButton::clicked, this, &WireGuardTabWidget::slotAddPeer);
0061     connect(d->ui.btnRemove, &QPushButton::clicked, this, &WireGuardTabWidget::slotRemovePeer);
0062     connect(d->ui.buttonBox, &QDialogButtonBox::accepted, this, &WireGuardTabWidget::accept);
0063     connect(d->ui.buttonBox, &QDialogButtonBox::rejected, this, &WireGuardTabWidget::reject);
0064 
0065     KAcceleratorManager::manage(this);
0066 
0067     loadConfig(peerData);
0068 
0069     if (peerData.isEmpty())
0070         slotAddPeer();
0071 }
0072 
0073 WireGuardTabWidget::~WireGuardTabWidget()
0074 {
0075     delete d;
0076 }
0077 
0078 void WireGuardTabWidget::loadConfig(const NMVariantMapList &peerData)
0079 {
0080     d->peers = peerData;
0081     int numIncomingPeers = d->peers.size();
0082 
0083     // If there weren't any peers in the incoming setting, create
0084     // the required first element
0085     if (d->peers.isEmpty())
0086         d->peers.append(*(new QVariantMap()));
0087 
0088     for (int i = 0; i < numIncomingPeers; i++) {
0089         slotAddPeerWithData(peerData[i]);
0090     }
0091     d->ui.tabWidget->setCurrentIndex(0);
0092 }
0093 
0094 NMVariantMapList WireGuardTabWidget::setting() const
0095 {
0096     d->peers.clear();
0097     for (int i = 0; i < d->ui.tabWidget->count(); i++)
0098         d->peers.append(static_cast<WireGuardPeerWidget *>(d->ui.tabWidget->widget(i))->setting());
0099     return d->peers;
0100 }
0101 
0102 void WireGuardTabWidget::slotAddPeer()
0103 {
0104     auto newItem = new QVariantMap;
0105     int numPeers = d->ui.tabWidget->count() + 1;
0106     auto newTab = new WireGuardPeerWidget(*newItem);
0107     connect(newTab, &WireGuardPeerWidget::notifyValid, this, &WireGuardTabWidget::slotWidgetChanged);
0108     d->ui.tabWidget->addTab(newTab, QString("Peer %1").arg(QString::number(numPeers)));
0109     d->peers.append(*newItem);
0110     d->ui.tabWidget->setCurrentIndex(numPeers - 1);
0111     slotWidgetChanged();
0112 }
0113 
0114 void WireGuardTabWidget::slotAddPeerWithData(const QVariantMap &peerData)
0115 {
0116     int numPeers = d->ui.tabWidget->count() + 1;
0117     auto newTab = new WireGuardPeerWidget(peerData);
0118     d->ui.tabWidget->addTab(newTab, QString("Peer %1").arg(QString::number(numPeers)));
0119     connect(newTab, &WireGuardPeerWidget::notifyValid, this, &WireGuardTabWidget::slotWidgetChanged);
0120     d->peers.append(peerData);
0121     d->ui.tabWidget->setCurrentIndex(numPeers - 1);
0122     slotWidgetChanged();
0123 }
0124 
0125 void WireGuardTabWidget::slotRemovePeer()
0126 {
0127     int numPeers = d->ui.tabWidget->count() - 1;
0128     d->ui.tabWidget->removeTab(d->ui.tabWidget->currentIndex());
0129     if (numPeers == 0) {
0130         slotAddPeer();
0131         numPeers = 1;
0132     }
0133 
0134     // Retitle the tabs to reflect the current numbers
0135     for (int i = 0; i < numPeers; i++)
0136         d->ui.tabWidget->setTabText(i, QString("Peer %1").arg(QString::number(i + 1)));
0137 }
0138 
0139 void WireGuardTabWidget::slotWidgetChanged()
0140 {
0141     bool valid = true;
0142     for (int i = 0; i < d->ui.tabWidget->count(); i++) {
0143         if (!static_cast<WireGuardPeerWidget *>(d->ui.tabWidget->widget(i))->isValid()) {
0144             valid = false;
0145             break;
0146         }
0147     }
0148     d->ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid);
0149 }
0150 
0151 #include "moc_wireguardtabwidget.cpp"