Update nightwatch75/dns-switcher to 0.1.2 — fix #292 review notes (#319)

Addresses the three non-blocking notes from #292:

- README's plugin_api requirement was stale (22) vs the manifest's real
  minimum (17, the onExit lifecycle addition) — corrected, and pinned the
  noctalia version floor to beta.7 (the first tagged release plugin_api
  actually reaches 17 in).
- apply()'s privilege path ran the whole discovery+mutate script through
  `priv sh -c '...'`, which the documented sudoers rule (NOPASSWD:
  /usr/bin/nmcli) never covers — sudo -n always failed. Now the privilege
  prefix is applied to each of the two mutating nmcli calls individually,
  never to a wrapping shell.
- Regenerated thumbnail.webp.

Co-authored-by: nightwatch75 <nightwatch75@users.noreply.github.com>
This commit is contained in:
nightwatch75
2026-08-09 09:53:47 -04:00
committed by GitHub
co-authored by nightwatch75
parent b9d21951ec
commit f222cdee2b
6 changed files with 34 additions and 25 deletions
+9 -3
View File
@@ -75,8 +75,8 @@ neighbouring provider (what scroll sends).
## Requirements
- noctalia v5.0.0-beta.6 or newer for the core plugin; the gesture remapping
and lookup tester need a newer build still (`plugin_api = 22`)
- noctalia v5.0.0-beta.7 or newer (`plugin_api = 17`, for the `onExit`
lifecycle cleanup in `service.luau`)
- NetworkManager (`networkmanager`, provides `nmcli`) with an active connection
- Permission to modify system connections (see *Privileges* below)
- `dig` (bind-tools/dnsutils) or `nslookup`, optional — only the lookup
@@ -87,13 +87,19 @@ neighbouring provider (what scroll sends).
*Privilege command* is **empty by default**: NetworkManager's polkit policy
usually lets active local sessions modify system connections without a
password. If you get a "not authorized" error, set it to `pkexec` (shows
noctalia's own polkit prompt) or `sudo -n` with a matching sudoers rule:
noctalia's own polkit prompt) or `sudo -n` with a matching sudoers rule.
The privilege command is applied to the `nmcli con mod` and `nmcli device
reapply` calls individually — never to a wrapping shell — so the sudoers
rule only ever needs to name `nmcli` itself:
```
# /etc/sudoers.d/nmcli-dns
youruser ALL=(root) NOPASSWD: /usr/bin/nmcli
```
With `pkexec`, this means an apply may show its polkit prompt twice (once
per elevated `nmcli` call) instead of once.
Or grant it via a polkit rule and keep the setting empty:
```js
+2 -1
View File
@@ -13,7 +13,8 @@
-- binding that opens its own settings, and that default is exactly what's
-- wanted here.
local STATE_KEY = "dns_state"
local STATE_KEY = "dns_state" -- published by service.luau
local GLYPH_UNKNOWN = "globe"
local snapshot = nil -- last state published by the service
+2 -2
View File
@@ -4,8 +4,8 @@
-- "apply_request" entries this panel emits. Picking a provider applies it
-- immediately (one nmcli change, no reactivation).
local STATE_KEY = "dns_state"
local REQUEST_KEY = "apply_request"
local STATE_KEY = "dns_state" -- published by service.luau
local REQUEST_KEY = "apply_request" -- consumed by service.luau
local RESOLVE_TIMEOUT_MS = 4000
+1 -1
View File
@@ -6,7 +6,7 @@
id = "nightwatch75/dns-switcher"
name = "DNS Switcher"
version = "0.1.1"
version = "0.1.2"
plugin_api = 17
author = "nightwatch75"
license = "MIT"
+20 -18
View File
@@ -14,10 +14,13 @@
-- reapply pushes the change onto the live connection without reactivating
-- it, so the network never drops. The privilege command is empty by default:
-- NetworkManager's polkit policy lets active local sessions modify system
-- connections on most desktop distros.
-- connections on most desktop distros. When set, it is prefixed onto each
-- of those two nmcli calls individually (never onto a wrapping shell), so a
-- sudoers NOPASSWD rule naming the nmcli binary itself is enough — see
-- apply() below and the README's Privileges section.
local STATE_KEY = "dns_state"
local REQUEST_KEY = "apply_request"
local STATE_KEY = "dns_state" -- published here, read by widget + panel
local REQUEST_KEY = "apply_request" -- sent by widget/panel, consumed here
local BUILTIN = {
{ id = "google", label = "Google", ip = "8.8.8.8 8.8.4.4", glyph = "brand-google" },
@@ -52,10 +55,6 @@ local function trim(value)
return (value:gsub("^%s+", ""):gsub("%s+$", ""))
end
local function shellQuote(value)
return "'" .. value:gsub("'", "'\\''") .. "'"
end
local function pollSeconds()
return math.max(2, tonumber(cfg("poll_seconds")) or 10)
end
@@ -302,23 +301,26 @@ local function apply(provider)
else
mods = 'ipv4.dns "' .. safeIp .. '" ipv4.ignore-auto-dns yes'
end
local inner = 'ACT=$(LC_ALL=C nmcli -t -f TYPE,DEVICE,UUID connection show --active 2>/dev/null); '
.. [[LINE=$(printf '%s\n' "$ACT" | grep -E '^(802-11-wireless|802-3-ethernet):' | head -n 1); ]]
.. [=[[ -n "$LINE" ] || LINE=$(printf '%s\n' "$ACT" | grep -v '^loopback:' | head -n 1); ]=]
.. [=[[ -n "$LINE" ] || exit 9; ]=]
.. 'DEV=$(printf \'%s\' "$LINE" | cut -d: -f2); '
.. 'UUID=$(printf \'%s\' "$LINE" | cut -d: -f3); '
.. 'nmcli con mod "$UUID" ' .. mods .. ' && nmcli device reapply "$DEV"'
local priv = cfg("privilege_command")
if type(priv) ~= "string" then
priv = ""
end
priv = trim(priv)
local cmd = inner
if priv ~= "" then
cmd = priv .. " sh -c " .. shellQuote(inner)
end
-- Prefixed onto each nmcli invocation individually, never onto a
-- wrapping `sh -c`: the README's sudoers example authorizes the nmcli
-- binary itself (NOPASSWD: /usr/bin/nmcli), which never covers a shell
-- run under sudo. Discovering the device/uuid stays unprivileged either
-- way (it's a plain read), so only the two mutating calls need it.
local privPrefix = priv ~= "" and (priv .. " ") or ""
local cmd = 'ACT=$(LC_ALL=C nmcli -t -f TYPE,DEVICE,UUID connection show --active 2>/dev/null); '
.. [[LINE=$(printf '%s\n' "$ACT" | grep -E '^(802-11-wireless|802-3-ethernet):' | head -n 1); ]]
.. [=[[ -n "$LINE" ] || LINE=$(printf '%s\n' "$ACT" | grep -v '^loopback:' | head -n 1); ]=]
.. [=[[ -n "$LINE" ] || exit 9; ]=]
.. 'DEV=$(printf \'%s\' "$LINE" | cut -d: -f2); '
.. 'UUID=$(printf \'%s\' "$LINE" | cut -d: -f3); '
.. privPrefix .. 'nmcli con mod "$UUID" ' .. mods .. ' && ' .. privPrefix .. 'nmcli device reapply "$DEV"'
changing = true
publish()
Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 79 KiB