allow update for uploaded routes and implement creator id for routes
This commit is contained in:
@@ -4,6 +4,7 @@ import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import test from 'node:test';
|
||||
import vm from 'node:vm';
|
||||
import { webcrypto } from 'node:crypto';
|
||||
|
||||
const root = path.resolve(import.meta.dirname, '..');
|
||||
const GPX_NAMESPACE = 'http://www.topografix.com/GPX/1/1';
|
||||
@@ -322,7 +323,7 @@ class FakeFileReader extends EventTarget {
|
||||
async function loadLocalRoutes(options = {}) {
|
||||
const sourcePath = path.join(root, 'public/js/local-routes.js');
|
||||
const source = await fs.readFile(sourcePath, 'utf8');
|
||||
const localStorage = new FakeStorage();
|
||||
const localStorage = options.localStorage || new FakeStorage();
|
||||
const indexedDB = new FakeIndexedDB();
|
||||
const document = new EventTarget();
|
||||
const events = [];
|
||||
@@ -336,7 +337,7 @@ async function loadLocalRoutes(options = {}) {
|
||||
EventTarget,
|
||||
FileReader: FakeFileReader,
|
||||
XMLSerializer: FakeXMLSerializer,
|
||||
crypto: options.crypto || { randomUUID: () => '11111111-2222-4333-8444-555555555555' },
|
||||
crypto: options.crypto || { randomUUID: () => '11111111-2222-4333-8444-555555555555', getRandomValues: bytes => webcrypto.getRandomValues(bytes) },
|
||||
document,
|
||||
globalThis: null,
|
||||
indexedDB,
|
||||
@@ -348,7 +349,7 @@ async function loadLocalRoutes(options = {}) {
|
||||
context.globalThis = context;
|
||||
await loadI18n(context);
|
||||
vm.runInNewContext(source, context, { filename: sourcePath });
|
||||
return { api: context.Wegwichtel.LocalRoutes, events, indexedDB, localStorage };
|
||||
return { api: context.Wegwichtel.LocalRoutes, events, indexedDB, localStorage, context };
|
||||
}
|
||||
|
||||
const sampleGpx = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -700,3 +701,32 @@ test('multiple Stationen with large local media keep Local Storage metadata smal
|
||||
assert.doesNotMatch(metadata, /data:image/);
|
||||
assert.equal(api.get(routeId).pois.length, 2);
|
||||
});
|
||||
|
||||
|
||||
test('256-bit creator identity survives reload, route deletion and requires explicit confirmation to reset', async () => {
|
||||
const first = await loadLocalRoutes();
|
||||
const identity = first.api.creatorId();
|
||||
assert.match(identity, /^[a-f0-9]{64}$/);
|
||||
const second = await loadLocalRoutes({ localStorage: first.localStorage });
|
||||
assert.equal(second.api.creatorId(), identity);
|
||||
const saved = second.api.save({ id: 'identity-test', route: { name: 'Test' }, pois: [] });
|
||||
assert.equal(saved.route.creator_id, identity);
|
||||
await second.api.remove('identity-test');
|
||||
assert.equal(second.api.creatorId(), identity);
|
||||
second.context.confirm = () => false;
|
||||
assert.equal(second.api.forgetCreatorId(), false);
|
||||
assert.equal(second.api.creatorId(), identity);
|
||||
second.context.confirm = () => true;
|
||||
assert.equal(second.api.forgetCreatorId(), true);
|
||||
assert.notEqual(second.api.creatorId(), identity);
|
||||
const other = await loadLocalRoutes();
|
||||
assert.notEqual(other.api.creatorId(), identity);
|
||||
});
|
||||
|
||||
test('creator identity never falls back to insecure randomness or replaces corrupt stored identity', async () => {
|
||||
const { api, localStorage } = await loadLocalRoutes({ crypto: {} });
|
||||
assert.throws(() => api.creatorId(), /Gerätekennung/);
|
||||
localStorage.setItem('wegwichtel.creator-id.v1', 'broken');
|
||||
assert.throws(() => api.creatorId(), /Gerätekennung/);
|
||||
assert.equal(localStorage.getItem('wegwichtel.creator-id.v1'), 'broken');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user