mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-03-20 07:39:07 -04:00
Add notice when vault is locked (#541)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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 && (
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user