From e8314f91dc556b7ad66f741a809eafdcd849c005 Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Fri, 21 Feb 2025 16:31:30 +0100 Subject: [PATCH] Update credentials list to properly refresh with new vault (#541) --- browser-extensions/chrome/contentScript.ts | 4 -- .../chrome/src/app/context/DbContext.tsx | 22 +----- .../chrome/src/app/pages/CredentialsList.tsx | 70 ++++++++----------- .../chrome/src/app/pages/Unlock.tsx | 5 +- 4 files changed, 32 insertions(+), 69 deletions(-) diff --git a/browser-extensions/chrome/contentScript.ts b/browser-extensions/chrome/contentScript.ts index 85ed2c78c..3ef99931e 100644 --- a/browser-extensions/chrome/contentScript.ts +++ b/browser-extensions/chrome/contentScript.ts @@ -9,15 +9,11 @@ document.addEventListener('focusin', async (e) => { const target = e.target as HTMLInputElement; const textInputTypes = ['text', 'email', 'tel', 'password', 'search', 'url']; - console.log('focusin triggered 1:', target); - if (target.tagName === 'INPUT' && textInputTypes.includes(target.type) && !target.dataset.aliasvaultIgnore) { const formDetector = new FormDetector(document, target); - console.log('focusin triggered 2'); - if (!formDetector.containsLoginForm()) return; injectIcon(target); diff --git a/browser-extensions/chrome/src/app/context/DbContext.tsx b/browser-extensions/chrome/src/app/context/DbContext.tsx index 5fd9986b2..02451d1ea 100644 --- a/browser-extensions/chrome/src/app/context/DbContext.tsx +++ b/browser-extensions/chrome/src/app/context/DbContext.tsx @@ -57,6 +57,7 @@ export const DbProvider: React.FC<{ children: React.ReactNode }> = ({ children } // Initialize the SQLite client. const client = new SqliteClient(); await client.initializeFromBase64(decryptedBlob); + setSqliteClient(client); setDbInitialized(true); setDbAvailable(true); @@ -80,6 +81,7 @@ export const DbProvider: React.FC<{ children: React.ReactNode }> = ({ children } if (response?.vault) { const client = new SqliteClient(); await client.initializeFromBase64(response.vault); + setSqliteClient(client); setDbInitialized(true); setDbAvailable(true); @@ -106,26 +108,6 @@ export const DbProvider: React.FC<{ children: React.ReactNode }> = ({ children } } }, [dbInitialized, checkStoredVault]); - /** - * Add a listener for when the popup becomes visible - */ - useEffect(() : void => { - /** - * Handles visibility state changes of the document. - * Checks and retrieves stored vault data when document becomes visible and database is not initialized. - */ - const handleVisibilityChange = () : void => { - if (document.visibilityState === 'visible' && !dbInitialized) { - checkStoredVault(); - } - }; - - document.addEventListener('visibilitychange', handleVisibilityChange); - return () : void => { - document.removeEventListener('visibilitychange', handleVisibilityChange); - }; - }, [dbInitialized, checkStoredVault]); - /** * Clear database and remove from background worker, called when logging out. */ diff --git a/browser-extensions/chrome/src/app/pages/CredentialsList.tsx b/browser-extensions/chrome/src/app/pages/CredentialsList.tsx index 0e5d3bdc5..00f43bbf0 100644 --- a/browser-extensions/chrome/src/app/pages/CredentialsList.tsx +++ b/browser-extensions/chrome/src/app/pages/CredentialsList.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback, useRef } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { useDb } from '../context/DbContext'; import { Credential } from '../../shared/types/Credential'; import { Buffer } from 'buffer'; @@ -22,7 +22,6 @@ const CredentialsList: React.FC = () => { const navigate = useNavigate(); const { showLoading, hideLoading, setIsInitialLoading } = useLoading(); const authContext = useAuth(); - const isMounted = useRef(false); /** * Loading state with minimum duration for more fluid UX. @@ -45,19 +44,18 @@ const CredentialsList: React.FC = () => { return; } - // If the vault has not been updated on the server, just load existing credentials - if (statusResponse.vaultRevision <= dbContext.vaultRevision) { - try { + try { + // If the vault revision is the same or lower, (re)load existing credentials. + if (statusResponse.vaultRevision <= dbContext.vaultRevision) { const results = dbContext.sqliteClient.getAllCredentials(); setCredentials(results); return; - } catch (err) { - console.error('Error loading credentials:', err); } - } - try { - // Make API call to get latest vault + /** + * If the vault revision is higher, fetch the latest vault and initialize the SQLite context again. + * This will trigger a new credentials list refresh. + */ const vaultResponseJson = await webApi.get('Vault'); const vaultError = webApi.validateVaultResponse(vaultResponseJson); @@ -72,42 +70,11 @@ const CredentialsList: React.FC = () => { // Initialize the SQLite context again with the newly retrieved decrypted blob await dbContext.initializeDatabase(vaultResponseJson, passwordHashBase64); - - // Load credentials - try { - const results = dbContext.sqliteClient.getAllCredentials(); - setCredentials(results); - } catch (err) { - console.error('Error loading credentials:', err); - } } catch (err) { console.error('Refresh error:', err); } }, [dbContext, webApi, authContext, hideLoading]); - /** - * Load the credentials list when the component is mounted (only once). - */ - useEffect(() => { - if (isMounted.current) { - return; - } - isMounted.current = true; - - /** - * Asynchronously load the credentials list. - */ - const loadInitialData = async () : Promise => { - setIsLoading(true); - await onRefresh(); - setIsLoading(false); - - // Hide the global app initial loading state after the credentials list is loaded. - setIsInitialLoading(false); - }; - loadInitialData(); - }, [onRefresh, setIsLoading, setIsInitialLoading]); - /** * Manually refresh the credentials list. */ @@ -117,6 +84,27 @@ const CredentialsList: React.FC = () => { hideLoading(); }; + /** + * Load credentials list on mount and on sqlite client change. + */ + useEffect(() => { + /** + * Refresh credentials list when sqlite client is available. + */ + const refreshCredentials = async () : Promise => { + if (dbContext?.sqliteClient) { + setIsLoading(true); + await onRefresh(); + setIsLoading(false); + + // Hide the global app initial loading state after the credentials list is loaded. + setIsInitialLoading(false); + } + }; + + refreshCredentials(); + }, [dbContext?.sqliteClient, onRefresh, setIsLoading, setIsInitialLoading]); + // Add this function to filter credentials const filteredCredentials = credentials.filter(cred => { const searchLower = searchTerm.toLowerCase(); diff --git a/browser-extensions/chrome/src/app/pages/Unlock.tsx b/browser-extensions/chrome/src/app/pages/Unlock.tsx index cb4eba8d7..1d1972d11 100644 --- a/browser-extensions/chrome/src/app/pages/Unlock.tsx +++ b/browser-extensions/chrome/src/app/pages/Unlock.tsx @@ -104,10 +104,7 @@ const Unlock: React.FC = () => { return (
-
- User avatar -

{authContext.username}

-
+

{authContext.username}

Enter your master password to unlock your vault.