99 lines
2.7 KiB
JavaScript
99 lines
2.7 KiB
JavaScript
const DB_NAME = 'duplicati-browser-secrets';
|
|
const STORE_NAME = 'source-secrets';
|
|
const DB_VERSION = 1;
|
|
const GLOBAL_SOURCE_ID = '__global_defaults__';
|
|
|
|
function openDatabase() {
|
|
return new Promise((resolve, reject) => {
|
|
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
|
|
request.onerror = () => reject(request.error ?? new Error('Failed to open IndexedDB.'));
|
|
request.onupgradeneeded = () => {
|
|
const database = request.result;
|
|
if (!database.objectStoreNames.contains(STORE_NAME)) {
|
|
database.createObjectStore(STORE_NAME, { keyPath: 'sourceId' });
|
|
}
|
|
};
|
|
request.onsuccess = () => resolve(request.result);
|
|
});
|
|
}
|
|
|
|
async function withStore(mode, callback) {
|
|
const database = await openDatabase();
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = database.transaction(STORE_NAME, mode);
|
|
const store = transaction.objectStore(STORE_NAME);
|
|
|
|
let callbackResult;
|
|
try {
|
|
callbackResult = callback(store);
|
|
} catch (error) {
|
|
transaction.abort();
|
|
database.close();
|
|
reject(error);
|
|
return;
|
|
}
|
|
|
|
transaction.onerror = () => {
|
|
database.close();
|
|
reject(transaction.error ?? new Error('IndexedDB transaction failed.'));
|
|
};
|
|
|
|
transaction.oncomplete = () => {
|
|
database.close();
|
|
resolve(callbackResult);
|
|
};
|
|
});
|
|
}
|
|
|
|
export async function loadClientSecrets(sourceId) {
|
|
const database = await openDatabase();
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = database.transaction(STORE_NAME, 'readonly');
|
|
const store = transaction.objectStore(STORE_NAME);
|
|
const request = store.get(sourceId);
|
|
|
|
request.onerror = () => {
|
|
database.close();
|
|
reject(request.error ?? new Error('Failed to load browser secrets.'));
|
|
};
|
|
|
|
request.onsuccess = () => {
|
|
database.close();
|
|
resolve(request.result ?? null);
|
|
};
|
|
});
|
|
}
|
|
|
|
export async function loadGlobalClientSecrets() {
|
|
return loadClientSecrets(GLOBAL_SOURCE_ID);
|
|
}
|
|
|
|
export async function saveClientSecrets(sourceId, secrets) {
|
|
const record = {
|
|
sourceId,
|
|
webdavBaseUrl: secrets.webdavBaseUrl,
|
|
authMode: secrets.authMode,
|
|
username: secrets.username,
|
|
password: secrets.password,
|
|
passphrase: secrets.passphrase,
|
|
updatedAt: new Date().toISOString()
|
|
};
|
|
|
|
return withStore('readwrite', (store) => store.put(record));
|
|
}
|
|
|
|
export async function saveGlobalClientSecrets(secrets) {
|
|
return saveClientSecrets(GLOBAL_SOURCE_ID, secrets);
|
|
}
|
|
|
|
export async function removeClientSecrets(sourceId) {
|
|
return withStore('readwrite', (store) => store.delete(sourceId));
|
|
}
|
|
|
|
export async function removeGlobalClientSecrets() {
|
|
return removeClientSecrets(GLOBAL_SOURCE_ID);
|
|
}
|