#!/usr/bin/env node import { input, password, select, confirm } from '@inquirer/prompts'; import Database from 'better-sqlite3'; import bcrypt from 'bcrypt'; const DB_FILE = 'ac_data.db'; const db = new Database(DB_FILE); db.exec(` CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'user', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); const insertUser = db.prepare('INSERT INTO users (username, password_hash, role) VALUES (?, ?, ?)'); const getAllUsers = db.prepare('SELECT id, username, role, created_at FROM users ORDER BY id'); const getUserById = db.prepare('SELECT * FROM users WHERE id = ?'); const updateUserRole = db.prepare('UPDATE users SET role = ? WHERE id = ?'); const updateUserPassword = db.prepare('UPDATE users SET password_hash = ? WHERE id = ?'); const deleteUser = db.prepare('DELETE FROM users WHERE id = ?'); console.log('\n╔══════════════════════════════════════╗'); console.log('║ 🔐 User Manager - AC Dashboard ║'); console.log('╚══════════════════════════════════════╝\n'); async function listUsers() { const users = getAllUsers.all(); if (users.length === 0) { console.log(' No users found.\n'); return; } console.log(' ID │ Username │ Role │ Created'); console.log(' ────┼────────────────┼────────┼─────────────────────'); users.forEach(u => { const id = String(u.id).padStart(3); const name = u.username.padEnd(14); const role = u.role.padEnd(6); const date = u.created_at?.slice(0, 16) || 'N/A'; const roleColor = u.role === 'admin' ? '\x1b[35m' : '\x1b[33m'; console.log(` ${id} │ ${name} │ ${roleColor}${role}\x1b[0m │ ${date}`); }); console.log(''); } async function createUser() { const username = await input({ message: 'Username:', validate: v => v.length >= 3 || 'Min 3 characters' }); const pwd = await password({ message: 'Password:', mask: '*', validate: v => v.length >= 4 || 'Min 4 characters' }); const role = await select({ message: 'Role:', choices: [ { name: '👤 user', value: 'user' }, { name: '👑 admin', value: 'admin' } ] }); try { const hash = await bcrypt.hash(pwd, 10); insertUser.run(username, hash, role); console.log(`\n✅ User "${username}" created as ${role}\n`); } catch (e) { if (e.code === 'SQLITE_CONSTRAINT_UNIQUE') { console.log(`\n❌ User "${username}" already exists\n`); } else throw e; } } async function editUser() { const users = getAllUsers.all(); if (users.length === 0) { console.log(' No users to edit.\n'); return; } const userId = await select({ message: 'Select user to edit:', choices: users.map(u => ({ name: `${u.username} (${u.role})`, value: u.id })) }); const action = await select({ message: 'What to change?', choices: [ { name: '🔑 Change password', value: 'password' }, { name: '👤 Change role', value: 'role' }, { name: '← Back', value: 'back' } ] }); if (action === 'back') return; if (action === 'password') { const pwd = await password({ message: 'New password:', mask: '*', validate: v => v.length >= 4 || 'Min 4 characters' }); const hash = await bcrypt.hash(pwd, 10); updateUserPassword.run(hash, userId); console.log('\n✅ Password updated\n'); } if (action === 'role') { const user = getUserById.get(userId); const newRole = await select({ message: 'New role:', choices: [ { name: '👤 user', value: 'user' }, { name: '👑 admin', value: 'admin' } ], default: user.role }); updateUserRole.run(newRole, userId); console.log(`\n✅ Role changed to ${newRole}\n`); } } async function removeUser() { const users = getAllUsers.all(); if (users.length === 0) { console.log(' No users to delete.\n'); return; } const userId = await select({ message: 'Select user to delete:', choices: users.map(u => ({ name: `${u.username} (${u.role})`, value: u.id })) }); const user = getUserById.get(userId); const confirmed = await confirm({ message: `Delete user "${user.username}"?`, default: false }); if (confirmed) { deleteUser.run(userId); console.log(`\n✅ User "${user.username}" deleted\n`); } else { console.log('\n❌ Cancelled\n'); } } async function main() { while (true) { try { const action = await select({ message: 'What would you like to do?', choices: [ { name: '📋 List users', value: 'list' }, { name: '➕ Create user', value: 'create' }, { name: '✏️ Edit user', value: 'edit' }, { name: '🗑️ Delete user', value: 'delete' }, { name: '🚪 Exit', value: 'exit' } ] }); if (action === 'exit') { console.log('Bye!\n'); break; } if (action === 'list') await listUsers(); if (action === 'create') await createUser(); if (action === 'edit') await editUser(); if (action === 'delete') await removeUser(); } catch (e) { if (e.name === 'ExitPromptError') { console.log('\nBye!\n'); break; } throw e; } } } main();