Introduce session-based curator login, gate debug/checkup routes, log mutations to curator_audit_log, and keep guest hall preload public. Fix gallery view mounting so WebGL halls render reliably after navigation.
73 lines
2.0 KiB
JavaScript
73 lines
2.0 KiB
JavaScript
require('dotenv').config();
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const pool = require('./db');
|
|
|
|
const INCREMENTAL_MIGRATIONS = [
|
|
'migrate-checkup-flags.sql',
|
|
'migrate-artist-checkup-flags.sql',
|
|
'migrate-influence-sources.sql',
|
|
'migrate-painting-annotations.sql',
|
|
'migrate-artist-palette.sql',
|
|
'migrate-auth.sql',
|
|
];
|
|
|
|
async function bootstrapCurator() {
|
|
const { rows } = await pool.query('SELECT COUNT(*)::int AS n FROM users');
|
|
if (rows[0].n > 0) {
|
|
console.log(' curator bootstrap: users table already populated');
|
|
return;
|
|
}
|
|
|
|
const username = (process.env.CURATOR_USERNAME || 'curator').trim();
|
|
const password = process.env.CURATOR_PASSWORD;
|
|
if (!password) {
|
|
console.warn(' curator bootstrap skipped: set CURATOR_PASSWORD to create the first curator account');
|
|
return;
|
|
}
|
|
|
|
const bcrypt = require('bcryptjs');
|
|
const passwordHash = await bcrypt.hash(password, 10);
|
|
await pool.query(
|
|
`INSERT INTO users (username, password_hash) VALUES ($1, $2)`,
|
|
[username, passwordHash]
|
|
);
|
|
console.log(` bootstrap curator account: ${username}`);
|
|
}
|
|
|
|
async function applySqlFile(label, filePath) {
|
|
const sql = fs.readFileSync(filePath, 'utf8');
|
|
await pool.query(sql);
|
|
console.log(` ${label}`);
|
|
}
|
|
|
|
async function migrate() {
|
|
const dbDir = path.join(__dirname, '..', 'db');
|
|
const schemaPath = path.join(dbDir, 'schema.sql');
|
|
|
|
console.log('Applying db/schema.sql …');
|
|
await applySqlFile('schema.sql', schemaPath);
|
|
|
|
console.log('Applying incremental migrations …');
|
|
for (const file of INCREMENTAL_MIGRATIONS) {
|
|
const filePath = path.join(dbDir, file);
|
|
if (!fs.existsSync(filePath)) {
|
|
console.warn(` skipped (missing): ${file}`);
|
|
continue;
|
|
}
|
|
await applySqlFile(file, filePath);
|
|
}
|
|
|
|
console.log('Bootstrapping curator account (if needed) …');
|
|
await bootstrapCurator();
|
|
|
|
console.log('Database migration complete.');
|
|
}
|
|
|
|
migrate()
|
|
.then(() => pool.end())
|
|
.catch((err) => {
|
|
console.error('Migration failed:', err.message);
|
|
pool.end().finally(() => process.exit(1));
|
|
});
|