Listing zones and services is what firewall-cmd already does. The question it does not answer needs both halves at once: a port is reachable only when something is LISTENING on a network address AND the firewall permits it. On this machine that crossing is the whole story. The rules look unremarkable -- one zone, three services, a port range -- and what they mean is that PostgreSQL and Redis, published by rootless containers on every interface, are reachable by anyone on the network. Neither half says that alone, which is exactly how a tidy rules list coexists with an open database. Nothing was misconfigured: Fedora's default zone met podman's default publish behaviour. Ephemeral client sockets are excluded. A browser's outbound UDP port is indistinguishable from a service in ss, and listing twenty of them buried the two rows that mattered. Closing the port range names what it would cut off, by service, before doing it, and removing ssh says so when someone is connected over it. Rich rules are shown and never edited: a syntax is not a setting, but hiding it would misrepresent the configuration. The contract needed a recorded firewall, and the reason is worth keeping. The rule this page exists for cannot be tested against this machine -- its zone permits everything above 1024, so "listening" and "listening and permitted" give identical answers, and a blocked listener needs a port below 1024, which needs root. With the crossing deleted, the contract passed. It now runs against a fixture where two listeners are blocked, and catches it. Also here: polkit response files are written 0600 rather than at the default mask, the agent sweeps requests left by an instance that did not exit cleanly, and the write sweep waits for its harness to be ready instead of reporting the startup race as settings that failed. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
201 lines
7.4 KiB
QML
201 lines
7.4 KiB
QML
import QtQuick
|
||
import qs.config
|
||
import qs.services
|
||
|
||
Rectangle {
|
||
id: root
|
||
|
||
property var hostWindow: null
|
||
readonly property var homePhoneDiagnostics: pageLoader.status === Loader.Ready
|
||
&& pageLoader.item
|
||
&& pageLoader.item.objectName === "home-phone-page"
|
||
? pageLoader.item.pageDiagnostics
|
||
: ({})
|
||
readonly property var healthDiagnostics: pageLoader.status === Loader.Ready
|
||
&& pageLoader.item
|
||
&& pageLoader.item.objectName === "system-health-page"
|
||
? pageLoader.item.uiDiagnostics()
|
||
: ({})
|
||
|
||
function requestHealthAction(id: string): bool {
|
||
if (pageLoader.status !== Loader.Ready
|
||
|| !pageLoader.item
|
||
|| pageLoader.item.objectName !== "system-health-page")
|
||
return false;
|
||
return pageLoader.item.activateRenderedAction(id);
|
||
}
|
||
|
||
color: Theme.bg
|
||
radius: 18
|
||
border.width: 1
|
||
border.color: Theme.alpha(Theme.fg, 0.08)
|
||
clip: true
|
||
|
||
SettingsSidebar {
|
||
id: sidebar
|
||
anchors.left: parent.left
|
||
anchors.top: titlebar.bottom
|
||
anchors.bottom: parent.bottom
|
||
selectedPage: ShellState.settingsPage
|
||
onPageRequested: page => ShellState.openSettings(page)
|
||
}
|
||
|
||
Rectangle {
|
||
id: titlebar
|
||
anchors.left: parent.left
|
||
anchors.right: parent.right
|
||
anchors.top: parent.top
|
||
height: 48
|
||
color: Theme.alpha(Theme.bgDark, 0.97)
|
||
border.width: 0
|
||
|
||
Text {
|
||
anchors.left: parent.left
|
||
anchors.leftMargin: 18
|
||
anchors.verticalCenter: parent.verticalCenter
|
||
text: "Settings"
|
||
color: Theme.fg
|
||
font.family: Theme.fontFamily
|
||
font.pixelSize: Theme.fontSize
|
||
font.weight: Font.DemiBold
|
||
}
|
||
|
||
Row {
|
||
anchors.right: parent.right
|
||
anchors.rightMargin: 12
|
||
anchors.verticalCenter: parent.verticalCenter
|
||
spacing: 7
|
||
|
||
Rectangle {
|
||
width: 28; height: 28; radius: 9
|
||
color: minMouse.containsMouse ? Theme.alpha(Theme.fg, 0.12) : Theme.alpha(Theme.fg, 0)
|
||
Text { anchors.centerIn: parent; text: "—"; color: Theme.fgDim; font.family: Theme.fontFamily; font.pixelSize: Theme.fontSize }
|
||
MouseArea { id: minMouse; anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor; onClicked: if (root.hostWindow) root.hostWindow.minimized = true }
|
||
}
|
||
|
||
Rectangle {
|
||
width: 28; height: 28; radius: 9
|
||
color: closeMouse.containsMouse ? Theme.alpha(Theme.danger, 0.17) : Theme.alpha(Theme.fg, 0)
|
||
Text { anchors.centerIn: parent; text: "×"; color: closeMouse.containsMouse ? Theme.danger : Theme.fgDim; font.family: Theme.fontFamily; font.pixelSize: 18 }
|
||
MouseArea { id: closeMouse; anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor; onClicked: ShellState.closeSettings() }
|
||
}
|
||
}
|
||
|
||
DragHandler {
|
||
target: null
|
||
onActiveChanged: if (active && root.hostWindow) root.hostWindow.startSystemMove()
|
||
}
|
||
}
|
||
|
||
Rectangle {
|
||
anchors.left: sidebar.right
|
||
anchors.top: titlebar.bottom
|
||
anchors.bottom: parent.bottom
|
||
width: 1
|
||
color: Theme.alpha(Theme.fg, 0.06)
|
||
}
|
||
|
||
Loader {
|
||
id: pageLoader
|
||
anchors.left: sidebar.right
|
||
anchors.right: parent.right
|
||
anchors.top: titlebar.bottom
|
||
anchors.bottom: parent.bottom
|
||
sourceComponent: {
|
||
switch (ShellState.settingsPage) {
|
||
case "appearance": return appearancePage;
|
||
case "displays": return displaysPage;
|
||
case "connectivity": return connectivityPage;
|
||
case "home-phone": return homePhonePage;
|
||
case "desktop": return desktopPage;
|
||
case "sound": return soundPage;
|
||
case "gaming": return gamingPage;
|
||
case "notifications": return notificationsPage;
|
||
case "screen-intelligence": return screenIntelligencePage;
|
||
case "shortcuts": return shortcutsPage;
|
||
case "mouse": return mousePage;
|
||
case "privacy": return privacyPage;
|
||
case "region": return regionPage;
|
||
case "accounts": return onlineAccountsPage;
|
||
case "accessibility": return accessibilityPage;
|
||
case "power": return powerPage;
|
||
case "datetime": return dateTimePage;
|
||
case "applications": return applicationsPage;
|
||
case "storage": return storagePage;
|
||
case "snapshots": return snapshotsPage;
|
||
case "updates": return updatesPage;
|
||
case "users": return usersPage;
|
||
case "sharing": return sharingPage;
|
||
case "firewall": return firewallPage;
|
||
case "printers": return printersPage;
|
||
case "services": return healthPage;
|
||
case "about": return aboutPage;
|
||
default: return homePage;
|
||
}
|
||
}
|
||
}
|
||
|
||
Rectangle {
|
||
anchors.right: parent.right
|
||
anchors.rightMargin: 22
|
||
anchors.bottom: parent.bottom
|
||
anchors.bottomMargin: 20
|
||
width: Math.min(460, errorCopy.implicitWidth + 34)
|
||
height: 42
|
||
radius: 12
|
||
visible: SystemSettings.lastError !== ""
|
||
color: Theme.mix(Theme.bgPopover, Theme.danger, 0.1)
|
||
border.width: 1
|
||
border.color: Theme.alpha(Theme.danger, 0.28)
|
||
|
||
Text {
|
||
id: errorCopy
|
||
anchors.centerIn: parent
|
||
text: SystemSettings.lastError
|
||
color: Theme.fg
|
||
font.family: Theme.fontFamily
|
||
font.pixelSize: Theme.fontSizeSmall
|
||
}
|
||
|
||
MouseArea {
|
||
anchors.fill: parent
|
||
cursorShape: Qt.PointingHandCursor
|
||
onClicked: SystemSettings.lastError = ""
|
||
}
|
||
}
|
||
|
||
Component { id: homePage; HomePage {} }
|
||
Component { id: applicationsPage; ApplicationsPage {} }
|
||
Component { id: storagePage; StoragePage {} }
|
||
Component { id: snapshotsPage; SnapshotsPage {} }
|
||
Component { id: updatesPage; UpdatesPage {} }
|
||
Component { id: usersPage; UsersPage {} }
|
||
Component { id: sharingPage; SharingPage {} }
|
||
Component { id: firewallPage; FirewallPage {} }
|
||
Component { id: printersPage; PrintersPage {} }
|
||
Component { id: accessibilityPage; AccessibilityPage {} }
|
||
Component { id: powerPage; PowerPage {} }
|
||
Component { id: dateTimePage; DateTimePage {} }
|
||
Component { id: appearancePage; AppearancePage {} }
|
||
Component { id: displaysPage; DisplaysPage {} }
|
||
Component { id: connectivityPage; ConnectivityPage {} }
|
||
Component { id: homePhonePage; HomePhonePage {} }
|
||
Component { id: desktopPage; DesktopPage {} }
|
||
Component { id: soundPage; SoundPage {} }
|
||
Component { id: gamingPage; GamingPage {} }
|
||
Component { id: notificationsPage; NotificationsPage {} }
|
||
Component { id: screenIntelligencePage; ScreenIntelligencePage {} }
|
||
Component { id: shortcutsPage; ShortcutsPage {} }
|
||
Component { id: mousePage; MousePage {} }
|
||
Component { id: privacyPage; PrivacyPage {} }
|
||
Component { id: regionPage; RegionPage {} }
|
||
Component { id: onlineAccountsPage; OnlineAccountsPage {} }
|
||
Component { id: healthPage; HealthPage {} }
|
||
Component { id: aboutPage; AboutPage {} }
|
||
|
||
Shortcut {
|
||
sequence: "Escape"
|
||
onActivated: ShellState.closeSettings()
|
||
}
|
||
}
|