forked from Yeraze/meshmonitor
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreset-admin.mjs
More file actions
110 lines (99 loc) · 3.64 KB
/
Copy pathreset-admin.mjs
File metadata and controls
110 lines (99 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import bcrypt from 'bcrypt';
// Generate a new random password
function generatePassword() {
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789!@#$%^&*';
let password = '';
for (let i = 0; i < 20; i++) {
password += chars.charAt(Math.floor(Math.random() * chars.length));
}
return password;
}
function printSuccess(newPassword) {
console.log('');
console.log('═══════════════════════════════════════════════════════════');
console.log('🔐 Admin password has been reset');
console.log('═══════════════════════════════════════════════════════════');
console.log(` Username: admin`);
console.log(` Password: ${newPassword}`);
console.log('');
console.log(' ⚠️ IMPORTANT: Save this password now!');
console.log('═══════════════════════════════════════════════════════════');
console.log('');
}
function printNotFound() {
console.error('Failed to reset password - admin user not found');
console.error('');
console.error('If you have not yet started the application, start it first');
console.error('to create the default admin account, then run this script.');
}
// Detect database type from DATABASE_URL
function detectDatabaseType() {
const url = process.env.DATABASE_URL;
if (url) {
const lower = url.toLowerCase();
if (lower.startsWith('postgres://') || lower.startsWith('postgresql://')) return 'postgres';
if (lower.startsWith('mysql://') || lower.startsWith('mariadb://')) return 'mysql';
}
return 'sqlite';
}
async function resetSqlite(hashedPassword) {
const Database = (await import('better-sqlite3')).default;
const dbPath = process.env.DATABASE_PATH || '/data/meshmonitor.db';
const db = new Database(dbPath);
try {
const stmt = db.prepare(
'UPDATE users SET password_hash = ?, is_active = 1, password_locked = 0 WHERE username = ?'
);
const result = stmt.run(hashedPassword, 'admin');
return result.changes > 0;
} finally {
db.close();
}
}
async function resetPostgres(hashedPassword) {
const pg = await import('pg');
const pool = new pg.default.Pool({ connectionString: process.env.DATABASE_URL });
try {
const result = await pool.query(
'UPDATE users SET "passwordHash" = $1, "isActive" = true, "passwordLocked" = false WHERE username = $2',
[hashedPassword, 'admin']
);
return result.rowCount > 0;
} finally {
await pool.end();
}
}
async function resetMysql(hashedPassword) {
const mysql = await import('mysql2/promise');
const pool = mysql.createPool(process.env.DATABASE_URL);
try {
const [result] = await pool.query(
'UPDATE users SET passwordHash = ?, isActive = true, passwordLocked = false WHERE username = ?',
[hashedPassword, 'admin']
);
return result.affectedRows > 0;
} finally {
await pool.end();
}
}
const dbType = detectDatabaseType();
console.log(`Detected database: ${dbType}`);
const newPassword = generatePassword();
const hashedPassword = await bcrypt.hash(newPassword, 10);
let success = false;
switch (dbType) {
case 'sqlite':
success = await resetSqlite(hashedPassword);
break;
case 'postgres':
success = await resetPostgres(hashedPassword);
break;
case 'mysql':
success = await resetMysql(hashedPassword);
break;
}
if (success) {
printSuccess(newPassword);
} else {
printNotFound();
}