diff --git a/web/database/database-module-provider.js b/web/database/database-module-provider.js --- a/web/database/database-module-provider.js +++ b/web/database/database-module-provider.js @@ -68,7 +68,11 @@ })(); } - userLoggedIn(currentLoggedInUserID: ?string) { + initDBForLoggedInUser(currentLoggedInUserID: ?string) { + if (this.status === databaseStatuses.initSuccess) { + return; + } + if ( this.status === databaseStatuses.notSupported && isSQLiteSupported(currentLoggedInUserID) @@ -77,6 +81,20 @@ } } + async clearSensitiveData(): Promise { + this.status = databaseStatuses.notSupported; + await this.workerProxy.scheduleOnWorker({ + type: workerRequestMessageTypes.CLEAR_SENSITIVE_DATA, + }); + } + + async isDatabaseSupported(): Promise { + if (this.status === databaseStatuses.initInProgress) { + await this.initPromise; + } + return this.status === databaseStatuses.initSuccess; + } + async schedule( payload: WorkerRequestMessage, ): Promise { diff --git a/web/database/sqlite-data-handler.js b/web/database/sqlite-data-handler.js new file mode 100644 --- /dev/null +++ b/web/database/sqlite-data-handler.js @@ -0,0 +1,62 @@ +// @flow + +import * as React from 'react'; + +import { databaseModule } from './database-module-provider.js'; +import { useSelector } from '../redux/redux-utils.js'; +import { workerRequestMessageTypes } from '../types/worker-types.js'; + +function SQLiteDataHandler(): React.Node { + const rehydrateConcluded = useSelector( + state => !!(state._persist && state._persist.rehydrated), + ); + const currentLoggedInUserID = useSelector(state => + state.currentUserInfo?.anonymous ? undefined : state.currentUserInfo?.id, + ); + + const handleSensitiveData = React.useCallback(async () => { + try { + const currentUserData = await databaseModule.schedule({ + type: workerRequestMessageTypes.GET_CURRENT_USER_ID, + }); + const currentDBUserID = currentUserData?.userID; + + if (currentDBUserID && currentDBUserID !== currentLoggedInUserID) { + await databaseModule.clearSensitiveData(); + } + if ( + currentLoggedInUserID && + (currentDBUserID || currentDBUserID !== currentLoggedInUserID) + ) { + await databaseModule.schedule({ + type: workerRequestMessageTypes.SET_CURRENT_USER_ID, + userID: currentLoggedInUserID, + }); + } + } catch (error) { + console.error(error); + throw error; + } + }, [currentLoggedInUserID]); + + React.useEffect(() => { + (async () => { + if (currentLoggedInUserID) { + await databaseModule.initDBForLoggedInUser(currentLoggedInUserID); + } + if (!rehydrateConcluded) { + return; + } + + const isSupported = await databaseModule.isDatabaseSupported(); + if (!isSupported) { + return; + } + await handleSensitiveData(); + })(); + }, [currentLoggedInUserID, handleSensitiveData, rehydrateConcluded]); + + return null; +} + +export { SQLiteDataHandler }; diff --git a/web/database/worker/db-worker.js b/web/database/worker/db-worker.js --- a/web/database/worker/db-worker.js +++ b/web/database/worker/db-worker.js @@ -173,6 +173,13 @@ if (message.type === workerRequestMessageTypes.INIT) { await initDatabase(message.sqljsFilePath, message.sqljsFilename); return undefined; + } else if (message.type === workerRequestMessageTypes.CLEAR_SENSITIVE_DATA) { + encryptionKey = null; + if (sqliteDb) { + sqliteDb.close(); + } + await localforage.clear(); + return undefined; } if (!sqliteDb) { diff --git a/web/root.js b/web/root.js --- a/web/root.js +++ b/web/root.js @@ -14,6 +14,7 @@ import { isDev } from 'lib/utils/dev-utils.js'; import App from './app.react.js'; +import { SQLiteDataHandler } from './database/sqlite-data-handler.js'; import ErrorBoundary from './error-boundary.react.js'; import Loading from './loading.react.js'; import { reducer } from './redux/redux-setup.js'; @@ -70,6 +71,7 @@ + diff --git a/web/types/worker-types.js b/web/types/worker-types.js --- a/web/types/worker-types.js +++ b/web/types/worker-types.js @@ -17,6 +17,7 @@ GET_PERSIST_STORAGE_ITEM: 7, SET_PERSIST_STORAGE_ITEM: 8, REMOVE_PERSIST_STORAGE_ITEM: 9, + CLEAR_SENSITIVE_DATA: 10, }); export const workerWriteRequests: $ReadOnlyArray = [ @@ -75,6 +76,10 @@ +key: string, }; +export type ClearSensitiveDataRequestMessage = { + +type: 10, +}; + export type WorkerRequestMessage = | PingWorkerRequestMessage | InitWorkerRequestMessage @@ -85,7 +90,8 @@ | GetCurrentUserIDRequestMessage | GetPersistStorageItemRequestMessage | SetPersistStorageItemRequestMessage - | RemovePersistStorageItemRequestMessage; + | RemovePersistStorageItemRequestMessage + | ClearSensitiveDataRequestMessage; export type WorkerRequestProxyMessage = { +id: number,