From 191216c728a44c2c795d466b2dc00f2fc7583753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Gren=C3=A4ngen?= Date: Thu, 18 Jul 2024 19:51:46 +0200 Subject: [PATCH] Feature - Add custom actions -> Refresh local DNS * This will use pkexec and rely on the fact that we're running systemd --- CMakeLists.txt | 2 ++ SysCommand.cpp | 35 +++++++++++++++++++++++++++++++++++ SysCommand.h | 22 ++++++++++++++++++++++ TailRunner.cpp | 2 +- TailRunner.h | 2 +- TrayMenuManager.cpp | 12 ++++++++++++ TrayMenuManager.h | 10 ++++++++-- 7 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 SysCommand.cpp create mode 100644 SysCommand.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c95a4be..60e9287 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,8 @@ set(PROJECT_SOURCES TailSettings.h AccountsTabUiManager.cpp AccountsTabUiManager.h + SysCommand.cpp + SysCommand.h ) qt_add_executable(tail-tray diff --git a/SysCommand.cpp b/SysCommand.cpp new file mode 100644 index 0000000..84ce369 --- /dev/null +++ b/SysCommand.cpp @@ -0,0 +1,35 @@ +// +// Created by marcus on 2024-07-18. +// + +#include "SysCommand.h" + +#include + +void SysCommand::refreshDns() +{ + QStringList args; + args << "restart"; + args << "systemd-resolved"; + + runCommand("systemctl", args, false, true); +} + +void SysCommand::runCommand(const QString& cmd, QStringList args, bool jsonResult, bool usePkExec) +{ + pProcess = std::make_unique(this); + connect(pProcess.get(), &QProcess::finished, this, [this](int exitCode, QProcess::ExitStatus status) { + qDebug() << "Process exit code " << exitCode << " - " << status; + }); + + if (jsonResult) + args << "--json"; + + if (usePkExec) { + args.insert(0, cmd); + pProcess->start("/usr/bin/pkexec", args); + } + else { + pProcess->start(cmd, args); + } +} diff --git a/SysCommand.h b/SysCommand.h new file mode 100644 index 0000000..52efc6f --- /dev/null +++ b/SysCommand.h @@ -0,0 +1,22 @@ +// +// Created by marcus on 2024-07-18. +// +#ifndef SYSCOMMAND_H +#define SYSCOMMAND_H + +#include +#include + +class SysCommand : public QObject +{ + Q_OBJECT +public: + void refreshDns(); + +private: + std::unique_ptr pProcess; + + void runCommand(const QString& cmd, QStringList args, bool jsonResult = false, bool usePkExec = false); +}; + +#endif //SYSCOMMAND_H diff --git a/TailRunner.cpp b/TailRunner.cpp index d0da840..8f8b4f3 100644 --- a/TailRunner.cpp +++ b/TailRunner.cpp @@ -99,7 +99,7 @@ void TailRunner::stop() { runCommand("down", QStringList()); } -void TailRunner::runCommand(QString cmd, QStringList args, bool jsonResult, bool usePkExec) { +void TailRunner::runCommand(const QString& cmd, QStringList args, bool jsonResult, bool usePkExec) { if (pProcess != nullptr) { if (pProcess->state() == QProcess::Running) { qDebug() << "Process already running!" << "Will queue up " << cmd << args << "command"; diff --git a/TailRunner.h b/TailRunner.h index bbd7239..533e6a9 100644 --- a/TailRunner.h +++ b/TailRunner.h @@ -49,7 +49,7 @@ class TailRunner : public QObject void loginFlowCompleted(); private: - void runCommand(QString cmd, QStringList args, bool jsonResult = false, bool usePkExec = false); + void runCommand(const QString& cmd, QStringList args, bool jsonResult = false, bool usePkExec = false); void onProcessCanReadStdOut(); void parseStatusResponse(const QJsonObject& obj); diff --git a/TrayMenuManager.cpp b/TrayMenuManager.cpp index c2a2d5c..3e31c79 100644 --- a/TrayMenuManager.cpp +++ b/TrayMenuManager.cpp @@ -26,6 +26,8 @@ TrayMenuManager::TrayMenuManager(TailSettings& s, TailRunner* runner, QObject* p , pAbout(nullptr) , pThisDevice(nullptr) , pExitNodeNone(nullptr) + , pRefreshLocalDns(nullptr) + , pSysCommand(std::make_unique()) { pTrayMenu = new QMenu("Tailscale"); @@ -56,6 +58,7 @@ TrayMenuManager::TrayMenuManager(TailSettings& s, TailRunner* runner, QObject* p pExitNodeNone->setCheckable(true); pExitNodeNone->setChecked(true); pExitNodeNone->setEnabled(false); + pRefreshLocalDns = new QAction("Refresh Local DNS"); setupWellKnownActions(); @@ -138,6 +141,8 @@ void TrayMenuManager::buildNotConnectedMenu(TailStatus const* pTailStatus) const if (pTailStatus != nullptr && pTailStatus->user != nullptr) pThisDevice->setText(pTailStatus->user->loginName); pTrayMenu->addAction(pThisDevice); + auto* actions = pTrayMenu->addMenu("Custom Actions"); + actions->addAction(pRefreshLocalDns); pTrayMenu->addSeparator(); pTrayMenu->addAction(pPreferences); pTrayMenu->addAction(pAbout); @@ -187,6 +192,9 @@ void TrayMenuManager::buildConnectedMenu(TailStatus const* pTailStatus) const } } + auto* actions = pTrayMenu->addMenu("Custom Actions"); + actions->addAction(pRefreshLocalDns); + pTrayMenu->addSeparator(); auto* exitNodes = pTrayMenu->addMenu("Exit nodes"); exitNodes->addAction(pExitNodeNone); @@ -316,4 +324,8 @@ void TrayMenuManager::setupWellKnownActions() const { } } ); + + connect(pRefreshLocalDns, &QAction::triggered, this, [this](bool) { + pSysCommand->refreshDns(); + }); } diff --git a/TrayMenuManager.h b/TrayMenuManager.h index 2026cd9..3d668b6 100644 --- a/TrayMenuManager.h +++ b/TrayMenuManager.h @@ -5,6 +5,8 @@ #ifndef TRAYMENUMANAGER_H #define TRAYMENUMANAGER_H +#include + #include #include #include @@ -12,18 +14,19 @@ #include "models.h" #include "TailRunner.h" #include "TailSettings.h" +#include "SysCommand.h" class TrayMenuManager : public QObject { Q_OBJECT public: explicit TrayMenuManager(TailSettings& s, TailRunner* runner, QObject* parent = nullptr); - virtual ~TrayMenuManager(); + ~TrayMenuManager() final; void onAccountsListed(const QList& foundAccounts); void stateChangedTo(TailState newState, TailStatus const* pTailStatus) const; - QSystemTrayIcon* trayIcon() const { return pSysTray; } + [[nodiscard]] QSystemTrayIcon* trayIcon() const { return pSysTray; } private: QList accounts; @@ -42,6 +45,9 @@ class TrayMenuManager : public QObject QAction* pAbout; QAction* pThisDevice; QAction* pExitNodeNone; + QAction* pRefreshLocalDns; + + std::unique_ptr pSysCommand; private: void buildNotLoggedInMenu() const;