mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-30 18:46:00 +00:00
41c541828f
The first-run seeder only applies ADMIN_EMAIL/ADMIN_PASSWORD on an empty database and then silently ignores them. People add the vars after the first boot, or pull a fresh image without clearing ./data, restart, and cannot log in with no hint why (#1339). The default is a generated password (not the .env.example placeholder), printed once in the first-run box. Now: warn loudly when the vars are set but a user already exists, and warn on a partial (one-of-two) config instead of quietly falling back. Also ship the reset-admin recovery script in the image -- it was never COPYed in despite the wiki referencing it. node server/reset-admin.js resets/creates admin@trek.local with a generated password (RESET_ADMIN_EMAIL/RESET_ADMIN_PASSWORD overridable), picks a free username so it cannot trip UNIQUE(username), and sets must_change_password.
51 lines
2.1 KiB
JavaScript
51 lines
2.1 KiB
JavaScript
/**
|
|
* Admin recovery — reset (or create) an admin account when you are locked out.
|
|
*
|
|
* Usage inside the container:
|
|
* docker exec -it trek node server/reset-admin.js
|
|
* docker exec -it -e RESET_ADMIN_EMAIL=me@example.com -e RESET_ADMIN_PASSWORD=secret trek node server/reset-admin.js
|
|
*
|
|
* Defaults to admin@trek.local with a generated password (printed below). The
|
|
* account is flagged must_change_password, so you are prompted to set a new one
|
|
* on first login. Honours TREK_DB_FILE the same way the server does.
|
|
*/
|
|
const path = require('path');
|
|
const crypto = require('crypto');
|
|
const Database = require('better-sqlite3');
|
|
const bcrypt = require('bcryptjs');
|
|
|
|
// Kept in sync with the seeder/authService cost factor.
|
|
const BCRYPT_COST = 12;
|
|
|
|
const email = process.env.RESET_ADMIN_EMAIL || 'admin@trek.local';
|
|
const password = process.env.RESET_ADMIN_PASSWORD || crypto.randomBytes(12).toString('base64url');
|
|
const generated = !process.env.RESET_ADMIN_PASSWORD;
|
|
|
|
const dbPath = process.env.TREK_DB_FILE || path.join(__dirname, 'data/travel.db');
|
|
const db = new Database(dbPath);
|
|
|
|
const hash = bcrypt.hashSync(password, BCRYPT_COST);
|
|
const existing = db.prepare('SELECT id FROM users WHERE email = ?').get(email);
|
|
|
|
if (existing) {
|
|
db.prepare('UPDATE users SET password_hash = ?, role = ?, must_change_password = 1 WHERE email = ?')
|
|
.run(hash, 'admin', email);
|
|
console.log(`\n✓ Admin password reset: ${email}`);
|
|
} else {
|
|
// 'admin' is usually taken by the first-run seed — pick the first free username
|
|
// so the insert can't trip the UNIQUE(username) constraint.
|
|
let username = 'admin';
|
|
let n = 1;
|
|
while (db.prepare('SELECT 1 FROM users WHERE username = ?').get(username)) {
|
|
username = `admin${n++}`;
|
|
}
|
|
db.prepare('INSERT INTO users (username, email, password_hash, role, must_change_password) VALUES (?, ?, ?, ?, 1)')
|
|
.run(username, email, hash, 'admin');
|
|
console.log(`\n✓ Admin account created: ${email} (username: ${username})`);
|
|
}
|
|
|
|
if (generated) console.log(` Password: ${password}`);
|
|
console.log(' You will be asked to change the password on first login.\n');
|
|
|
|
db.close();
|