mobile: fix vault unlock with biometrics

This commit is contained in:
Ammar Ahmed
2024-04-30 11:36:48 +05:00
committed by Ammar Ahmed
parent 96558c5df5
commit 62dd5a5416
10 changed files with 33 additions and 39 deletions

View File

@@ -24,7 +24,7 @@ import {
setAppLockVerificationCipher, setAppLockVerificationCipher,
validateAppLockPassword validateAppLockPassword
} from "../../../common/database/encryption"; } from "../../../common/database/encryption";
import BiometicService from "../../../services/biometrics"; import BiometricService from "../../../services/biometrics";
import { DDS } from "../../../services/device-detection"; import { DDS } from "../../../services/device-detection";
import { import {
ToastManager, ToastManager,
@@ -323,7 +323,7 @@ export const AppLockPassword = () => {
SettingsService.setProperty("appLockHasPasswordSecurity", false); SettingsService.setProperty("appLockHasPasswordSecurity", false);
if ( if (
!(await BiometicService.isBiometryAvailable()) || !(await BiometricService.isBiometryAvailable()) ||
SettingsService.getProperty("biometricsAuthEnabled") === false SettingsService.getProperty("biometricsAuthEnabled") === false
) { ) {
SettingsService.setProperty("appLockEnabled", false); SettingsService.setProperty("appLockEnabled", false);

View File

@@ -128,7 +128,7 @@ export class VaultDialog extends Component {
: this.state.copyNote : this.state.copyNote
? "Unlock note to copy it. If biometrics are not working, you can enter device pin to unlock vault." ? "Unlock note to copy it. If biometrics are not working, you can enter device pin to unlock vault."
: this.state.goToEditor : this.state.goToEditor
? "Unlock note to open it in editor. If biometrics are not working, you can enter device pin to unlock vault." ? "Unlock note to open it in editor."
: "Enter vault password to unlock note. If biometrics are not working, you can enter device pin to unlock vault." : "Enter vault password to unlock note. If biometrics are not working, you can enter device pin to unlock vault."
: "Enter vault password to lock note. If biometrics are not working, you can enter device pin to lock note."); : "Enter vault password to lock note. If biometrics are not working, you can enter device pin to lock note.");
} }

View File

@@ -85,7 +85,6 @@ import { SyncStatus, useUserStore } from "../stores/use-user-store";
import { updateStatusBarColor } from "../utils/colors"; import { updateStatusBarColor } from "../utils/colors";
import { BETA } from "../utils/constants"; import { BETA } from "../utils/constants";
import { import {
eClearEditor,
eCloseSheet, eCloseSheet,
eLoginSessionExpired, eLoginSessionExpired,
eOnLoadNote, eOnLoadNote,
@@ -532,12 +531,6 @@ export const useAppEvents = () => {
//@ts-ignore //@ts-ignore
globalThis["IS_SHARE_EXTENSION"] = false; globalThis["IS_SHARE_EXTENSION"] = false;
} else { } else {
const id = useTabStore.getState().getCurrentNoteId();
const note = id ? await db.notes.note(id) : undefined;
const locked = note && (await db.vaults.itemExists(note));
if (locked && SettingsService.canLockAppInBackground()) {
eSendEvent(eClearEditor);
}
await saveEditorState(); await saveEditorState();
if ( if (
SettingsService.canLockAppInBackground() && SettingsService.canLockAppInBackground() &&

View File

@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import React, { useCallback, useEffect } from "react"; import React, { useCallback, useEffect } from "react";
import BiometicService from "../services/biometrics"; import BiometricService from "../services/biometrics";
import { eSubscribeEvent, eUnSubscribeEvent } from "../services/event-manager"; import { eSubscribeEvent, eUnSubscribeEvent } from "../services/event-manager";
import { db } from "../common/database"; import { db } from "../common/database";
@@ -39,8 +39,8 @@ export const useVaultStatus = () => {
const checkVaultStatus = useCallback(() => { const checkVaultStatus = useCallback(() => {
db.vault?.exists().then(async (exists) => { db.vault?.exists().then(async (exists) => {
const available = await BiometicService.isBiometryAvailable(); const available = await BiometricService.isBiometryAvailable();
const fingerprint = await BiometicService.hasInternetCredentials(); const fingerprint = await BiometricService.hasInternetCredentials();
if ( if (
VaultStatusCache.exists === exists && VaultStatusCache.exists === exists &&
VaultStatusCache.biometryEnrolled === fingerprint && VaultStatusCache.biometryEnrolled === fingerprint &&

View File

@@ -32,7 +32,7 @@ import WebView from "react-native-webview";
import { ShouldStartLoadRequest } from "react-native-webview/lib/WebViewTypes"; import { ShouldStartLoadRequest } from "react-native-webview/lib/WebViewTypes";
import { notesnook } from "../../../e2e/test.ids"; import { notesnook } from "../../../e2e/test.ids";
import { db } from "../../common/database"; import { db } from "../../common/database";
import BiometicService from "../../services/biometrics"; import BiometricService from "../../services/biometrics";
import { import {
ToastManager, ToastManager,
eSendEvent, eSendEvent,
@@ -208,8 +208,8 @@ const useLockedNoteHandler = () => {
useEffect(() => { useEffect(() => {
(async () => { (async () => {
const biometry = await BiometicService.isBiometryAvailable(); const biometry = await BiometricService.isBiometryAvailable();
const fingerprint = await BiometicService.hasInternetCredentials(); const fingerprint = await BiometricService.hasInternetCredentials();
useTabStore.setState({ useTabStore.setState({
biometryAvailable: !!biometry, biometryAvailable: !!biometry,
biometryEnrolled: !!fingerprint biometryEnrolled: !!fingerprint
@@ -223,9 +223,9 @@ const useLockedNoteHandler = () => {
try { try {
if (!tabRef.current?.noteLocked || !tabRef.current) return; if (!tabRef.current?.noteLocked || !tabRef.current) return;
console.log("Trying to unlock with biometrics..."); console.log("Trying to unlock with biometrics...");
const credentials = await BiometicService.getCredentials( const credentials = await BiometricService.getCredentials(
"Unlock note", "Unlock note",
"Unlock note to open it in editor. If biometrics are not working, you can enter device pin to unlock vault." "Unlock note to open it in editor."
); );
if (credentials && credentials?.password && tabRef.current.noteId) { if (credentials && credentials?.password && tabRef.current.noteId) {
@@ -233,6 +233,7 @@ const useLockedNoteHandler = () => {
tabRef.current.noteId, tabRef.current.noteId,
credentials?.password credentials?.password
); );
eSendEvent(eOnLoadNote, { eSendEvent(eOnLoadNote, {
item: note item: note
}); });
@@ -269,7 +270,7 @@ const useLockedNoteHandler = () => {
try { try {
const unlocked = await db.vault.unlock(password); const unlocked = await db.vault.unlock(password);
if (!unlocked) throw new Error("Incorrect vault password"); if (!unlocked) throw new Error("Incorrect vault password");
await BiometicService.storeCredentials(password); await BiometricService.storeCredentials(password);
eSendEvent("vaultUpdated"); eSendEvent("vaultUpdated");
ToastManager.show({ ToastManager.show({
heading: "Biometric unlocking enabled!", heading: "Biometric unlocking enabled!",
@@ -278,8 +279,8 @@ const useLockedNoteHandler = () => {
context: "global" context: "global"
}); });
const biometry = await BiometicService.isBiometryAvailable(); const biometry = await BiometricService.isBiometryAvailable();
const fingerprint = await BiometicService.hasInternetCredentials(); const fingerprint = await BiometricService.hasInternetCredentials();
useTabStore.setState({ useTabStore.setState({
biometryAvailable: !!biometry, biometryAvailable: !!biometry,
biometryEnrolled: !!fingerprint biometryEnrolled: !!fingerprint

View File

@@ -26,7 +26,7 @@ import { Pressable } from "../../components/ui/pressable";
import Seperator from "../../components/ui/seperator"; import Seperator from "../../components/ui/seperator";
import Heading from "../../components/ui/typography/heading"; import Heading from "../../components/ui/typography/heading";
import Paragraph from "../../components/ui/typography/paragraph"; import Paragraph from "../../components/ui/typography/paragraph";
import BiometicService from "../../services/biometrics"; import BiometricService from "../../services/biometrics";
import { ToastManager, presentSheet } from "../../services/event-manager"; import { ToastManager, presentSheet } from "../../services/event-manager";
import SettingsService from "../../services/settings"; import SettingsService from "../../services/settings";
import { useSettingStore } from "../../stores/use-setting-store"; import { useSettingStore } from "../../stores/use-setting-store";
@@ -119,7 +119,7 @@ const AppLock = () => {
type={appLockMode === item.value ? "secondary" : "transparent"} type={appLockMode === item.value ? "secondary" : "transparent"}
onPress={async () => { onPress={async () => {
if ( if (
!(await BiometicService.isBiometryAvailable()) && !(await BiometricService.isBiometryAvailable()) &&
!useUserStore.getState().user && !useUserStore.getState().user &&
item.value !== modes[0].value && item.value !== modes[0].value &&
!SettingsService.getProperty("appLockHasPasswordSecurity") !SettingsService.getProperty("appLockHasPasswordSecurity")
@@ -139,7 +139,7 @@ const AppLock = () => {
) && ) &&
item.value !== modes[0].value item.value !== modes[0].value
) { ) {
const verified = await BiometicService.validateUser( const verified = await BiometricService.validateUser(
"Verify it's you" "Verify it's you"
); );
if (verified) { if (verified) {

View File

@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { db } from "../../common/database"; import { db } from "../../common/database";
import { validateAppLockPassword } from "../../common/database/encryption"; import { validateAppLockPassword } from "../../common/database/encryption";
import { presentDialog } from "../../components/dialog/functions"; import { presentDialog } from "../../components/dialog/functions";
import BiometicService from "../../services/biometrics"; import BiometricService from "../../services/biometrics";
import { ToastManager } from "../../services/event-manager"; import { ToastManager } from "../../services/event-manager";
import SettingsService from "../../services/settings"; import SettingsService from "../../services/settings";
import { useUserStore } from "../../stores/use-user-store"; import { useUserStore } from "../../stores/use-user-store";
@@ -100,9 +100,9 @@ export async function verifyUserWithApplock() {
} }
}); });
} else { } else {
BiometicService.isBiometryAvailable().then((available) => { BiometricService.isBiometryAvailable().then((available) => {
if (available) { if (available) {
BiometicService.validateUser("Verify it's you").then((verified) => { BiometricService.validateUser("Verify it's you").then((verified) => {
resolve(verified); resolve(verified);
}); });
} else if (useUserStore.getState().user) { } else if (useUserStore.getState().user) {

View File

@@ -38,7 +38,7 @@ import { Update } from "../../components/sheets/update";
import { VaultStatusType, useVaultStatus } from "../../hooks/use-vault-status"; import { VaultStatusType, useVaultStatus } from "../../hooks/use-vault-status";
import { BackgroundSync } from "../../services/background-sync"; import { BackgroundSync } from "../../services/background-sync";
import BackupService from "../../services/backup"; import BackupService from "../../services/backup";
import BiometicService from "../../services/biometrics"; import BiometricService from "../../services/biometrics";
import { import {
ToastManager, ToastManager,
eSendEvent, eSendEvent,
@@ -349,7 +349,7 @@ export const settingsGroups: SettingSection[] = [
await db.user?.logout(); await db.user?.logout();
setLoginMessage(); setLoginMessage();
await PremiumService.setPremiumStatus(); await PremiumService.setPremiumStatus();
await BiometicService.resetCredentials(); await BiometricService.resetCredentials();
MMKV.clearStore(); MMKV.clearStore();
clearAllStores(); clearAllStores();
refreshAllStores(); refreshAllStores();
@@ -394,7 +394,7 @@ export const settingsGroups: SettingSection[] = [
if (verified) { if (verified) {
eSendEvent("settings-loading", true); eSendEvent("settings-loading", true);
await db.user?.deleteUser(value); await db.user?.deleteUser(value);
await BiometicService.resetCredentials(); await BiometricService.resetCredentials();
SettingsService.set({ SettingsService.set({
introCompleted: true introCompleted: true
}); });
@@ -789,7 +789,7 @@ export const settingsGroups: SettingSection[] = [
} }
}, },
{ {
id: "biometic-unlock", id: "biometric-unlock",
type: "switch", type: "switch",
name: "Biometric unlocking", name: "Biometric unlocking",
icon: "fingerprint", icon: "fingerprint",
@@ -859,13 +859,13 @@ export const settingsGroups: SettingSection[] = [
if (!SettingsService.getProperty("appLockEnabled")) { if (!SettingsService.getProperty("appLockEnabled")) {
if ( if (
!SettingsService.getProperty("appLockHasPasswordSecurity") && !SettingsService.getProperty("appLockHasPasswordSecurity") &&
(await BiometicService.isBiometryAvailable()) (await BiometricService.isBiometryAvailable())
) { ) {
SettingsService.setProperty("biometricsAuthEnabled", true); SettingsService.setProperty("biometricsAuthEnabled", true);
} }
if ( if (
!(await BiometicService.isBiometryAvailable()) && !(await BiometricService.isBiometryAvailable()) &&
!SettingsService.getProperty("appLockHasPasswordSecurity") !SettingsService.getProperty("appLockHasPasswordSecurity")
) { ) {
ToastManager.show({ ToastManager.show({

View File

@@ -179,7 +179,7 @@ async function validateUser(title: string, description?: string) {
} }
} }
const BiometicService = { const BiometricService = {
isBiometryAvailable, isBiometryAvailable,
enableFingerprintAuth, enableFingerprintAuth,
isFingerprintAuthEnabled, isFingerprintAuthEnabled,
@@ -190,4 +190,4 @@ const BiometicService = {
validateUser validateUser
}; };
export default BiometicService; export default BiometricService;

View File

@@ -40,7 +40,7 @@ import { basename, dirname, join } from "pathe";
import downloadAttachment from "../common/filesystem/download-attachment"; import downloadAttachment from "../common/filesystem/download-attachment";
import { presentDialog } from "../components/dialog/functions"; import { presentDialog } from "../components/dialog/functions";
import { useSettingStore } from "../stores/use-setting-store"; import { useSettingStore } from "../stores/use-setting-store";
import BiometicService from "./biometrics"; import BiometricService from "./biometrics";
import { ToastManager } from "./event-manager"; import { ToastManager } from "./event-manager";
import { cacheDir } from "../common/filesystem/utils"; import { cacheDir } from "../common/filesystem/utils";
@@ -186,10 +186,10 @@ async function exportAs(
} }
async function unlockVault() { async function unlockVault() {
const biometry = await BiometicService.isBiometryAvailable(); const biometry = await BiometricService.isBiometryAvailable();
const fingerprint = await BiometicService.hasInternetCredentials(); const fingerprint = await BiometricService.hasInternetCredentials();
if (biometry && fingerprint) { if (biometry && fingerprint) {
const credentials = await BiometicService.getCredentials( const credentials = await BiometricService.getCredentials(
"Unlock vault", "Unlock vault",
"Unlock vault to export locked notes" "Unlock vault to export locked notes"
); );