openvibers/openvibe.network Commits
Legacy secret cleanup: configuration rows only (the VAPID public key is public) (#561)
Changes
@@@ -136,7 +136,9 @@ function readSecret(db, key) {*/async function migrateLegacySecrets(db, out) {const rows = await db.prepare('SELECT key, value, type FROM site_settings').all();-- const candidates = rows.filter((r) => r.value != null && String(r.value) !== ''++ // Only configuration rows: keys the journal never holds (NOT_CONFIG: the VAPID pair, migration markers) have no++ // sealed copy to prove against, and are not counted.++ const candidates = rows.filter((r) => r.value != null && String(r.value) !== '' && isConfigKey(r.key)&& (r.type === 'secret' || SECRET.test(r.key)) && !secrets.isSecret(r.key));if (!candidates.length) return { checked: 0, blanked: 0, differs: 0, kept: 0, sealed: !!out.store.sealed };if (!out.store.sealed) {@@@ -64,7 +64,7 @@ async function initVapid(db) {const keys = webpush.generateVAPIDKeys();publicKey = keys.publicKey;privateKey = keys.privateKey;-- await upsert.run('vapid_public_key', publicKey, 'secret');++ await upsert.run('vapid_public_key', publicKey, 'string'); // public: served to every browserawait upsert.run('vapid_private_key', privateKey, 'secret');_publicKey = publicKey;console.log('[push] Generated new VAPID keypair');@@@ -26,6 +26,8 @@ console.error = (...a) => logs.push(a.map(String).join(' '));await set.run('net.ipinfo_token', SECRET, 'secret');await set.run('discord_bot_token', PROVIDER, 'secret');await set.run('platform_name', 'OpenVibe', 'string');++ // The VAPID public key (served to browsers) has an old 'secret' row type: it is not configuration, not counted.++ await set.run('vapid_public_key', 'sentinel-vapid-public', 'secret');const siteConfig = require('../server/admin/site-config');const report = await siteConfig.init(db);@@@ -33,12 +35,14 @@ console.error = (...a) => logs.push(a.map(String).join(' '));assert.strictEqual(journal.store.sealed, true);assert.strictEqual(report.blanked, 1, 'the non-provider secret row was blanked');assert.strictEqual(report.differs, 0, 'an equal value is not counted as differing');++ assert.strictEqual(report.checked, 1, 'a non-configuration row (vapid_public_key) is not a candidate');const raw = async (k) => (await db.prepare('SELECT value, type FROM site_settings WHERE key = ?').get(k));assert.strictEqual((await raw('net.ipinfo_token')).value, '', 'no secret-class value remains in site_settings');assert.strictEqual((await raw('net.ipinfo_token')).type, 'secret', 'the typed slot stays for the settings page');assert.strictEqual((await raw('discord_bot_token')).value, PROVIDER, 'a provider secret is never moved or blanked');assert.strictEqual((await raw('platform_name')).value, 'OpenVibe', 'a non-secret row is untouched');++ assert.strictEqual((await raw('vapid_public_key')).value, 'sentinel-vapid-public', 'the VAPID public key is untouched');assert.strictEqual(await db.getSetting('net.ipinfo_token'), SECRET, 'the reader gets the journal value');assert.strictEqual(await db.getSetting('discord_bot_token'), null, 'a provider secret is still environment-only');
@@ -136,7 +136,9 @@ function readSecret(db, key) {
@@ -136,7 +136,9 @@ function readSecret(db, key) {
*/
*/
async function migrateLegacySecrets(db, out) {
async function migrateLegacySecrets(db, out) {
const rows = await db.prepare('SELECT key, value, type FROM site_settings').all();
const rows = await db.prepare('SELECT key, value, type FROM site_settings').all();
- const candidates = rows.filter((r) => r.value != null && String(r.value) !== ''
+ // Only configuration rows: keys the journal never holds (NOT_CONFIG: the VAPID pair, migration markers) have no
+ // sealed copy to prove against, and are not counted.
+ const candidates = rows.filter((r) => r.value != null && String(r.value) !== '' && isConfigKey(r.key)
&& (r.type === 'secret' || SECRET.test(r.key)) && !secrets.isSecret(r.key));
&& (r.type === 'secret' || SECRET.test(r.key)) && !secrets.isSecret(r.key));
if (!candidates.length) return { checked: 0, blanked: 0, differs: 0, kept: 0, sealed: !!out.store.sealed };
if (!candidates.length) return { checked: 0, blanked: 0, differs: 0, kept: 0, sealed: !!out.store.sealed };
if (!out.store.sealed) {
if (!out.store.sealed) {
@@ -64,7 +64,7 @@ async function initVapid(db) {
@@ -64,7 +64,7 @@ async function initVapid(db) {
const keys = webpush.generateVAPIDKeys();
const keys = webpush.generateVAPIDKeys();
publicKey = keys.publicKey;
publicKey = keys.publicKey;
privateKey = keys.privateKey;
privateKey = keys.privateKey;
- await upsert.run('vapid_public_key', publicKey, 'secret');
+ await upsert.run('vapid_public_key', publicKey, 'string'); // public: served to every browser
await upsert.run('vapid_private_key', privateKey, 'secret');
await upsert.run('vapid_private_key', privateKey, 'secret');
_publicKey = publicKey;
_publicKey = publicKey;
console.log('[push] Generated new VAPID keypair');
console.log('[push] Generated new VAPID keypair');
@@ -26,6 +26,8 @@ console.error = (...a) => logs.push(a.map(String).join(' '));
@@ -26,6 +26,8 @@ console.error = (...a) => logs.push(a.map(String).join(' '));
await set.run('net.ipinfo_token', SECRET, 'secret');
await set.run('net.ipinfo_token', SECRET, 'secret');
await set.run('discord_bot_token', PROVIDER, 'secret');
await set.run('discord_bot_token', PROVIDER, 'secret');
await set.run('platform_name', 'OpenVibe', 'string');
await set.run('platform_name', 'OpenVibe', 'string');
+ // The VAPID public key (served to browsers) has an old 'secret' row type: it is not configuration, not counted.
+ await set.run('vapid_public_key', 'sentinel-vapid-public', 'secret');
const siteConfig = require('../server/admin/site-config');
const siteConfig = require('../server/admin/site-config');
const report = await siteConfig.init(db);
const report = await siteConfig.init(db);
@@ -33,12 +35,14 @@ console.error = (...a) => logs.push(a.map(String).join(' '));
@@ -33,12 +35,14 @@ console.error = (...a) => logs.push(a.map(String).join(' '));
assert.strictEqual(journal.store.sealed, true);
assert.strictEqual(journal.store.sealed, true);
assert.strictEqual(report.blanked, 1, 'the non-provider secret row was blanked');
assert.strictEqual(report.blanked, 1, 'the non-provider secret row was blanked');
assert.strictEqual(report.differs, 0, 'an equal value is not counted as differing');
assert.strictEqual(report.differs, 0, 'an equal value is not counted as differing');
+ assert.strictEqual(report.checked, 1, 'a non-configuration row (vapid_public_key) is not a candidate');
const raw = async (k) => (await db.prepare('SELECT value, type FROM site_settings WHERE key = ?').get(k));
const raw = async (k) => (await db.prepare('SELECT value, type FROM site_settings WHERE key = ?').get(k));
assert.strictEqual((await raw('net.ipinfo_token')).value, '', 'no secret-class value remains in site_settings');
assert.strictEqual((await raw('net.ipinfo_token')).value, '', 'no secret-class value remains in site_settings');
assert.strictEqual((await raw('net.ipinfo_token')).type, 'secret', 'the typed slot stays for the settings page');
assert.strictEqual((await raw('net.ipinfo_token')).type, 'secret', 'the typed slot stays for the settings page');
assert.strictEqual((await raw('discord_bot_token')).value, PROVIDER, 'a provider secret is never moved or blanked');
assert.strictEqual((await raw('discord_bot_token')).value, PROVIDER, 'a provider secret is never moved or blanked');
assert.strictEqual((await raw('platform_name')).value, 'OpenVibe', 'a non-secret row is untouched');
assert.strictEqual((await raw('platform_name')).value, 'OpenVibe', 'a non-secret row is untouched');
+ assert.strictEqual((await raw('vapid_public_key')).value, 'sentinel-vapid-public', 'the VAPID public key is untouched');
assert.strictEqual(await db.getSetting('net.ipinfo_token'), SECRET, 'the reader gets the journal value');
assert.strictEqual(await db.getSetting('net.ipinfo_token'), SECRET, 'the reader gets the journal value');
assert.strictEqual(await db.getSetting('discord_bot_token'), null, 'a provider secret is still environment-only');
assert.strictEqual(await db.getSetting('discord_bot_token'), null, 'a provider secret is still environment-only');