this is a big slop that might backfire lol... new config system and UI!

This commit is contained in:
legop3
2026-09-14 02:31:12 -04:00
parent 17b1404157
commit bfdb6555d8
108 changed files with 3212 additions and 701 deletions
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env node
// Administrator Recovery Command
// Purpose: Creates or resets a lockdown administrator when web authentication cannot be repaired through /admin.
// Scope: Performs one explicit local database mutation and never creates a recurring startup bypass.
const bcrypt = require('bcrypt');
const { getConfigurationDatabase } = require('../src/configuration');
function usage() {
process.stderr.write('Usage: node scripts/adminAccount.js <username> <password> [discord-id]\n');
}
async function main() {
const [username, password, discordId = ''] = process.argv.slice(2);
if (!username || !password) {
usage();
process.exitCode = 2;
return;
}
if (password.length < 10) throw new Error('Administrator password must be at least 10 characters.');
const database = getConfigurationDatabase();
const existing = database.findAdministratorForAuthentication(username);
const passwordHash = await bcrypt.hash(password, 12);
if (existing) {
database.updateAdministrator(existing.id, { passwordHash, role: 'lockdown', discordId }, 'command-line-recovery');
process.stdout.write(`Reset lockdown administrator ${existing.username}.\n`);
return;
}
const created = database.createAdministrator({ username, passwordHash, discordId, role: 'lockdown' }, 'command-line-recovery');
process.stdout.write(`Created lockdown administrator ${created.username}.\n`);
}
main().catch((error) => {
process.stderr.write(`Administrator recovery failed: ${error.message}\n`);
process.exitCode = 1;
});
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env node
// Legacy Configuration Import Command
// Purpose: Imports or validates an explicitly selected YAML file before normal database-only startup.
// Scope: Provides recovery/unattended migration using the same importer as first-run setup.
const fs = require('fs');
const path = require('path');
const { getConfigurationDatabase } = require('../src/configuration');
const { importLegacyConfiguration } = require('../src/configuration/legacyImporter');
function usage() {
process.stderr.write('Usage: node scripts/importLegacyConfig.js <config.yaml> [--dry-run]\n');
}
function main() {
const args = process.argv.slice(2);
const dryRun = args.includes('--dry-run');
const selectedPath = args.find((arg) => arg !== '--dry-run');
if (!selectedPath) {
usage();
process.exitCode = 2;
return;
}
const absolutePath = path.resolve(selectedPath);
const text = fs.readFileSync(absolutePath, 'utf8');
const result = importLegacyConfiguration({
text,
database: getConfigurationDatabase(),
actor: 'command-line-import',
source: path.basename(absolutePath),
dryRun,
});
/*
Never print parsed configuration values: the legacy document commonly
contains Discord, Home Assistant, and camera credentials. A concise count
and revision are sufficient for an unattended migration log.
*/
process.stdout.write(`${dryRun ? 'Legacy configuration is valid' : 'Legacy configuration imported'}: ${result.administratorCount} administrator(s)${result.revision ? `, revision ${result.revision}` : ''}.\n`);
}
try {
main();
} catch (error) {
process.stderr.write(`Legacy configuration import failed: ${error.message}\n`);
if (Array.isArray(error.validationErrors)) {
error.validationErrors.forEach((entry) => process.stderr.write(`- ${entry.path}: ${entry.message}\n`));
}
process.exitCode = 1;
}
+1 -1
View File
@@ -3,7 +3,7 @@
// Purpose: Lets the installer validate server-owned MediaMTX inputs before disabling the legacy service.
// Scope: Builds and serializes the runtime YAML without starting MediaMTX or changing external state.
const yaml = require('js-yaml');
const { loadConfig } = require('../src/helpers/configLoader');
const { loadConfig } = require('../src/configuration');
const { buildMediaMtxConfig } = require('../src/services/mediaMtxService/config');
const config = loadConfig();