#!/usr/bin/env node // ============================================================ // ADMIN CLI — Command line admin tool // Run inside Docker: docker exec pediatric-ai-scribe node admin-cli.js // ============================================================ require('dotenv').config(); var db = require('./src/db/database'); var bcrypt = require('bcryptjs'); var args = process.argv.slice(2); var command = args[0]; async function main() { // Verify DB connection before proceeding await db.query('SELECT 1', []); switch (command) { case 'make-admin': { var email = args[1]; if (!email) { console.log('Usage: node admin-cli.js make-admin '); process.exit(1); } var user = await db.get('SELECT id, name, role FROM users WHERE email = ?', [email.toLowerCase()]); if (!user) { console.log('❌ User not found: ' + email); process.exit(1); } await db.run('UPDATE users SET role = ? WHERE id = ?', ['admin', user.id]); console.log('✅ ' + user.name + ' (' + email + ') is now ADMIN'); break; } case 'remove-admin': { var email = args[1]; if (!email) { console.log('Usage: node admin-cli.js remove-admin '); process.exit(1); } var user = await db.get('SELECT id, name, role FROM users WHERE email = ?', [email.toLowerCase()]); if (!user) { console.log('❌ User not found: ' + email); process.exit(1); } await db.run('UPDATE users SET role = ? WHERE id = ?', ['user', user.id]); console.log('✅ ' + user.name + ' (' + email + ') is now regular user'); break; } case 'verify-user': { var email = args[1]; if (!email) { console.log('Usage: node admin-cli.js verify-user '); process.exit(1); } var user = await db.get('SELECT id, name FROM users WHERE email = ?', [email.toLowerCase()]); if (!user) { console.log('❌ User not found: ' + email); process.exit(1); } await db.run('UPDATE users SET email_verified = true, verify_token = NULL WHERE id = ?', [user.id]); console.log('✅ ' + user.name + ' (' + email + ') email verified'); break; } case 'disable-user': { var email = args[1]; if (!email) { console.log('Usage: node admin-cli.js disable-user '); process.exit(1); } var user = await db.get('SELECT id, name FROM users WHERE email = ?', [email.toLowerCase()]); if (!user) { console.log('❌ User not found: ' + email); process.exit(1); } await db.run('UPDATE users SET disabled = true WHERE id = ?', [user.id]); console.log('✅ ' + user.name + ' (' + email + ') DISABLED'); break; } case 'enable-user': { var email = args[1]; if (!email) { console.log('Usage: node admin-cli.js enable-user '); process.exit(1); } var user = await db.get('SELECT id, name FROM users WHERE email = ?', [email.toLowerCase()]); if (!user) { console.log('❌ User not found: ' + email); process.exit(1); } await db.run('UPDATE users SET disabled = false WHERE id = ?', [user.id]); console.log('✅ ' + user.name + ' (' + email + ') ENABLED'); break; } case 'delete-user': { var email = args[1]; if (!email) { console.log('Usage: node admin-cli.js delete-user '); process.exit(1); } var user = await db.get('SELECT id, name FROM users WHERE email = ?', [email.toLowerCase()]); if (!user) { console.log('❌ User not found: ' + email); process.exit(1); } await db.run('DELETE FROM users WHERE id = ?', [user.id]); console.log('✅ ' + user.name + ' (' + email + ') DELETED'); break; } case 'reset-password': { var email = args[1]; var newPass = args[2]; if (!email || !newPass) { console.log('Usage: node admin-cli.js reset-password '); process.exit(1); } if (newPass.length < 8) { console.log('❌ Password must be 8+ characters'); process.exit(1); } var user = await db.get('SELECT id, name FROM users WHERE email = ?', [email.toLowerCase()]); if (!user) { console.log('❌ User not found: ' + email); process.exit(1); } var hash = await bcrypt.hash(newPass, 12); await db.run('UPDATE users SET password = ? WHERE id = ?', [hash, user.id]); console.log('✅ Password reset for ' + user.name + ' (' + email + ')'); break; } case 'create-admin': { var email = args[1]; var password = args[2]; var name = args[3]; if (!email || !password || !name) { console.log('Usage: node admin-cli.js create-admin '); process.exit(1); } if (password.length < 8) { console.log('❌ Password must be 8+ characters'); process.exit(1); } var existing = await db.get('SELECT id FROM users WHERE email = ?', [email.toLowerCase()]); if (existing) { console.log('❌ Email already exists: ' + email); process.exit(1); } var hash = await bcrypt.hash(password, 12); await db.run( 'INSERT INTO users (email, password, name, role, email_verified) VALUES (?, ?, ?, ?, true)', [email.toLowerCase(), hash, name, 'admin'] ); console.log('✅ Admin user created: ' + name + ' (' + email + ')'); break; } case 'list-users': { var users = await db.all('SELECT id, email, name, role, email_verified, disabled, created_at FROM users ORDER BY id', []); console.log(''); console.log('ID | Email | Name | Role | Verified | Disabled'); console.log('---+---------------------------+-------------------+-------+----------+---------'); users.forEach(function(u) { console.log( String(u.id).padEnd(3) + '| ' + u.email.padEnd(26) + '| ' + (u.name || '').padEnd(18) + '| ' + (u.role || 'user').padEnd(6) + '| ' + (u.email_verified ? '✅' : '❌').padEnd(9) + '| ' + (u.disabled ? '🚫 Yes' : '✅ No') ); }); console.log(''); console.log('Total: ' + users.length + ' users'); break; } case 'toggle-registration': { var current = await db.getSetting('registration_enabled'); var newValue = current === 'false' ? 'true' : 'false'; await db.setSetting('registration_enabled', newValue); console.log('✅ Registration is now: ' + (newValue === 'true' ? 'ENABLED' : 'DISABLED')); break; } case 'stats': { var userCount = await db.get('SELECT COUNT(*) as count FROM users', []); var apiCount = await db.get('SELECT COUNT(*) as count FROM api_log', []); var todayApi = await db.get("SELECT COUNT(*) as count FROM api_log WHERE timestamp > NOW() - INTERVAL '1 day'", []); var regEnabled = await db.getSetting('registration_enabled'); console.log(''); console.log('📊 App Statistics'); console.log('─────────────────'); console.log('Users: ' + (userCount ? userCount.count : 0)); console.log('Total API calls: ' + (apiCount ? apiCount.count : 0)); console.log('Today API calls: ' + (todayApi ? todayApi.count : 0)); console.log('Registration: ' + (regEnabled !== 'false' ? '✅ Enabled' : '❌ Disabled')); console.log(''); break; } default: console.log(''); console.log('🏥 Pediatric AI Scribe — Admin CLI'); console.log(''); console.log('Usage: docker exec pediatric-ai-scribe node admin-cli.js '); console.log(''); console.log('User Management:'); console.log(' list-users List all users'); console.log(' create-admin Create admin user'); console.log(' make-admin Promote user to admin'); console.log(' remove-admin Demote admin to user'); console.log(' verify-user Verify user email'); console.log(' disable-user Disable user account'); console.log(' enable-user Enable user account'); console.log(' delete-user Delete user permanently'); console.log(' reset-password Reset user password'); console.log(''); console.log('App Settings:'); console.log(' toggle-registration Toggle registration on/off'); console.log(' stats Show app statistics'); console.log(''); } process.exit(0); } main().catch(function(err) { console.error('❌ Error:', err.message); process.exit(1); });