mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 09:31:20 -04:00
remove useless slop stuff
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// Configuration System Tests
|
||||
// Purpose: Verifies strict defaults, immutable revisions, secret handling, legacy import, and administrator safety.
|
||||
// Purpose: Verifies strict defaults, immutable revisions, secret handling, explicit setup-file import, and administrator safety.
|
||||
// Scope: Uses isolated temporary databases and never opens the development server's data store.
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
@@ -10,7 +10,7 @@ const { defaultConfig, normalizeConfig, assertValidConfig } = require('./validat
|
||||
const { definitions, rootSchema, secretPaths, featureDefinitions } = require('./definition');
|
||||
const { getFeatureFlags } = require('./index');
|
||||
const { createConfigurationDatabase } = require('./database');
|
||||
const { parseLegacyConfiguration, importLegacyConfiguration } = require('./legacyImporter');
|
||||
const { parseConfigurationFile, importConfigurationFile } = require('./configurationFileImporter');
|
||||
|
||||
const temporaryRoots = [];
|
||||
|
||||
@@ -168,7 +168,7 @@ test('administrator storage never exposes hashes or removes the final lockdown a
|
||||
database.close();
|
||||
});
|
||||
|
||||
test('legacy YAML imports configuration and bcrypt hashes exactly once', () => {
|
||||
test('an explicitly uploaded YAML file imports configuration and bcrypt hashes exactly once', () => {
|
||||
const yamlText = `
|
||||
admins:
|
||||
- username: owner
|
||||
@@ -179,14 +179,14 @@ timezone: America/Chicago
|
||||
media:
|
||||
whepBaseUrl: http://localhost:8889/video
|
||||
`;
|
||||
const parsed = parseLegacyConfiguration(yamlText);
|
||||
const parsed = parseConfigurationFile(yamlText);
|
||||
assert.equal(parsed.config.timezone, 'America/Chicago');
|
||||
assert.equal(parsed.administrators[0].passwordHash, '$2b$10$preservedHash');
|
||||
|
||||
const database = createTestDatabase();
|
||||
const result = importLegacyConfiguration({ text: yamlText, database, dryRun: false });
|
||||
const result = importConfigurationFile({ text: yamlText, database });
|
||||
assert.equal(result.administratorCount, 1);
|
||||
assert.equal(database.findAdministratorForAuthentication('OWNER').passwordHash, '$2b$10$preservedHash');
|
||||
assert.throws(() => importLegacyConfiguration({ text: yamlText, database }), /cannot replace an initialized installation/);
|
||||
assert.throws(() => importConfigurationFile({ text: yamlText, database }), /cannot replace an initialized installation/);
|
||||
database.close();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// Configuration File Importer
|
||||
// Purpose: Validates one YAML file deliberately uploaded during first-run setup and stores it in the configuration database.
|
||||
// Scope: This is an explicit setup action only; startup and installation never search for or consume configuration files.
|
||||
const yaml = require('js-yaml');
|
||||
const { normalizeConfig, assertValidConfig } = require('./validation');
|
||||
|
||||
function normalizeUploadedAdministrator(entry, index) {
|
||||
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
||||
throw new Error(`Administrator ${index + 1} must be an object.`);
|
||||
}
|
||||
const username = String(entry.username || '').trim();
|
||||
const passwordHash = String(entry.password_hash || '').trim();
|
||||
if (!username || !passwordHash) {
|
||||
throw new Error(`Administrator ${index + 1} requires username and password_hash.`);
|
||||
}
|
||||
return {
|
||||
username,
|
||||
passwordHash,
|
||||
discordId: String(entry.discord_id || '').trim(),
|
||||
role: entry.lockdown ? 'lockdown' : 'admin',
|
||||
};
|
||||
}
|
||||
|
||||
function parseConfigurationFile(text) {
|
||||
const parsed = yaml.load(String(text || ''));
|
||||
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
||||
throw new Error('The configuration file must contain a YAML object.');
|
||||
}
|
||||
|
||||
const administrators = Array.isArray(parsed.admins)
|
||||
? parsed.admins.map(normalizeUploadedAdministrator)
|
||||
: [];
|
||||
const configInput = Object.fromEntries(
|
||||
Object.entries(parsed).filter(([key]) => key !== 'admins'),
|
||||
);
|
||||
const config = normalizeConfig(configInput);
|
||||
|
||||
/*
|
||||
Unknown fields remain in the normalized document so strict schema
|
||||
validation reports them to the operator instead of silently losing data
|
||||
from the explicitly selected file.
|
||||
*/
|
||||
assertValidConfig(config);
|
||||
if (!administrators.some((admin) => admin.role === 'lockdown')) {
|
||||
throw new Error('The configuration file must contain at least one lockdown administrator.');
|
||||
}
|
||||
return { config, administrators };
|
||||
}
|
||||
|
||||
function importConfigurationFile({ text, database, actor = 'setup-file-upload', source = 'uploaded-config.yaml' }) {
|
||||
const result = parseConfigurationFile(text);
|
||||
const revision = database.importConfigurationFile({
|
||||
config: result.config,
|
||||
administrators: result.administrators,
|
||||
actor,
|
||||
source,
|
||||
});
|
||||
return {
|
||||
revision,
|
||||
administratorCount: result.administrators.length,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parseConfigurationFile,
|
||||
importConfigurationFile,
|
||||
};
|
||||
@@ -331,8 +331,10 @@ function createConfigurationDatabase({ databasePath = DEFAULT_DATABASE_PATH } =
|
||||
}));
|
||||
}
|
||||
|
||||
const importLegacyTransaction = db.transaction(({ config, administrators, actor, source }) => {
|
||||
if (isSetupComplete()) throw new Error('Legacy configuration cannot replace an initialized installation.');
|
||||
const importConfigurationFileTransaction = db.transaction(({ config, administrators, actor, source }) => {
|
||||
// A setup upload initializes an empty installation; it is deliberately not
|
||||
// a general-purpose replacement path for a running server's configuration.
|
||||
if (isSetupComplete()) throw new Error('A configuration file cannot replace an initialized installation.');
|
||||
const normalized = assertValidConfig(normalizeConfig(config));
|
||||
const revision = commitRevisionTransaction(normalized, {
|
||||
expectedRevision: getActiveConfigurationRecord().revision,
|
||||
@@ -340,13 +342,13 @@ function createConfigurationDatabase({ databasePath = DEFAULT_DATABASE_PATH } =
|
||||
source,
|
||||
});
|
||||
administrators.forEach((admin) => createAdministratorTransaction(admin, actor, false));
|
||||
if (!isSetupComplete()) throw new Error('Legacy import must contain at least one lockdown administrator.');
|
||||
writeAudit(actor, 'legacy-import.completed', { revision, administratorCount: administrators.length, source });
|
||||
if (!isSetupComplete()) throw new Error('The configuration file must contain at least one lockdown administrator.');
|
||||
writeAudit(actor, 'setup.configuration-file-imported', { revision, administratorCount: administrators.length, source });
|
||||
return revision;
|
||||
});
|
||||
|
||||
function importLegacy(payload) {
|
||||
return importLegacyTransaction(payload);
|
||||
function importConfigurationFile(payload) {
|
||||
return importConfigurationFileTransaction(payload);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -364,7 +366,7 @@ function createConfigurationDatabase({ databasePath = DEFAULT_DATABASE_PATH } =
|
||||
countLockdownAdministrators,
|
||||
isSetupComplete,
|
||||
listAuditEvents,
|
||||
importLegacy,
|
||||
importConfigurationFile,
|
||||
close: () => db.close(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
// Legacy YAML Configuration Importer
|
||||
// Purpose: Converts one explicitly supplied config.yaml document into the database-backed configuration model.
|
||||
// Scope: Parses and validates legacy input without becoming a runtime fallback or watcher.
|
||||
const yaml = require('js-yaml');
|
||||
const { normalizeConfig, assertValidConfig } = require('./validation');
|
||||
|
||||
function normalizeLegacyAdministrator(entry, index) {
|
||||
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
||||
throw new Error(`Legacy administrator ${index + 1} must be an object.`);
|
||||
}
|
||||
const username = String(entry.username || '').trim();
|
||||
const passwordHash = String(entry.password_hash || '').trim();
|
||||
if (!username || !passwordHash) {
|
||||
throw new Error(`Legacy administrator ${index + 1} requires username and password_hash.`);
|
||||
}
|
||||
return {
|
||||
username,
|
||||
passwordHash,
|
||||
discordId: String(entry.discord_id || '').trim(),
|
||||
role: entry.lockdown ? 'lockdown' : 'admin',
|
||||
};
|
||||
}
|
||||
|
||||
function parseLegacyConfiguration(text) {
|
||||
const parsed = yaml.load(String(text || ''));
|
||||
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
||||
throw new Error('Legacy configuration must contain a YAML object.');
|
||||
}
|
||||
|
||||
const administrators = Array.isArray(parsed.admins)
|
||||
? parsed.admins.map(normalizeLegacyAdministrator)
|
||||
: [];
|
||||
const configInput = Object.fromEntries(
|
||||
Object.entries(parsed).filter(([key]) => key !== 'admins'),
|
||||
);
|
||||
const config = normalizeConfig(configInput);
|
||||
|
||||
/*
|
||||
Unknown fields are retained by normalizeConfig and therefore appear in
|
||||
Ajv's precise validation errors instead of being silently discarded during
|
||||
the one-time import.
|
||||
*/
|
||||
assertValidConfig(config);
|
||||
if (!administrators.some((admin) => admin.role === 'lockdown')) {
|
||||
throw new Error('Legacy configuration must contain at least one lockdown administrator.');
|
||||
}
|
||||
return { config, administrators };
|
||||
}
|
||||
|
||||
function importLegacyConfiguration({ text, database, actor = 'legacy-import', source = 'config.yaml', dryRun = false }) {
|
||||
const result = parseLegacyConfiguration(text);
|
||||
if (dryRun) {
|
||||
return {
|
||||
dryRun: true,
|
||||
administratorCount: result.administrators.length,
|
||||
};
|
||||
}
|
||||
const revision = database.importLegacy({
|
||||
config: result.config,
|
||||
administrators: result.administrators,
|
||||
actor,
|
||||
source,
|
||||
});
|
||||
return {
|
||||
dryRun: false,
|
||||
revision,
|
||||
administratorCount: result.administrators.length,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parseLegacyConfiguration,
|
||||
importLegacyConfiguration,
|
||||
};
|
||||
Reference in New Issue
Block a user