116 lines
4.5 KiB
JavaScript
116 lines
4.5 KiB
JavaScript
// Generated, do not edit. sha256:8e7f997881d1fd01e18e1023544e1df65cb2a48e77ba25495de5fe5ba3785bef
|
|
import { setAppSetting } from '../app-settings.js';
|
|
import { t } from '../i18n/index.js';
|
|
import { serverFoutTekst } from '../data/_rpc.js';
|
|
import * as dialog from '../ui/dialog.js';
|
|
|
|
export async function backupDb() {
|
|
const res = await dialog.form({
|
|
title: t('dbfile.backup'),
|
|
fields: [{ key: 'w1', label: t('dbfile.backupPass'), type: 'password' },
|
|
{ key: 'w2', label: t('dbfile.backupPassAgain'), type: 'password' }],
|
|
confirmLabel: t('dbfile.backupConfirm'),
|
|
});
|
|
if (!res) return false;
|
|
if (res.w1 !== res.w2) { dialog.alert({ title: t('dialog.error'), message: t('dbfile.backupPassMismatch') }); return false; }
|
|
try {
|
|
const r = await fetch('/api/db/backup', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ passphrase: res.w1 }),
|
|
});
|
|
if (!r.ok) throw new Error(serverFoutTekst(await r.json().catch(() => null)) || `HTTP ${r.status}`);
|
|
const blob = await r.blob();
|
|
const naam = (r.headers.get('Content-Disposition') || '').match(/filename="([^"]+)"/)?.[1] || 'assetapp.assetbak';
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url; a.download = naam; a.click();
|
|
URL.revokeObjectURL(url);
|
|
await stempelBackup();
|
|
await dialog.alert({ message: t('dbfile.backupDone') });
|
|
return true;
|
|
} catch (err) {
|
|
dialog.alert({ title: t('dialog.error'), message: err.message });
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export async function exportDb() {
|
|
const a = document.createElement('a');
|
|
a.href = '/api/db/export';
|
|
a.download = '';
|
|
a.click();
|
|
await stempelBackup();
|
|
}
|
|
|
|
export function restoreDb(onChanged = () => {}) {
|
|
const fileInput = document.createElement('input');
|
|
fileInput.type = 'file';
|
|
fileInput.accept = '.assetbak,.sqlite,.db';
|
|
fileInput.onchange = async () => {
|
|
const file = fileInput.files[0];
|
|
if (!file) return;
|
|
try {
|
|
const kop = new Uint8Array(await file.slice(0, 15).arrayBuffer());
|
|
const isBackup = new TextDecoder('latin1').decode(kop) === 'ASSETAPP-BACKUP';
|
|
|
|
if (!(await dialog.confirm({
|
|
message: isBackup ? t('dbfile.confirmRestoreBackup') : t('dbfile.confirmImport'), danger: true,
|
|
}))) return;
|
|
|
|
const headers = { 'Content-Type': 'application/octet-stream' };
|
|
if (isBackup) {
|
|
const res = await dialog.form({
|
|
title: t('dbfile.import'),
|
|
fields: [{ key: 'w', label: t('dbfile.backupPass'), type: 'password' }],
|
|
confirmLabel: t('dbfile.import'),
|
|
});
|
|
if (!res) return;
|
|
headers['X-Backup-Passphrase'] = res.w;
|
|
}
|
|
|
|
const res = await fetch('/api/db/import', { method: 'POST', headers, body: await file.arrayBuffer() });
|
|
const json = await res.json().catch(() => null);
|
|
if (!res.ok) throw new Error(serverFoutTekst(json) || `HTTP ${res.status}`);
|
|
|
|
const regels = [`${t('dbfile.importDone')} (versie ${json.versie}).`];
|
|
if (json.wezen) regels.push(`${t('dbfile.importOrphans')} ${json.wezen}`);
|
|
regels.push(json.versleuteld ? `${t('dbfile.restoredSecrets')} ${json.geheimen}` : json.geheimenWaarschuwing);
|
|
dialog.alert({ message: regels.join('\n\n') });
|
|
onChanged();
|
|
} catch (err) {
|
|
dialog.alert({ title: t('dialog.error'), message: err.message });
|
|
}
|
|
};
|
|
fileInput.click();
|
|
}
|
|
|
|
export async function startFresh(onChanged = () => {}) {
|
|
if (!(await dialog.confirm({ message: t('dbfile.confirmFresh'), danger: true }))) return;
|
|
const woord = t('dbfile.freshWord');
|
|
const res = await dialog.form({
|
|
title: t('dbfile.fresh'),
|
|
fields: [{ key: 'w', label: `${t('dbfile.freshTypeLabel')} ${woord}`, type: 'text' }],
|
|
confirmLabel: t('dbfile.fresh'),
|
|
});
|
|
if (!res) return;
|
|
if ((res.w || '').trim().toLowerCase() !== woord.toLowerCase()) {
|
|
dialog.alert({ title: t('dialog.error'), message: t('dbfile.freshWordMismatch') });
|
|
return;
|
|
}
|
|
try {
|
|
const r = await fetch('/api/db/fresh', { method: 'POST' });
|
|
const json = await r.json().catch(() => null);
|
|
if (!r.ok) throw new Error(serverFoutTekst(json) || `HTTP ${r.status}`);
|
|
dialog.alert({ message: `${t('dbfile.freshDone')} (versie ${json.versie}).\n\n${json.geheimenWaarschuwing}` });
|
|
onChanged();
|
|
} catch (err) {
|
|
dialog.alert({ title: t('dialog.error'), message: err.message });
|
|
}
|
|
}
|
|
|
|
async function stempelBackup() {
|
|
try { await setAppSetting('last_backup_at', new Date().toISOString()); } catch { }
|
|
document.dispatchEvent(new CustomEvent('providers-changed'));
|
|
}
|