Add notice when vault is locked (#541)

This commit is contained in:
Leendert de Borst
2025-01-28 20:17:22 +01:00
parent 6298cff1a3
commit 57cbedf701
5 changed files with 81 additions and 11 deletions

View File

@@ -81,14 +81,14 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
case 'GET_CREDENTIALS_FOR_URL': {
if (!vaultState.derivedKey) {
sendResponse({ credentials: [] });
sendResponse({ credentials: [], status: 'LOCKED' });
return;
}
chrome.storage.session.get(['encryptedVault'], async (result) => {
try {
if (!result.encryptedVault) {
sendResponse({ credentials: [] });
sendResponse({ credentials: [], status: 'LOCKED' });
return;
}
@@ -97,11 +97,9 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
vaultState.derivedKey!
);
// Initialize SQLite client
// Initialize SQLite client and get credentials.
const sqliteClient = new SqliteClient();
await sqliteClient.initializeFromBase64(decryptedVault);
// Query credentials with their related service information
const credentials = sqliteClient.getAllCredentials();
// Filter credentials that match the current domain
@@ -123,7 +121,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
sendResponse({ credentials: credentials });
} catch (error) {
console.error('Error getting credentials:', error);
sendResponse({ credentials: [] });
sendResponse({ credentials: [], status: 'LOCKED', error: 'Failed to get credentials' });
}
});
break;

View File

@@ -1,6 +1,11 @@
import { detectForms } from './utils/FormDetector';
import { Credential } from './types/Credential';
interface CredentialResponse {
status: 'OK' | 'LOCKED';
credentials?: Credential[];
}
const placeholderBase64 = 'UklGRjoEAABXRUJQVlA4IC4EAAAwFwCdASqAAIAAPpFCm0olo6Ihp5IraLASCWUA0eb/0s56RrLtCnYfLPiBshdXWMx8j1Ez65f169iA4xUDBTEV6ylMQeCIj2b7RngGi7gKZ9WjKdSoy9R8JcgOmjCMlDmLG20KhNo/i/Dc/Ah5GAvGfm8kfniV3AkR6fxN6eKwjDc6xrDgSfS48G5uGV6WzQt24YAVlLSK9BMwndzfHnePK1KFchFrL7O3ulB8cGNCeomu4o+l0SrS/JKblJ4WTzj0DAD++lCUEouSfgRKdiV2TiYCD+H+l3tANKSPQFPQuzi7rbvxqGeRmXB9kDwURaoSTTpYjA9REMUi9uA6aV7PWtBNXgUzMLowYMZeos6Xvyhb34GmufswMHA5ZyYpxzjTphOak4ZjNOiz8aScO5ygiTx99SqwX/uL+HSeVOSraHw8IymrMwm+jLxqN8BS8dGcItLlm/ioulqH2j4V8glDgSut+ExkxiD7m8TGPrrjCQNJbRDzpOFsyCyfBZupvp8QjGKW2KGziSZeIWes4aTB9tRmeEBhnUrmTDZQuXcc67Fg82KHrSfaeeOEq6jjuUjQ8wUnzM4Zz3dhrwSyslVz/WvnKqYkr4V/TTXPFF5EjF4rM1bHZ8bK63EfTnK41+n3n4gEFoYP4mXkNH0hntnYcdTqiE7Gn+q0BpRRxnkpBSZlA6Wa70jpW0FGqkw5e591A5/H+OV+60WAo+4Mi+NlsKrvLZ9EiVaPnoEFZlJQx1fA777AJ2MjXJ4KSsrWDWJi1lE8yPs8V6XvcC0chDTYt8456sKXAagCZyY+fzQriFMaddXyKQdG8qBqcdYjAsiIcjzaRFBBoOK9sU+sFY7N6B6+xtrlu3c37rQKkI3O2EoiJOris54EjJ5OFuumA0M6riNUuBf/MEPFBVx1JRcUEs+upEBsCnwYski7FT3TTqHrx7v5AjgFN97xhPTkmVpu6sxRnWBi1fxIRp8eWZeFM6mUcGgVk1WeVb1yhdV9hoMo2TsNEPE0tHo/wvuSJSzbZo7wibeXM9v/rRfKcx7X93rfiXVnyQ9f/5CaAQ4lxedPp/6uzLtOS4FyL0bCNeZ6L5w+AiuyWCTDFIYaUzhwfG+/YTQpWyeZCdQIKzhV+3GeXI2cxoP0ER/DlOKymf1gm+zRU3sqf1lBVQ0y+mK/Awl9bS3uaaQmI0FUyUwHUKP7PKuXnO+LcwDv4OfPT6hph8smc1EtMe5ib/apar/qZ9dyaEaElALJ1KKxnHziuvVl8atk1fINSQh7OtXDyqbPw9o/nGIpTnv5iFmwmWJLis2oyEgPkJqyx0vYI8rjkVEzKc8eQavAJBYSpjMwM193Swt+yJyjvaGYWPnqExxKiNarpB2WSO7soCAZXhS1uEYHryrK47BH6W1dRiruqT0xpLih3MXiwU3VDwAAAA==';
// Listen for input field focus
@@ -19,10 +24,18 @@ function showCredentialPopup(input: HTMLInputElement) : void {
if (!forms.length) return;
// Request credentials from background script
chrome.runtime.sendMessage({ type: 'GET_CREDENTIALS_FOR_URL', url: window.location.href }, (response) => {
if (!response.credentials?.length) return;
chrome.runtime.sendMessage({ type: 'GET_CREDENTIALS_FOR_URL', url: window.location.href }, (response: CredentialResponse) => {
switch (response.status) {
case 'OK':
if (response.credentials?.length) {
createPopup(input, response.credentials);
}
break;
createPopup(input, response.credentials);
case 'LOCKED':
createStatusPopup(input, 'AliasVault is locked, please login (again).');
break;
}
});
}
@@ -126,6 +139,62 @@ function createPopup(input: HTMLInputElement, credentials: Credential[]) : void
document.body.appendChild(popup);
}
/**
* Create status popup. TODO: refactor to use same popup basic structure for all popup types.
*/
function createStatusPopup(input: HTMLInputElement, message: string): void {
// Remove existing popup if any
removeExistingPopup();
const popup = document.createElement('div');
popup.id = 'aliasvault-credential-popup';
// Get input width
const inputWidth = input.offsetWidth;
// Set popup width to match input width, with min/max constraints
const popupWidth = Math.max(250, Math.min(960, inputWidth));
popup.style.cssText = `
position: absolute;
z-index: 999999;
background: white;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
padding: 12px 16px;
width: ${popupWidth}px;
`;
// Add message
const messageElement = document.createElement('div');
messageElement.style.cssText = `
color: #666;
font-size: 14px;
`;
messageElement.textContent = message;
popup.appendChild(messageElement);
// Position popup below input
const rect = input.getBoundingClientRect();
popup.style.top = `${rect.bottom + window.scrollY + 2}px`;
popup.style.left = `${rect.left + window.scrollX}px`;
// Add click outside handler
const handleClickOutside = (event: MouseEvent): void => {
if (!popup.contains(event.target as Node)) {
removeExistingPopup();
document.removeEventListener('mousedown', handleClickOutside);
}
};
setTimeout(() => {
document.addEventListener('mousedown', handleClickOutside);
}, 100);
document.body.appendChild(popup);
}
/**
* Remove existing popup
*/

View File

@@ -82,6 +82,9 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
* Logout
*/
const logout = async () : Promise<void> => {
// Clear vault in background worker.
await chrome.runtime.sendMessage({ type: 'CLEAR_VAULT' });
await Promise.all([
localStorage.removeItem('username'),
localStorage.removeItem('accessToken'),

View File

@@ -83,7 +83,7 @@ const Unlock: React.FC = () => {
</div>
<p className="text-base text-gray-500 dark:text-gray-200 mb-6">
Enter your master password to unlock your database.
Enter your master password to unlock your vault.
</p>
{error && (

View File

@@ -48,7 +48,7 @@ else
else
{
<p class="text-base font-normal text-gray-500 dark:text-gray-400 mb-4">
Enter your master password to unlock your database.
Enter your master password to unlock your vault.
</p>
<EditForm Model="_unlockModel" OnValidSubmit="UnlockSubmit" class="mt-8 space-y-6">