This commit is contained in:
2025-04-21 13:02:32 +02:00
parent 2cf31905b0
commit c47f67b901
2 changed files with 758 additions and 70 deletions

View File

@@ -70,34 +70,181 @@ function clearAutoLogout() {
}
}
// LocalStorage functions for key spaces
const STORAGE_PREFIX = 'crypto_space_';
// IndexedDB setup and functions
const DB_NAME = 'CryptoSpaceDB';
const DB_VERSION = 1;
const STORE_NAME = 'keySpaces';
// Save encrypted space to localStorage
function saveSpaceToStorage(spaceName, encryptedData) {
localStorage.setItem(`${STORAGE_PREFIX}${spaceName}`, encryptedData);
// Initialize the database
function initDatabase() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(DB_NAME, DB_VERSION);
request.onerror = (event) => {
console.error('Error opening database:', event.target.error);
reject('Error opening database: ' + event.target.error);
};
request.onsuccess = (event) => {
const db = event.target.result;
resolve(db);
};
request.onupgradeneeded = (event) => {
const db = event.target.result;
// Create object store for key spaces if it doesn't exist
if (!db.objectStoreNames.contains(STORE_NAME)) {
const store = db.createObjectStore(STORE_NAME, { keyPath: 'name' });
store.createIndex('name', 'name', { unique: true });
store.createIndex('lastAccessed', 'lastAccessed', { unique: false });
}
};
});
}
// Get encrypted space from localStorage
function getSpaceFromStorage(spaceName) {
return localStorage.getItem(`${STORAGE_PREFIX}${spaceName}`);
// Get database connection
function getDB() {
return initDatabase();
}
// List all spaces in localStorage
function listSpacesFromStorage() {
const spaces = [];
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith(STORAGE_PREFIX)) {
spaces.push(key.substring(STORAGE_PREFIX.length));
}
}
return spaces;
// Save encrypted space to IndexedDB
async function saveSpaceToStorage(spaceName, encryptedData) {
const db = await getDB();
return new Promise((resolve, reject) => {
const transaction = db.transaction([STORE_NAME], 'readwrite');
const store = transaction.objectStore(STORE_NAME);
const space = {
name: spaceName,
encryptedData: encryptedData,
created: new Date(),
lastAccessed: new Date()
};
const request = store.put(space);
request.onsuccess = () => {
resolve();
};
request.onerror = (event) => {
console.error('Error saving space:', event.target.error);
reject('Error saving space: ' + event.target.error);
};
transaction.oncomplete = () => {
db.close();
};
});
}
// Remove space from localStorage
function removeSpaceFromStorage(spaceName) {
localStorage.removeItem(`${STORAGE_PREFIX}${spaceName}`);
// Get encrypted space from IndexedDB
async function getSpaceFromStorage(spaceName) {
const db = await getDB();
return new Promise((resolve, reject) => {
const transaction = db.transaction([STORE_NAME], 'readonly');
const store = transaction.objectStore(STORE_NAME);
const request = store.get(spaceName);
request.onsuccess = (event) => {
const space = event.target.result;
if (space) {
// Update last accessed timestamp
updateLastAccessed(spaceName).catch(console.error);
resolve(space.encryptedData);
} else {
resolve(null);
}
};
request.onerror = (event) => {
console.error('Error retrieving space:', event.target.error);
reject('Error retrieving space: ' + event.target.error);
};
transaction.oncomplete = () => {
db.close();
};
});
}
// Update last accessed timestamp
async function updateLastAccessed(spaceName) {
const db = await getDB();
return new Promise((resolve, reject) => {
const transaction = db.transaction([STORE_NAME], 'readwrite');
const store = transaction.objectStore(STORE_NAME);
const request = store.get(spaceName);
request.onsuccess = (event) => {
const space = event.target.result;
if (space) {
space.lastAccessed = new Date();
store.put(space);
resolve();
} else {
resolve();
}
};
transaction.oncomplete = () => {
db.close();
};
});
}
// List all spaces in IndexedDB
async function listSpacesFromStorage() {
const db = await getDB();
return new Promise((resolve, reject) => {
const transaction = db.transaction([STORE_NAME], 'readonly');
const store = transaction.objectStore(STORE_NAME);
const request = store.openCursor();
const spaces = [];
request.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
spaces.push(cursor.value.name);
cursor.continue();
} else {
resolve(spaces);
}
};
request.onerror = (event) => {
console.error('Error listing spaces:', event.target.error);
reject('Error listing spaces: ' + event.target.error);
};
transaction.oncomplete = () => {
db.close();
};
});
}
// Remove space from IndexedDB
async function removeSpaceFromStorage(spaceName) {
const db = await getDB();
return new Promise((resolve, reject) => {
const transaction = db.transaction([STORE_NAME], 'readwrite');
const store = transaction.objectStore(STORE_NAME);
const request = store.delete(spaceName);
request.onsuccess = () => {
resolve();
};
request.onerror = (event) => {
console.error('Error removing space:', event.target.error);
reject('Error removing space: ' + event.target.error);
};
transaction.oncomplete = () => {
db.close();
};
});
}
// Session state
@@ -131,7 +278,7 @@ function updateLoginUI() {
}
// Update the spaces dropdown list
function updateSpacesList() {
async function updateSpacesList() {
const spacesList = document.getElementById('space-list');
// Clear existing options
@@ -139,16 +286,20 @@ function updateSpacesList() {
spacesList.remove(1);
}
// Get spaces list
const spaces = listSpacesFromStorage();
// Add options for each space
spaces.forEach(spaceName => {
const option = document.createElement('option');
option.value = spaceName;
option.textContent = spaceName;
spacesList.appendChild(option);
});
try {
// Get spaces list
const spaces = await listSpacesFromStorage();
// Add options for each space
spaces.forEach(spaceName => {
const option = document.createElement('option');
option.value = spaceName;
option.textContent = spaceName;
spacesList.appendChild(option);
});
} catch (e) {
console.error('Error updating spaces list:', e);
}
}
// Login to a space
@@ -162,8 +313,11 @@ async function performLogin() {
}
try {
// Get encrypted space from localStorage
const encryptedSpace = getSpaceFromStorage(spaceName);
// Show loading state
document.getElementById('space-result').textContent = 'Loading...';
// Get encrypted space from IndexedDB
const encryptedSpace = await getSpaceFromStorage(spaceName);
if (!encryptedSpace) {
document.getElementById('space-result').textContent = `Space "${spaceName}" not found`;
return;
@@ -189,6 +343,7 @@ async function performLogin() {
document.getElementById('space-result').textContent = `Error logging in: ${result}`;
}
} catch (e) {
console.error('Login error:', e);
document.getElementById('space-result').textContent = `Error: ${e}`;
}
}
@@ -203,19 +358,23 @@ async function performCreateSpace() {
return;
}
// Check if space already exists
if (getSpaceFromStorage(spaceName)) {
document.getElementById('space-result').textContent = `Space "${spaceName}" already exists`;
return;
}
try {
// Show loading state
document.getElementById('space-result').textContent = 'Loading...';
// Check if space already exists
const existingSpace = await getSpaceFromStorage(spaceName);
if (existingSpace) {
document.getElementById('space-result').textContent = `Space "${spaceName}" already exists`;
return;
}
// Create new space
const result = create_key_space(spaceName);
if (result === 0) {
// Encrypt and save the space
const encryptedSpace = encrypt_key_space(password);
saveSpaceToStorage(spaceName, encryptedSpace);
await saveSpaceToStorage(spaceName, encryptedSpace);
isLoggedIn = true;
currentSpace = spaceName;
@@ -234,6 +393,7 @@ async function performCreateSpace() {
document.getElementById('space-result').textContent = `Error creating space: ${result}`;
}
} catch (e) {
console.error('Error creating space:', e);
document.getElementById('space-result').textContent = `Error: ${e}`;
}
}
@@ -329,7 +489,7 @@ async function performCreateKeypair() {
// Display public key
displaySelectedKeypairPublicKey();
// Save the updated space to localStorage
// Save the updated space to IndexedDB
saveCurrentSpace();
} else {
document.getElementById('keypair-management-result').textContent = `Error creating keypair: ${result}`;
@@ -409,8 +569,8 @@ function displaySelectedKeypairPublicKey() {
}
}
// Save the current space to localStorage
function saveCurrentSpace() {
// Save the current space to IndexedDB
async function saveCurrentSpace() {
if (!isLoggedIn || !currentSpace) return;
try {
@@ -424,30 +584,37 @@ function saveCurrentSpace() {
}
const encryptedSpace = encrypt_key_space(password);
saveSpaceToStorage(currentSpace, encryptedSpace);
await saveSpaceToStorage(currentSpace, encryptedSpace);
} catch (e) {
console.error('Error saving space:', e);
alert('Error saving space: ' + e);
}
}
// Delete a space from localStorage
function deleteSpace(spaceName) {
// Delete a space from IndexedDB
async function deleteSpace(spaceName) {
if (!spaceName) return false;
// Check if space exists
if (!getSpaceFromStorage(spaceName)) {
try {
// Check if space exists
const existingSpace = await getSpaceFromStorage(spaceName);
if (!existingSpace) {
return false;
}
// Remove from IndexedDB
await removeSpaceFromStorage(spaceName);
// If this was the current space, logout
if (isLoggedIn && currentSpace === spaceName) {
performLogout();
}
return true;
} catch (e) {
console.error('Error deleting space:', e);
return false;
}
// Remove from localStorage
removeSpaceFromStorage(spaceName);
// If this was the current space, logout
if (isLoggedIn && currentSpace === spaceName) {
performLogout();
}
return true;
}
async function run() {
@@ -460,17 +627,24 @@ async function run() {
document.getElementById('login-button').addEventListener('click', performLogin);
document.getElementById('create-space-button').addEventListener('click', performCreateSpace);
document.getElementById('logout-button').addEventListener('click', performLogout);
document.getElementById('delete-space-button').addEventListener('click', () => {
document.getElementById('delete-space-button').addEventListener('click', async () => {
if (confirm(`Are you sure you want to delete the space "${currentSpace}"? This action cannot be undone.`)) {
if (deleteSpace(currentSpace)) {
document.getElementById('space-result').textContent = `Space "${currentSpace}" deleted successfully`;
} else {
document.getElementById('space-result').textContent = `Error deleting space "${currentSpace}"`;
document.getElementById('space-result').textContent = 'Deleting...';
try {
const result = await deleteSpace(currentSpace);
if (result) {
document.getElementById('space-result').textContent = `Space "${currentSpace}" deleted successfully`;
} else {
document.getElementById('space-result').textContent = `Error deleting space "${currentSpace}"`;
}
} catch (e) {
console.error('Error during space deletion:', e);
document.getElementById('space-result').textContent = `Error: ${e}`;
}
}
});
document.getElementById('delete-selected-space-button').addEventListener('click', () => {
document.getElementById('delete-selected-space-button').addEventListener('click', async () => {
const selectedSpace = document.getElementById('space-list').value;
if (!selectedSpace) {
document.getElementById('space-result').textContent = 'Please select a space to delete';
@@ -478,11 +652,18 @@ async function run() {
}
if (confirm(`Are you sure you want to delete the space "${selectedSpace}"? This action cannot be undone.`)) {
if (deleteSpace(selectedSpace)) {
document.getElementById('space-result').textContent = `Space "${selectedSpace}" deleted successfully`;
updateSpacesList();
} else {
document.getElementById('space-result').textContent = `Error deleting space "${selectedSpace}"`;
document.getElementById('space-result').textContent = 'Deleting...';
try {
const result = await deleteSpace(selectedSpace);
if (result) {
document.getElementById('space-result').textContent = `Space "${selectedSpace}" deleted successfully`;
await updateSpacesList();
} else {
document.getElementById('space-result').textContent = `Error deleting space "${selectedSpace}"`;
}
} catch (e) {
console.error('Error during space deletion:', e);
document.getElementById('space-result').textContent = `Error: ${e}`;
}
}
});