Files
Panama/config/dot/quickshell/modules/polkit/PolkitPrompt.qml
T
Gabriel Brown f42b3cfe0e Let the password prompt say why
panama-sudo is pkexec with a stated reason: the reason travels to the
shell over the existing polkit IPC target, and the prompt renders it
labeled "Stated reason (unverified)" beside polkitd's real action
message -- beside, never instead of, because any process can claim any
reason and the action text is the trust anchor. Reasons are single-shot
and expire in ten seconds, so a stale one cannot dress up an unrelated
prompt; without a reason, a running shell, or qs the wrapper is exactly
pkexec. Built for agents, so the person typing their password learns
what for. Verified live end to end -- reason shown, consumed once,
expired when stale, cleared on dismissal -- and pinned by the polkit
reason contract.
2026-08-21 18:57:26 -04:00

186 lines
5.8 KiB
QML

// The authentication prompt.
//
// Deliberately a Panama surface rather than the compositor's stock agent: this
// is the window that asks for the password to everything, and it was the one
// window on the desktop that looked like it belonged to something else.
//
// Two things here are security, not styling. It takes EXCLUSIVE keyboard focus,
// so keystrokes cannot reach the window underneath while a password is being
// typed. And the field is cleared on every exit path, including the ones nobody
// plans for.
import Quickshell
import Quickshell.Wayland
import QtQuick
import qs.config
import qs.services
import qs.modules.settings
PanelWindow {
id: root
visible: Polkit.active
color: "transparent"
anchors { top: true; bottom: true; left: true; right: true }
exclusiveZone: 0
WlrLayershell.namespace: "qs-polkit"
WlrLayershell.layer: WlrLayer.Overlay
// Exclusive, not OnDemand: a password prompt that lets keystrokes through
// to whatever is behind it is a keylogger with extra steps.
WlrLayershell.keyboardFocus: Polkit.active
? WlrKeyboardFocus.Exclusive
: WlrKeyboardFocus.None
onVisibleChanged: {
if (root.visible) {
field.text = "";
field.forceActiveFocus();
} else {
field.text = "";
}
}
// Dims what is behind, and swallows clicks so nothing outside the dialog
// can be operated while it is waiting.
Rectangle {
anchors.fill: parent
color: Theme.alpha(Theme.bgDark, Theme.overlayAlpha)
MouseArea {
anchors.fill: parent
// Clicking outside does nothing on purpose. Dismissing an
// authentication request by misclick, and having the thing that
// asked report a mysterious failure, is worse than an explicit
// Cancel.
hoverEnabled: true
}
}
Rectangle {
id: dialog
anchors.centerIn: parent
width: 420
implicitHeight: layout.implicitHeight + 44
radius: Theme.popoverRadius
color: Theme.alpha(Theme.bgPopover, Theme.popoverAlpha)
border.width: 1
border.color: Theme.alpha(Theme.fg, 0.1)
Column {
id: layout
anchors.centerIn: parent
width: parent.width - 44
spacing: 14
Text {
width: parent.width
text: "Authentication required"
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.DemiBold
wrapMode: Text.WordWrap
}
Text {
width: parent.width
text: Polkit.message
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
wrapMode: Text.WordWrap
}
// The caller's stated reason, when panama-sudo passed one.
// Untrusted commentary from an unprivileged process, so it is
// labeled as a claim and drawn beside polkitd's message above --
// never in place of it. The real action text is the trust anchor.
Column {
width: parent.width
visible: Polkit.statedReason !== ""
spacing: 2
Text {
text: "Stated reason (unverified)"
color: Theme.fgMuted
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
}
Text {
width: parent.width
text: Polkit.statedReason
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
font.italic: true
wrapMode: Text.WordWrap
}
}
Text {
width: parent.width
visible: Polkit.users.length > 1
text: "Authenticating as " + Polkit.chosenUser
color: Theme.fgMuted
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
PasswordField {
id: field
width: parent.width
placeholder: "Password"
enabled: !Polkit.authenticating
onAccepted: {
if (field.text !== "")
Polkit.submit(field.text);
field.text = "";
}
}
Text {
width: parent.width
visible: Polkit.failureText !== ""
text: Polkit.failureText
color: Theme.danger
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
wrapMode: Text.WordWrap
}
Row {
anchors.right: parent.right
spacing: 8
SettingsButton {
text: "Cancel"
onClicked: Polkit.cancel()
}
SettingsButton {
text: Polkit.authenticating ? "Checking…" : "Authenticate"
tone: "accent"
enabled: !Polkit.authenticating
onClicked: {
if (field.text !== "")
Polkit.submit(field.text);
field.text = "";
}
}
}
}
}
// Escape cancels, which is what every other dialog on this desktop does.
Item {
anchors.fill: parent
focus: true
Keys.onEscapePressed: Polkit.cancel()
}
}