Files
soconnor 32ffe782ea Fix Live Activity lock screen rendering and polish multi-account auth.
Flatten widget layouts and use system colors so banner and expanded regions render on vibrant lock screens; migrate auth sessions per account to prevent double sign-in; scope app lock PIN to accounts; default clock description to "Clock In"; add architecture docs and deferred form validation on auth screens.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-18 01:23:36 -04:00

80 lines
2.7 KiB
TypeScript

import * as SecureStore from "expo-secure-store";
import { normalizeSecureStoreKey } from "@/lib/secure-store-keys";
function lockKey(accountId: string, field: "enabled" | "pin" | "biometric") {
return normalizeSecureStoreKey(`beenvoice.app-lock.${accountId}.${field}`);
}
const LEGACY_ENABLED_KEY = "beenvoice_app_lock_enabled";
const LEGACY_PIN_KEY = "beenvoice_app_lock_pin";
const LEGACY_BIOMETRIC_KEY = "beenvoice_app_lock_biometric";
async function migrateLegacyLockIfNeeded(accountId: string): Promise<void> {
const [legacyEnabled, legacyPin, legacyBiometric, accountEnabled] = await Promise.all([
SecureStore.getItemAsync(LEGACY_ENABLED_KEY),
SecureStore.getItemAsync(LEGACY_PIN_KEY),
SecureStore.getItemAsync(LEGACY_BIOMETRIC_KEY),
SecureStore.getItemAsync(lockKey(accountId, "enabled")),
]);
if (accountEnabled != null || legacyEnabled !== "1") return;
if (legacyPin) {
await setStoredPin(accountId, legacyPin);
}
await setAppLockEnabled(accountId, true);
if (legacyBiometric === "1") {
await setBiometricEnabled(accountId, true);
}
await Promise.all([
SecureStore.deleteItemAsync(LEGACY_ENABLED_KEY),
SecureStore.deleteItemAsync(LEGACY_PIN_KEY),
SecureStore.deleteItemAsync(LEGACY_BIOMETRIC_KEY),
]);
}
export async function getAppLockEnabled(accountId: string): Promise<boolean> {
await migrateLegacyLockIfNeeded(accountId);
const value = await SecureStore.getItemAsync(lockKey(accountId, "enabled"));
return value === "1";
}
export async function setAppLockEnabled(accountId: string, enabled: boolean): Promise<void> {
if (enabled) {
await SecureStore.setItemAsync(lockKey(accountId, "enabled"), "1");
} else {
await SecureStore.deleteItemAsync(lockKey(accountId, "enabled"));
}
}
export async function getStoredPin(accountId: string): Promise<string | null> {
return SecureStore.getItemAsync(lockKey(accountId, "pin"));
}
export async function setStoredPin(accountId: string, pin: string): Promise<void> {
await SecureStore.setItemAsync(lockKey(accountId, "pin"), pin);
}
export async function clearStoredPin(accountId: string): Promise<void> {
await SecureStore.deleteItemAsync(lockKey(accountId, "pin"));
}
export async function getBiometricEnabled(accountId: string): Promise<boolean> {
const value = await SecureStore.getItemAsync(lockKey(accountId, "biometric"));
return value === "1";
}
export async function setBiometricEnabled(accountId: string, enabled: boolean): Promise<void> {
if (enabled) {
await SecureStore.setItemAsync(lockKey(accountId, "biometric"), "1");
} else {
await SecureStore.deleteItemAsync(lockKey(accountId, "biometric"));
}
}
export function isValidPin(pin: string): boolean {
return /^\d{4,6}$/.test(pin);
}