5 Commits

Author SHA1 Message Date
nevaforget 7cee4f4f8d Bump version to 0.2.0 2026-03-26 16:31:20 +01:00
nevaforget 1ed42d51d1 Make login box background transparent 2026-03-26 16:31:01 +01:00
nevaforget a05c2030e8 Clean dist/ before wheel build to prevent stale artifacts
Version bumps leave old wheels in dist/, causing the glob to
expand to multiple files and python-installer to fail.
2026-03-26 15:49:37 +01:00
nevaforget 22f725e4ac Bump version to 0.1.1 2026-03-26 15:44:37 +01:00
nevaforget b8e060b850 Fix fprintd AlreadyInUse error by respecting done flag
VerifyStart was called unconditionally on retry/no-match statuses,
ignoring the done parameter from fprintd's VerifyStatus signal.
When done=False the verify session is still active, causing
AlreadyInUse errors. Now only restarts verification when done=True.
2026-03-26 15:43:27 +01:00
6 changed files with 62 additions and 13 deletions
+2 -1
View File
@@ -4,7 +4,7 @@
# Maintainer: Dominik Kressler # Maintainer: Dominik Kressler
pkgname=moonlock-git pkgname=moonlock-git
pkgver=0.0.0.r9.b365572 pkgver=0.1.1.r0.g22f725e
pkgrel=1 pkgrel=1
pkgdesc="A secure Wayland lockscreen with GTK4, PAM and fingerprint support" pkgdesc="A secure Wayland lockscreen with GTK4, PAM and fingerprint support"
arch=('any') arch=('any')
@@ -38,6 +38,7 @@ pkgver() {
build() { build() {
cd "$srcdir/moonlock" cd "$srcdir/moonlock"
rm -rf dist/
python -m build --wheel --no-isolation python -m build --wheel --no-isolation
} }
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project] [project]
name = "moonlock" name = "moonlock"
version = "0.1.0" version = "0.2.0"
description = "A secure Wayland lockscreen with GTK4, PAM and fingerprint support" description = "A secure Wayland lockscreen with GTK4, PAM and fingerprint support"
requires-python = ">=3.11" requires-python = ">=3.11"
license = "MIT" license = "MIT"
+5 -3
View File
@@ -143,13 +143,15 @@ class FingerprintListener:
return return
if status in _RETRY_STATUSES: if status in _RETRY_STATUSES:
# Retry silently — finger wasn't read properly # Retry — finger wasn't read properly
self._device_proxy.VerifyStart("(s)", "any") if done:
self._device_proxy.VerifyStart("(s)", "any")
return return
if status == "verify-no-match": if status == "verify-no-match":
if self._on_failure: if self._on_failure:
self._on_failure() self._on_failure()
# Restart verification for another attempt # Restart verification for another attempt
self._device_proxy.VerifyStart("(s)", "any") if done:
self._device_proxy.VerifyStart("(s)", "any")
return return
+1 -1
View File
@@ -12,7 +12,7 @@ window.lockscreen {
.login-box { .login-box {
padding: 40px; padding: 40px;
border-radius: 12px; border-radius: 12px;
background-color: alpha(@theme_bg_color, 0.7); background-color: transparent;
} }
/* Round avatar image */ /* Round avatar image */
+35 -4
View File
@@ -90,7 +90,22 @@ class TestFingerprintSignalHandling:
on_success.assert_called_once() on_success.assert_called_once()
def test_verify_no_match_calls_on_failure_and_retries(self): def test_verify_no_match_calls_on_failure_and_retries_when_done(self):
listener = FingerprintListener.__new__(FingerprintListener)
listener._device_proxy = MagicMock()
listener._running = True
on_success = MagicMock()
on_failure = MagicMock()
listener._on_success = on_success
listener._on_failure = on_failure
listener._on_verify_status("verify-no-match", True)
on_failure.assert_called_once()
# Should restart verification when done=True
listener._device_proxy.VerifyStart.assert_called_once_with("(s)", "any")
def test_verify_no_match_calls_on_failure_without_restart_when_not_done(self):
listener = FingerprintListener.__new__(FingerprintListener) listener = FingerprintListener.__new__(FingerprintListener)
listener._device_proxy = MagicMock() listener._device_proxy = MagicMock()
listener._running = True listener._running = True
@@ -102,10 +117,10 @@ class TestFingerprintSignalHandling:
listener._on_verify_status("verify-no-match", False) listener._on_verify_status("verify-no-match", False)
on_failure.assert_called_once() on_failure.assert_called_once()
# Should restart verification for retry # Should NOT restart verification when done=False (still in progress)
listener._device_proxy.VerifyStart.assert_called_once_with("(s)", "any") listener._device_proxy.VerifyStart.assert_not_called()
def test_verify_swipe_too_short_retries_without_failure(self): def test_verify_swipe_too_short_retries_when_done(self):
listener = FingerprintListener.__new__(FingerprintListener) listener = FingerprintListener.__new__(FingerprintListener)
listener._device_proxy = MagicMock() listener._device_proxy = MagicMock()
listener._running = True listener._running = True
@@ -119,3 +134,19 @@ class TestFingerprintSignalHandling:
on_success.assert_not_called() on_success.assert_not_called()
on_failure.assert_not_called() on_failure.assert_not_called()
listener._device_proxy.VerifyStart.assert_called_once_with("(s)", "any") listener._device_proxy.VerifyStart.assert_called_once_with("(s)", "any")
def test_retry_status_does_not_restart_when_not_done(self):
listener = FingerprintListener.__new__(FingerprintListener)
listener._device_proxy = MagicMock()
listener._running = True
on_success = MagicMock()
on_failure = MagicMock()
listener._on_success = on_success
listener._on_failure = on_failure
listener._on_verify_status("verify-swipe-too-short", False)
on_success.assert_not_called()
on_failure.assert_not_called()
# Should NOT restart — verification still in progress
listener._device_proxy.VerifyStart.assert_not_called()
+18 -3
View File
@@ -74,8 +74,23 @@ class TestFingerprintAuthFlow:
listener._on_verify_status("verify-match", False) listener._on_verify_status("verify-match", False)
assert len(unlock_called) == 1 assert len(unlock_called) == 1
def test_fingerprint_no_match_retries(self): def test_fingerprint_no_match_retries_when_done(self):
"""verify-no-match should retry verification.""" """verify-no-match with done=True should call on_failure and restart verification."""
from moonlock.fingerprint import FingerprintListener
listener = FingerprintListener.__new__(FingerprintListener)
listener._device_proxy = MagicMock()
listener._running = True
listener._on_success = MagicMock()
listener._on_failure = MagicMock()
listener._on_verify_status("verify-no-match", True)
listener._on_failure.assert_called_once()
listener._device_proxy.VerifyStart.assert_called_once()
def test_fingerprint_no_match_no_restart_when_not_done(self):
"""verify-no-match with done=False should call on_failure but not restart."""
from moonlock.fingerprint import FingerprintListener from moonlock.fingerprint import FingerprintListener
listener = FingerprintListener.__new__(FingerprintListener) listener = FingerprintListener.__new__(FingerprintListener)
@@ -87,7 +102,7 @@ class TestFingerprintAuthFlow:
listener._on_verify_status("verify-no-match", False) listener._on_verify_status("verify-no-match", False)
listener._on_failure.assert_called_once() listener._on_failure.assert_called_once()
listener._device_proxy.VerifyStart.assert_called_once() listener._device_proxy.VerifyStart.assert_not_called()
def test_fingerprint_and_password_independent(self): def test_fingerprint_and_password_independent(self):
"""Both auth methods should work independently.""" """Both auth methods should work independently."""