auth: make fingerprint initialization async (#544)

This commit is contained in:
moggiesir 2024-11-05 05:12:26 -08:00 committed by GitHub
parent f225e23e5b
commit 1cd3231537
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 75 additions and 73 deletions

View file

@ -48,15 +48,33 @@ CFingerprint::CFingerprint() {
std::shared_ptr<sdbus::IConnection> CFingerprint::start() { std::shared_ptr<sdbus::IConnection> CFingerprint::start() {
if (!m_bEnabled) if (!m_bEnabled)
return {}; return {};
m_sDBUSState.connection = sdbus::createSystemBusConnection(); m_sDBUSState.connection = sdbus::createSystemBusConnection();
registerSleepHandler(); m_sDBUSState.login = sdbus::createProxy(*m_sDBUSState.connection, sdbus::ServiceName{"org.freedesktop.login1"}, sdbus::ObjectPath{"/org/freedesktop/login1"});
m_sDBUSState.login->getPropertyAsync("PreparingForSleep").onInterface(LOGIN_MANAGER).uponReplyInvoke([this](std::optional<sdbus::Error> e, sdbus::Variant preparingForSleep) {
// When entering sleep, the wake signal will trigger startVerify(). if (e) {
if (m_sDBUSState.sleeping) Debug::log(WARN, "fprint: Failed getting value for PreparingForSleep: {}", e->what());
return m_sDBUSState.connection; return;
}
startVerify(); m_sDBUSState.sleeping = preparingForSleep.get<bool>();
// When entering sleep, the wake signal will trigger startVerify().
if (m_sDBUSState.sleeping)
return;
inhibitSleep();
startVerify();
});
m_sDBUSState.login->uponSignal("PrepareForSleep").onInterface(LOGIN_MANAGER).call([this](bool start) {
Debug::log(LOG, "fprint: PrepareForSleep (start: {})", start);
if (start) {
m_sDBUSState.sleeping = true;
stopVerify();
m_sDBUSState.inhibitLock.reset();
} else {
m_sDBUSState.sleeping = false;
inhibitSleep();
startVerify();
}
});
return m_sDBUSState.connection; return m_sDBUSState.connection;
} }
@ -73,30 +91,16 @@ void CFingerprint::terminate() {
releaseDevice(); releaseDevice();
} }
void CFingerprint::registerSleepHandler() {
m_sDBUSState.login = sdbus::createProxy(*m_sDBUSState.connection, sdbus::ServiceName{"org.freedesktop.login1"}, sdbus::ObjectPath{"/org/freedesktop/login1"});
m_sDBUSState.sleeping = m_sDBUSState.login->getProperty("PreparingForSleep").onInterface(LOGIN_MANAGER).get<bool>();
m_sDBUSState.login->uponSignal("PrepareForSleep").onInterface(LOGIN_MANAGER).call([this](bool start) {
Debug::log(LOG, "fprint: PrepareForSleep (start: {})", start);
if (start) {
m_sDBUSState.sleeping = true;
stopVerify();
m_sDBUSState.inhibitLock.reset();
} else {
m_sDBUSState.sleeping = false;
inhibitSleep();
startVerify();
}
});
if (!m_sDBUSState.sleeping)
inhibitSleep();
}
void CFingerprint::inhibitSleep() { void CFingerprint::inhibitSleep() {
m_sDBUSState.login->callMethod("Inhibit") m_sDBUSState.login->callMethodAsync("Inhibit")
.onInterface(LOGIN_MANAGER) .onInterface(LOGIN_MANAGER)
.withArguments("sleep", "hyprlock", "Fingerprint verifcation must be stopped before sleep", "delay") .withArguments("sleep", "hyprlock", "Fingerprint verifcation must be stopped before sleep", "delay")
.storeResultsTo(m_sDBUSState.inhibitLock); .uponReplyInvoke([this](std::optional<sdbus::Error> e, sdbus::UnixFd fd) {
if (e)
Debug::log(WARN, "fprint: could not inhibit sleep: {}", e->what());
else
m_sDBUSState.inhibitLock = fd;
});
} }
bool CFingerprint::createDeviceProxy() { bool CFingerprint::createDeviceProxy() {
@ -145,12 +149,9 @@ void CFingerprint::handleVerifyStatus(const std::string& result, bool done) {
stopVerify(); stopVerify();
if (m_sDBUSState.retries >= 3) { if (m_sDBUSState.retries >= 3) {
m_sDBUSState.message = "Fingerprint auth disabled: too many failed attempts"; m_sDBUSState.message = "Fingerprint auth disabled: too many failed attempts";
} else if (startVerify(/* showMessage= */ false)) {
done = false;
m_sDBUSState.retries++;
m_sDBUSState.message = RETRY_MESSAGE;
} else { } else {
m_sDBUSState.message = "Fingerprint auth disabled: could not restart verification"; done = false;
startVerify(true);
} }
break; break;
case MATCH_UNKNOWN_ERROR: case MATCH_UNKNOWN_ERROR:
@ -173,44 +174,46 @@ void CFingerprint::handleVerifyStatus(const std::string& result, bool done) {
break; break;
} }
g_pHyprlock->enqueueForceUpdateTimers(); g_pHyprlock->enqueueForceUpdateTimers();
if (done || m_sDBUSState.abort) { if (done || m_sDBUSState.abort)
m_sDBUSState.done = true; m_sDBUSState.done = true;
m_sDBUSState.connection->leaveEventLoop();
}
} }
bool CFingerprint::claimDevice() { void CFingerprint::claimDevice() {
try { const auto currentUser = ""; // Empty string means use the caller's id.
const auto currentUser = ""; // Empty string means use the caller's id. m_sDBUSState.device->callMethodAsync("Claim").onInterface(DEVICE).withArguments(currentUser).uponReplyInvoke([this](std::optional<sdbus::Error> e) {
m_sDBUSState.device->callMethod("Claim").onInterface(DEVICE).withArguments(currentUser); if (e)
} catch (sdbus::Error& e) { Debug::log(WARN, "fprint: could not claim device, {}", e->what());
Debug::log(WARN, "fprint: could not claim device, {}", e.what()); else {
return false; Debug::log(LOG, "fprint: claimed device");
} startVerify();
Debug::log(LOG, "fprint: claimed device"); }
return true; });
} }
bool CFingerprint::startVerify(bool updateMessage) { void CFingerprint::startVerify(bool isRetry) {
if (!m_sDBUSState.device) { if (!m_sDBUSState.device) {
if (!createDeviceProxy()) if (!createDeviceProxy())
return false; return;
claimDevice(); claimDevice();
return;
} }
try { auto finger = "any"; // Any finger.
auto finger = "any"; // Any finger. m_sDBUSState.device->callMethodAsync("VerifyStart").onInterface(DEVICE).withArguments(finger).uponReplyInvoke([this, isRetry](std::optional<sdbus::Error> e) {
m_sDBUSState.device->callMethod("VerifyStart").onInterface(DEVICE).withArguments(finger); if (e) {
} catch (sdbus::Error& e) { Debug::log(WARN, "fprint: could not start verifying, {}", e->what());
Debug::log(WARN, "fprint: could not start verifying, {}", e.what()); if (isRetry)
return false; m_sDBUSState.message = "Fingerprint auth disabled: could not restart verification";
} } else {
Debug::log(LOG, "fprint: started verifying"); Debug::log(LOG, "fprint: started verifying");
if (updateMessage) { if (isRetry) {
m_sDBUSState.message = m_sFingerprintReady; m_sDBUSState.retries++;
m_sDBUSState.message = RETRY_MESSAGE;
} else
m_sDBUSState.message = m_sFingerprintReady;
}
g_pHyprlock->enqueueForceUpdateTimers(); g_pHyprlock->enqueueForceUpdateTimers();
} });
return true;
} }
bool CFingerprint::stopVerify() { bool CFingerprint::stopVerify() {

View file

@ -31,21 +31,20 @@ class CFingerprint {
bool sleeping = false; bool sleeping = false;
} m_sDBUSState; } m_sDBUSState;
std::string m_sFingerprintReady; std::string m_sFingerprintReady;
std::string m_sFingerprintPresent; std::string m_sFingerprintPresent;
bool m_bAuthenticated = false; bool m_bAuthenticated = false;
bool m_bEnabled = false; bool m_bEnabled = false;
void handleVerifyStatus(const std::string& result, const bool done); void handleVerifyStatus(const std::string& result, const bool done);
void registerSleepHandler(); void inhibitSleep();
void inhibitSleep();
bool createDeviceProxy(); bool createDeviceProxy();
bool claimDevice(); void claimDevice();
bool startVerify(bool updateMessage = true); void startVerify(bool isRetry = false);
bool stopVerify(); bool stopVerify();
bool releaseDevice(); bool releaseDevice();
}; };
inline std::unique_ptr<CFingerprint> g_pFingerprint; inline std::unique_ptr<CFingerprint> g_pFingerprint;