This commit is contained in:
sebseb7
2025-12-21 01:43:19 +01:00
parent 6b9ebb5ea0
commit 97056ebc5c
10 changed files with 2322 additions and 13 deletions

195
manage-users.js Normal file
View File

@@ -0,0 +1,195 @@
#!/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();