Own the network: details, VPN, enterprise Wi-Fi, and a firewall that can also allow

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-24 16:31:52 -04:00
parent aba2d16ffa
commit b30bf40407
29 changed files with 4452 additions and 241 deletions
@@ -84,6 +84,30 @@ Singleton {
readonly property bool wifiEnabled: Networking.wifiEnabled
readonly property bool wifiAvailable: Networking.wifiHardwareEnabled
// The radio switches, as functions rather than as writes a page makes for
// itself. Both are one-line assignments to the native modules, which is
// exactly the point: a page that reached past this service to set
// Networking.wifiEnabled directly would be one page's worth of the rule
// this file exists to keep -- and the next such write, needing a retry or a
// guard, would have nowhere to live but the page.
//
// Native both ways. Nothing here shells out to nmcli or rfkill; airplane
// mode, which genuinely needs rfkill, lives in NetworkTools.qml instead.
function setWifiEnabled(enabled: bool): void {
if (Networking.wifiEnabled !== enabled)
Networking.wifiEnabled = enabled;
}
function setBluetoothEnabled(enabled: bool): void {
const device = root.adapter;
if (!device || device.enabled === enabled)
return;
device.enabled = enabled;
}
readonly property bool bluetoothEnabled: root.adapter?.enabled ?? false
readonly property bool bluetoothAvailable: !!root.adapter
// Current network, then saved, then by signal -- the order GNOME uses,
// which is the order you actually look for things in.
readonly property var networks: {
@@ -124,15 +148,37 @@ Singleton {
&& network.security !== WifiSecurityType.Unknown;
}
// Member names come from the installed plugin's own qmltypes --
// Quickshell/Networking/quickshell-network.qmltypes, whose WifiSecurityType
// is exactly: Wpa3SuiteB192, Sae, Wpa2Eap, Wpa2Psk, WpaEap, WpaPsk,
// StaticWep, DynamicWep, Leap, Owe, Open, Unknown -- rather than the
// GNOME-style names this switch used to test (Wep, Wpa, Wpa2, Wpa3,
// Enterprise). None of those five exist, and a `case` against an undefined
// member simply never matches, so every secured network read "Secured" and
// "Enterprise" was unreachable. The enterprise join form keys off exactly
// that string, so the whole 802.1X flow was dead.
//
// The open cases are named here rather than delegated to isSecured(),
// which treats Unknown as unsecured. Calling a network whose security
// nobody could read "Open" is a claim this cannot back up; Unknown falls
// through to "Secured" instead. isSecured() keeps its own meaning -- "does
// joining this need a passphrase" -- and is unchanged.
//
// Owe is Enhanced Open: encrypted, but joined without a passphrase, so to
// someone picking a network it reads as open.
function securityLabel(network: var): string {
if (!root.isSecured(network))
return "Open";
switch (network.security) {
case WifiSecurityType.Wep: return "WEP";
case WifiSecurityType.Wpa: return "WPA";
case WifiSecurityType.Wpa2: return "WPA2";
case WifiSecurityType.Wpa3: return "WPA3";
case WifiSecurityType.Enterprise: return "Enterprise";
case WifiSecurityType.Open: return "Open";
case WifiSecurityType.Owe: return "Open";
case WifiSecurityType.StaticWep: return "WEP";
case WifiSecurityType.WpaPsk: return "WPA";
case WifiSecurityType.Wpa2Psk: return "WPA2";
case WifiSecurityType.Sae: return "WPA3";
case WifiSecurityType.WpaEap: return "Enterprise";
case WifiSecurityType.Wpa2Eap: return "Enterprise";
case WifiSecurityType.Wpa3SuiteB192: return "Enterprise";
case WifiSecurityType.DynamicWep: return "Enterprise";
case WifiSecurityType.Leap: return "Enterprise";
}
return "Secured";
}
@@ -152,10 +198,14 @@ Singleton {
return "No signal";
}
// NoSecrets, not "Authentication" -- the qmltypes members are NoSecrets,
// Unknown, WifiAuthTimeout, WifiClientDisconnected, WifiClientFailed,
// WifiNetworkLost. A case against an undefined member never matches, so a
// wrong password used to fall through to the generic text.
function connectionFailureText(reason: var): string {
switch (reason) {
case ConnectionFailReason.WifiAuthTimeout:
case ConnectionFailReason.Authentication:
case ConnectionFailReason.NoSecrets:
return "Wrong password";
case ConnectionFailReason.WifiNetworkLost:
return "Network out of range";