summaryrefslogtreecommitdiff
path: root/modules/lock/Pam.qml
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--modules/lock/Pam.qml127
1 files changed, 123 insertions, 4 deletions
diff --git a/modules/lock/Pam.qml b/modules/lock/Pam.qml
index 2675405..0186c2f 100644
--- a/modules/lock/Pam.qml
+++ b/modules/lock/Pam.qml
@@ -1,4 +1,6 @@
+import qs.config
import Quickshell
+import Quickshell.Io
import Quickshell.Wayland
import Quickshell.Services.Pam
import QtQuick
@@ -9,12 +11,16 @@ Scope {
required property WlSessionLock lock
readonly property alias passwd: passwd
- readonly property bool active: passwd.active
+ readonly property alias fprint: fprint
+ property string lockMessage
property string state
+ property string fprintState
property string buffer
+ signal flashMsg
+
function handleKey(event: KeyEvent): void {
- if (passwd.active)
+ if (passwd.active || state === "max")
return;
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
@@ -34,6 +40,16 @@ Scope {
PamContext {
id: passwd
+ config: "passwd"
+ configDirectory: Quickshell.shellDir + "/assets/pam.d"
+
+ onMessageChanged: {
+ if (message.startsWith("The account is locked"))
+ root.lockMessage = message;
+ else if (root.lockMessage && message.endsWith(" left to unlock)"))
+ root.lockMessage += "\n" + message;
+ }
+
onResponseRequiredChanged: {
if (!responseRequired)
return;
@@ -53,22 +69,125 @@ Scope {
else if (res === PamResult.Failed)
root.state = "fail";
+ root.flashMsg();
stateReset.restart();
}
}
+ PamContext {
+ id: fprint
+
+ property bool available
+ property int tries
+ property int errorTries
+
+ function checkAvail(): void {
+ if (!available || !Config.lock.enableFprint || !root.lock.secure) {
+ abort();
+ return;
+ }
+
+ tries = 0;
+ errorTries = 0;
+ start();
+ }
+
+ config: "fprint"
+ configDirectory: Quickshell.shellDir + "/assets/pam.d"
+
+ onCompleted: res => {
+ if (!available)
+ return;
+
+ if (res === PamResult.Success)
+ return root.lock.unlock();
+
+ if (res === PamResult.Error) {
+ root.fprintState = "error";
+ errorTries++;
+ if (errorTries < 5) {
+ abort();
+ errorRetry.restart();
+ }
+ } else if (res === PamResult.MaxTries) {
+ // Isn't actually the real max tries as pam only reports completed
+ // when max tries is reached.
+ tries++;
+ if (tries < Config.lock.maxFprintTries) {
+ // Restart if not actually real max tries
+ root.fprintState = "fail";
+ start();
+ } else {
+ root.fprintState = "max";
+ abort();
+ }
+ }
+
+ root.flashMsg();
+ fprintStateReset.start();
+ }
+ }
+
+ Process {
+ id: availProc
+
+ command: ["sh", "-c", "fprintd-list $USER"]
+ onExited: code => {
+ fprint.available = code === 0;
+ fprint.checkAvail();
+ }
+ }
+
+ Timer {
+ id: errorRetry
+
+ interval: 800
+ onTriggered: fprint.start()
+ }
+
Timer {
id: stateReset
interval: 4000
- onTriggered: root.state = ""
+ onTriggered: {
+ if (root.state !== "max")
+ root.state = "";
+ }
+ }
+
+ Timer {
+ id: fprintStateReset
+
+ interval: 4000
+ onTriggered: {
+ root.fprintState = "";
+ fprint.errorTries = 0;
+ }
}
Connections {
target: root.lock
+ function onSecureChanged(): void {
+ if (root.lock.secure) {
+ availProc.running = true;
+ root.buffer = "";
+ root.state = "";
+ root.fprintState = "";
+ root.lockMessage = "";
+ }
+ }
+
function onUnlock(): void {
- root.buffer = "";
+ fprint.abort();
+ }
+ }
+
+ Connections {
+ target: Config.lock
+
+ function onEnableFprintChanged(): void {
+ fprint.checkAvail();
}
}
}