...
This commit is contained in:
321
www/js/index.js
321
www/js/index.js
@@ -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}`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user