77 lines
2.5 KiB
JavaScript
77 lines
2.5 KiB
JavaScript
import * as SecureStore from "expo-secure-store";
|
|
import { createLogger } from "~/lib/logger";
|
|
import { SYSTEM_SCOPES } from "~/lib/logger/scopes";
|
|
|
|
const storageLogger = createLogger({
|
|
module: SYSTEM_SCOPES.STORAGE,
|
|
feature: "secure-store",
|
|
});
|
|
|
|
const secureStoreOptions = {
|
|
keychainAccessible: SecureStore.AFTER_FIRST_UNLOCK,
|
|
};
|
|
|
|
/**
|
|
* Wrapper for SecureStore that uses AFTER_FIRST_UNLOCK accessibility
|
|
* to prevent "User interaction is not allowed" errors on iOS
|
|
* see also https://github.com/expo/expo/issues/23924
|
|
*/
|
|
export const secureStore = {
|
|
getItemAsync: async (key) => {
|
|
storageLogger.debug("Retrieving secure item", { key });
|
|
const value = await SecureStore.getItemAsync(key, secureStoreOptions);
|
|
storageLogger.debug("Secure item retrieval result", {
|
|
key,
|
|
hasValue: !!value,
|
|
});
|
|
return value;
|
|
},
|
|
setItemAsync: async (key, value) => {
|
|
storageLogger.debug("Setting secure item", { key });
|
|
await SecureStore.setItemAsync(key, value, secureStoreOptions);
|
|
storageLogger.debug("Secure item set successfully", { key });
|
|
},
|
|
deleteItemAsync: async (key) => {
|
|
storageLogger.debug("Deleting secure item", { key });
|
|
await SecureStore.deleteItemAsync(key, secureStoreOptions);
|
|
storageLogger.debug("Secure item deleted successfully", { key });
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Migrates a key from the old accessibility setting to the new one
|
|
*/
|
|
export const migrateKey = async (oldKey, newKey = oldKey) => {
|
|
storageLogger.info("Starting secure store key migration", { oldKey, newKey });
|
|
try {
|
|
// Try to get value with old accessibility setting
|
|
const value = await SecureStore.getItemAsync(oldKey);
|
|
if (value) {
|
|
storageLogger.debug("Found value with old accessibility setting", {
|
|
oldKey,
|
|
});
|
|
// Store with new accessibility setting
|
|
await secureStore.setItemAsync(newKey, value);
|
|
storageLogger.debug("Stored value with new accessibility setting", {
|
|
newKey,
|
|
});
|
|
// Clean up old key if the new key is different
|
|
if (oldKey !== newKey) {
|
|
await SecureStore.deleteItemAsync(oldKey);
|
|
storageLogger.debug("Cleaned up old key", { oldKey });
|
|
}
|
|
storageLogger.info("Key migration completed successfully", {
|
|
oldKey,
|
|
newKey,
|
|
});
|
|
return value;
|
|
}
|
|
} catch (error) {
|
|
storageLogger.error("Failed to migrate secure store key", {
|
|
oldKey,
|
|
error: error.message,
|
|
stack: error.stack,
|
|
});
|
|
}
|
|
return null;
|
|
};
|