tractatus/scripts/seed-admin.js
TheFlow ac2db33732 fix(submissions): restructure Economist package and fix article display
- Create Economist SubmissionTracking package correctly:
  * mainArticle = full blog post content
  * coverLetter = 216-word SIR— letter
  * Links to blog post via blogPostId
- Archive 'Letter to The Economist' from blog posts (it's the cover letter)
- Fix date display on article cards (use published_at)
- Target publication already displaying via blue badge

Database changes:
- Make blogPostId optional in SubmissionTracking model
- Economist package ID: 68fa85ae49d4900e7f2ecd83
- Le Monde package ID: 68fa2abd2e6acd5691932150

Next: Enhanced modal with tabs, validation, export

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:47:42 +13:00

113 lines
3 KiB
JavaScript
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Seed Admin User Script
* Creates the initial admin user for the Tractatus platform
*
* Usage: npm run seed:admin
*/
require('dotenv').config();
const readline = require('readline');
const { connect, close } = require('../src/utils/db.util');
const User = require('../src/models/User.model');
const logger = require('../src/utils/logger.util');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function question(prompt) {
return new Promise((resolve) => {
rl.question(prompt, resolve);
});
}
async function seedAdmin() {
try {
console.log('\n=== Tractatus Admin User Setup ===\n');
// Connect to database
await connect();
// Check if admin user already exists
const existingAdmin = await User.findByEmail(process.env.ADMIN_EMAIL || 'admin@tractatus.local');
if (existingAdmin) {
console.log('⚠️ Admin user already exists.');
const overwrite = await question('Do you want to delete and recreate? (yes/no): ');
if (overwrite.toLowerCase() !== 'yes') {
console.log('Cancelled. No changes made.');
await cleanup();
return;
}
await User.deleteOne({ _id: existingAdmin._id });
console.log('✅ Existing admin user deleted.');
}
// Get admin details
console.log('\nEnter admin user details:');
const name = await question('Name (default: Admin User): ') || 'Admin User';
const email = await question(`Email (default: ${process.env.ADMIN_EMAIL || 'admin@tractatus.local'}): `)
|| process.env.ADMIN_EMAIL
|| 'admin@tractatus.local';
// Password input (hidden)
console.log('\n⚠ Password will be visible. Use a development password only.');
const password = await question('Password (min 8 chars): ');
if (!password || password.length < 8) {
console.error('❌ Password must be at least 8 characters.');
await cleanup();
return;
}
// Create admin user
const admin = await User.create({
name,
email,
password, // Will be hashed by the model
role: 'admin',
active: true
});
console.log('\n✅ Admin user created successfully!');
console.log('\nCredentials:');
console.log(` Email: ${admin.email}`);
console.log(` Role: ${admin.role}`);
console.log(` ID: ${admin._id}`);
console.log('\nYou can now login at: POST /api/auth/login');
console.log('');
logger.info(`Admin user created: ${admin.email}`);
} catch (error) {
console.error('\n❌ Error creating admin user:', error.message);
logger.error('Admin seed error:', error);
process.exit(1);
} finally {
await cleanup();
}
}
async function cleanup() {
rl.close();
await close();
}
// Handle Ctrl+C
process.on('SIGINT', async () => {
console.log('\n\n👋 Cancelled by user');
await cleanup();
process.exit(0);
});
// Run if called directly
if (require.main === module) {
seedAdmin();
}
module.exports = seedAdmin;