Files
actest/manage-users.js
sebseb7 97056ebc5c u
2025-12-21 01:43:19 +01:00

196 lines
6.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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();