fingerprint: better feedback and don't clear input field on retry (#613)

This commit is contained in:
Ricky Lopez 2024-12-27 07:21:02 -08:00 committed by GitHub
parent 181294c4d8
commit d212f4cc10
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 58 additions and 22 deletions

View file

@ -13,7 +13,6 @@ static const auto FPRINT = sdbus::ServiceName{"net.reactivated.Fprint"};
static const auto DEVICE = sdbus::ServiceName{"net.reactivated.Fprint.Device"}; static const auto DEVICE = sdbus::ServiceName{"net.reactivated.Fprint.Device"};
static const auto MANAGER = sdbus::ServiceName{"net.reactivated.Fprint.Manager"}; static const auto MANAGER = sdbus::ServiceName{"net.reactivated.Fprint.Manager"};
static const auto LOGIN_MANAGER = sdbus::ServiceName{"org.freedesktop.login1.Manager"}; static const auto LOGIN_MANAGER = sdbus::ServiceName{"org.freedesktop.login1.Manager"};
static const auto RETRY_MESSAGE = "Could not match fingerprint. Try again.";
enum MatchResult { enum MatchResult {
MATCH_INVALID = 0, MATCH_INVALID = 0,
@ -81,10 +80,14 @@ void CFingerprint::handleInput(const std::string& input) {
} }
std::optional<std::string> CFingerprint::getLastFailText() { std::optional<std::string> CFingerprint::getLastFailText() {
return m_sDBUSState.message.empty() ? std::nullopt : std::optional(m_sDBUSState.message); if (!m_sFailureReason.empty())
return std::optional(m_sFailureReason);
return std::nullopt;
} }
std::optional<std::string> CFingerprint::getLastPrompt() { std::optional<std::string> CFingerprint::getLastPrompt() {
if (!m_sPrompt.empty())
return std::optional(m_sPrompt);
return std::nullopt; return std::nullopt;
} }
@ -140,7 +143,8 @@ bool CFingerprint::createDeviceProxy() {
bool isPresent = presentVariant.get<bool>(); bool isPresent = presentVariant.get<bool>();
if (!isPresent) if (!isPresent)
return; return;
m_sDBUSState.message = m_sFingerprintPresent; m_sPrompt = m_sFingerprintPresent;
m_sFailureReason = "";
g_pHyprlock->enqueueForceUpdateTimers(); g_pHyprlock->enqueueForceUpdateTimers();
} catch (std::out_of_range& e) {} } catch (std::out_of_range& e) {}
}); });
@ -153,6 +157,7 @@ void CFingerprint::handleVerifyStatus(const std::string& result, bool done) {
Debug::log(LOG, "fprint: handling status {}", result); Debug::log(LOG, "fprint: handling status {}", result);
auto matchResult = s_mapStringToTestType[result]; auto matchResult = s_mapStringToTestType[result];
bool authenticated = false; bool authenticated = false;
bool retry = false;
if (m_sDBUSState.sleeping && matchResult != MATCH_DISCONNECTED) if (m_sDBUSState.sleeping && matchResult != MATCH_DISCONNECTED)
return; return;
switch (matchResult) { switch (matchResult) {
@ -160,34 +165,53 @@ void CFingerprint::handleVerifyStatus(const std::string& result, bool done) {
case MATCH_NO_MATCH: case MATCH_NO_MATCH:
stopVerify(); stopVerify();
if (m_sDBUSState.retries >= 3) { if (m_sDBUSState.retries >= 3) {
m_sDBUSState.message = "Fingerprint auth disabled (too many failed attempts)"; m_sPrompt = "";
m_sFailureReason = "Fingerprint auth disabled (too many failed attempts)";
} else { } else {
done = false; done = false;
startVerify(true); startVerify(true);
m_sDBUSState.message = "Fingerprint not matched";
} }
break; break;
case MATCH_UNKNOWN_ERROR: case MATCH_UNKNOWN_ERROR:
stopVerify(); stopVerify();
m_sDBUSState.message = "Fingerprint auth disabled (unknown error)"; m_sPrompt = "";
m_sFailureReason = "Fingerprint auth disabled (unknown error)";
break; break;
case MATCH_MATCHED: case MATCH_MATCHED:
stopVerify(); stopVerify();
m_sDBUSState.message = ""; m_sPrompt = "";
authenticated = true; m_sFailureReason = "";
authenticated = true;
g_pAuth->enqueueUnlock(); g_pAuth->enqueueUnlock();
break; break;
case MATCH_RETRY: m_sDBUSState.message = "Please retry fingerprint scan"; break; case MATCH_RETRY:
case MATCH_SWIPE_TOO_SHORT: m_sDBUSState.message = "Swipe too short - try again"; break; retry = true;
case MATCH_FINGER_NOT_CENTERED: m_sDBUSState.message = "Finger not centered - try again"; break; m_sPrompt = "Please retry fingerprint scan";
case MATCH_REMOVE_AND_RETRY: m_sDBUSState.message = "Remove your finger and try again"; break; m_sFailureReason = "";
break;
case MATCH_SWIPE_TOO_SHORT:
retry = true;
m_sPrompt = "Swipe too short - try again";
m_sFailureReason = "";
break;
case MATCH_FINGER_NOT_CENTERED:
retry = true;
m_sPrompt = "Finger not centered - try again";
m_sFailureReason = "";
break;
case MATCH_REMOVE_AND_RETRY:
retry = true;
m_sPrompt = "Remove your finger and try again";
m_sFailureReason = "";
break;
case MATCH_DISCONNECTED: case MATCH_DISCONNECTED:
m_sDBUSState.message = "Fingerprint device disconnected"; m_sPrompt = "";
m_sDBUSState.abort = true; m_sFailureReason = "Fingerprint device disconnected";
m_sDBUSState.abort = true;
break; break;
} }
if (!authenticated) if (!authenticated && !retry)
g_pAuth->enqueueFail(); g_pAuth->enqueueFail();
if (done || m_sDBUSState.abort) if (done || m_sDBUSState.abort)
@ -218,15 +242,20 @@ void CFingerprint::startVerify(bool isRetry) {
m_sDBUSState.device->callMethodAsync("VerifyStart").onInterface(DEVICE).withArguments(finger).uponReplyInvoke([this, isRetry](std::optional<sdbus::Error> e) { m_sDBUSState.device->callMethodAsync("VerifyStart").onInterface(DEVICE).withArguments(finger).uponReplyInvoke([this, isRetry](std::optional<sdbus::Error> e) {
if (e) { if (e) {
Debug::log(WARN, "fprint: could not start verifying, {}", e->what()); Debug::log(WARN, "fprint: could not start verifying, {}", e->what());
if (isRetry) if (isRetry) {
m_sDBUSState.message = "Fingerprint auth disabled (failed to restart)"; m_sPrompt = "";
m_sFailureReason = "Fingerprint auth disabled (failed to restart)";
}
} else { } else {
Debug::log(LOG, "fprint: started verifying"); Debug::log(LOG, "fprint: started verifying");
if (isRetry) { if (isRetry) {
m_sDBUSState.retries++; m_sDBUSState.retries++;
m_sDBUSState.message = RETRY_MESSAGE; m_sPrompt = "Could not match fingerprint. Try again.";
} else m_sFailureReason = "";
m_sDBUSState.message = m_sFingerprintReady; } else {
m_sPrompt = m_sFingerprintReady;
m_sFailureReason = "";
}
} }
g_pHyprlock->enqueueForceUpdateTimers(); g_pHyprlock->enqueueForceUpdateTimers();
}); });

View file

@ -26,8 +26,6 @@ class CFingerprint : public IAuthImplementation {
private: private:
struct SDBUSState { struct SDBUSState {
std::string message = "";
std::shared_ptr<sdbus::IConnection> connection; std::shared_ptr<sdbus::IConnection> connection;
std::unique_ptr<sdbus::IProxy> login; std::unique_ptr<sdbus::IProxy> login;
std::unique_ptr<sdbus::IProxy> device; std::unique_ptr<sdbus::IProxy> device;
@ -42,6 +40,9 @@ class CFingerprint : public IAuthImplementation {
std::string m_sFingerprintReady; std::string m_sFingerprintReady;
std::string m_sFingerprintPresent; std::string m_sFingerprintPresent;
std::string m_sPrompt{""};
std::string m_sFailureReason{""};
void handleVerifyStatus(const std::string& result, const bool done); void handleVerifyStatus(const std::string& result, const bool done);
void inhibitSleep(); void inhibitSleep();

View file

@ -197,6 +197,12 @@ IWidget::SFormatResult IWidget::formatString(std::string in) {
result.allowForceUpdate = true; result.allowForceUpdate = true;
} }
if (in.contains("$FPRINTPROMPT")) {
const auto FPRINTPROMPT = g_pAuth->getPrompt(AUTH_IMPL_FINGERPRINT);
replaceInString(in, "$FPRINTPROMPT", FPRINTPROMPT.value_or(""));
result.allowForceUpdate = true;
}
if (in.starts_with("cmd[") && in.contains("]")) { if (in.starts_with("cmd[") && in.contains("]")) {
// this is a command // this is a command
CVarList vars(in.substr(4, in.find_first_of(']') - 4), 0, ',', true); CVarList vars(in.substr(4, in.find_first_of(']') - 4), 0, ',', true);