49 lines
2.5 KiB
JavaScript
49 lines
2.5 KiB
JavaScript
// Node-Backend der Android-App. Die Kanäle kommen aus src/core/backend.js (gemeinsam mit der Web-Version);
|
|
// hier nur, was Android betrifft: Bridge-Anbindung, Entsperren per Fingerabdruck, Pause/Fortsetzen.
|
|
// Protokoll: Oberfläche → 'call' [reqId, Kanal, Argumente] bzw. 'send' [Kanal, Argumente];
|
|
// Backend → 'reply' [reqId, ok, Wert|Fehler] und 'evt' [Kanal, Argumente].
|
|
const { channel } = require('bridge');
|
|
const crypto = require('crypto');
|
|
const { Store } = require('../../src/main/store');
|
|
const { createBackend } = require('../../src/core/backend');
|
|
const i18n = require('../../src/i18n');
|
|
|
|
const send = (ch, ...args) => channel.send('evt', ch, args);
|
|
process.on('uncaughtException', (e) => { console.error(e); send('toast', e?.message || String(e), 'error'); });
|
|
process.on('unhandledRejection', (e) => console.error('Unhandled rejection:', e));
|
|
|
|
const store = new Store();
|
|
const applyLanguage = (lang = store.get().settings.language) => i18n.setLanguage(lang, process.env.MRTERM_LOCALE || 'en');
|
|
const be = createBackend({ store, send, platform: 'android', version: process.env.MRTERM_VERSION || '0.0.0', withSync: true, onLanguage: applyLanguage });
|
|
|
|
channel.addListener('call', async (reqId, ch, args = []) => {
|
|
try { channel.send('reply', reqId, true, await be.call(ch, args)); } catch (e) { channel.send('reply', reqId, false, e?.message || String(e)); }
|
|
});
|
|
channel.addListener('send', (ch, args = []) => be.notify(ch, args));
|
|
|
|
// ---------- Fingerabdruck (Geheimnis aus dem Android Keystore, nur zusätzlich zum Passwort) ----------
|
|
const bioKek = (b64) => Buffer.from(crypto.hkdfSync('sha256', Buffer.from(b64, 'base64'), Buffer.alloc(0), 'mrterm-bio-kek', 32));
|
|
be.handle('lock:unlockBio', (secret) => {
|
|
if (!store.lock?.bio) throw new Error(i18n.t('Fingerprint unlock is not set up.'));
|
|
try { store.unlockWith(bioKek(secret), store.lock.bio.wrap); } catch { throw new Error(i18n.t('Fingerprint unlock failed. Use your password.')); }
|
|
applyLanguage();
|
|
be.sync.start().catch(() => {});
|
|
return true;
|
|
});
|
|
be.handle('lock:setBio', (secret) => {
|
|
be.requireUnlocked();
|
|
if (!store.lock?.password) throw new Error(i18n.t('Set a password first.'));
|
|
store.lock.bio = secret ? { wrap: store.wrapDek(bioKek(secret)) } : null;
|
|
store.save();
|
|
return be.lockStatus();
|
|
});
|
|
|
|
// App im Hintergrund: Sync-Sockets schließen, im Vordergrund wieder öffnen
|
|
be.handle('app:pause', () => be.sync.stop());
|
|
be.handle('app:resume', () => be.sync.start().catch(() => {}));
|
|
|
|
store.load();
|
|
applyLanguage();
|
|
be.sync.start().catch(() => {});
|
|
channel.send('ready');
|