- Timestamp:
- 08/21/2026 08:00:05 AM (3 weeks ago)
- Branches:
- main
- Children:
- bb9e54c
- Parents:
- 1294c36
- File:
-
- 1 edited
-
scripts/reset-admin.mjs (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
scripts/reset-admin.mjs
r1294c36 r0f09302 4 4 // 5 5 // Usage: 6 // npm run reset-admin # reset the (first) god user, print new password 7 // npm run reset-admin -- <user|email> # reset a specific user, print new password 8 // npm run reset-admin -- <user|email> <pw> # set a chosen password 6 // npm run reset-admin # reset the (first) god user, print new password 7 // npm run reset-admin -- <user|email> # reset a specific user, print new password 8 // npm run reset-admin -- <user|email> <pw> # set a chosen password 9 // npm run reset-admin -- --instance <slug> [...] # pick an instance (shared code, /var/lib/klonkt) 9 10 // 10 // Run from the project root so DATABASE_PATH/.env is loaded correctly. 11 // Run from the project root so DATABASE_PATH/.env is loaded correctly, or name 12 // the instance with --instance. 11 13 12 import 'dotenv/config'; 14 import fs from 'fs'; 15 import path from 'path'; 13 16 import crypto from 'crypto'; 17 import { fileURLToPath } from 'url'; 18 import dotenv from 'dotenv'; 14 19 import bcrypt from 'bcryptjs'; 15 import db from '../src/config/database.js';16 20 17 const arg = process.argv[2]; 18 const pwArg = process.argv[3]; 21 const __dirname = path.dirname(fileURLToPath(import.meta.url)); 22 const wortel = path.join(__dirname, '..'); 23 24 // De argumenten: --instance mag overal staan, de rest is stelling-afhankelijk. 25 const argv = process.argv.slice(2); 26 let slug = null; 27 const rest = []; 28 for (let i = 0; i < argv.length; i++) { 29 const a = argv[i]; 30 if (a === '--instance' || a === '-i') { slug = argv[++i] || null; continue; } 31 if (a.startsWith('--instance=')) { slug = a.slice('--instance='.length); continue; } 32 rest.push(a); 33 } 34 const [arg, pwArg] = rest; 35 36 if (slug !== null && !slug) { 37 console.error('--instance verwacht een slug, bijvoorbeeld: --instance boiert'); 38 process.exit(1); 39 } 40 41 // WAAR DE CONFIGURATIE VANDAAN KOMT, en waarom dit meer dan één regel is. 42 // 43 // Bij één-instantie-per-checkout staat de .env naast de code en vindt dotenv 44 // hem vanzelf. In de gedeelde opstelling van deploy/klonkt@.service niet: daar 45 // is de code gedeeld op /opt/klonkt en staat de configuratie per instantie in 46 // /var/lib/klonkt/<slug>/.env, waar SYSTEMD hem leest via EnvironmentFile. 47 // Dotenv kijkt in de werkmap en vindt daar niets, dus zonder --instance draait 48 // dit script met een lege DATABASE_PATH -- en dan wijst hij de verkeerde kant 49 // op. Vandaar deze schakelaar. 50 const DATA_ROOT = process.env.KLONKT_DATA_ROOT || '/var/lib/klonkt'; 51 if (slug) { 52 const envPad = path.join(DATA_ROOT, slug, '.env'); 53 if (!fs.existsSync(envPad)) { 54 console.error(`Geen .env voor instantie "${slug}" op ${envPad}.`); 55 console.error(`Bestaande instanties: ${bestaandeInstanties().join(', ') || '(geen gevonden)'}`); 56 console.error('Staat je data ergens anders? Zet KLONKT_DATA_ROOT.'); 57 process.exit(1); 58 } 59 // override: dotenv laat een bestaande variabele normaal met rust, maar wie 60 // --instance typt heeft die instantie AANGEWEZEN. Een DATABASE_PATH die nog 61 // in de shell hangt van een vorige instantie zou anders stilletjes winnen, 62 // en dan reset je het wachtwoord van de verkeerde site. 63 dotenv.config({ path: envPad, override: true }); 64 } else { 65 dotenv.config(); 66 } 67 68 function bestaandeInstanties() { 69 try { 70 return fs.readdirSync(DATA_ROOT).filter((d) => fs.existsSync(path.join(DATA_ROOT, d, '.env'))); 71 } catch { return []; } 72 } 73 74 // EERST KIJKEN, DAN PAS IMPORTEREN. src/config/database.js maakt zijn map en 75 // zijn bestand aan zodra hij geladen wordt -- prima bij de eerste start van een 76 // server, funest hier: sta je in de verkeerde map, dan legt hij een lege 77 // database neer en klapt daarna op "no such table: users". Dat is een 78 // stacktrace op de plek waar een aanwijzing hoort te staan. Dus dezelfde 79 // padkeuze als database.js, maar dan alleen berekend. 80 const dbPad = process.env.DATABASE_PATH || path.join(wortel, 'storage/database.sqlite'); 81 if (!fs.existsSync(dbPad)) { 82 console.error(`Geen database op ${dbPad}.`); 83 console.error(''); 84 console.error('Dit script maakt er met opzet geen aan: een ontbrekende database betekent'); 85 console.error('bijna altijd dat DATABASE_PATH niet geladen is, niet dat de site leeg is.'); 86 console.error(''); 87 if (!slug) { 88 const gevonden = bestaandeInstanties(); 89 if (gevonden.length) { 90 console.error(`Gedeelde opstelling? Noem de instantie: npm run reset-admin -- --instance <slug>`); 91 console.error(`Gevonden in ${DATA_ROOT}: ${gevonden.join(', ')}`); 92 } else { 93 console.error('Draai dit vanuit de projectmap, zodat de .env ernaast geladen wordt,'); 94 console.error('of geef het pad mee: DATABASE_PATH=/pad/naar/database.sqlite npm run reset-admin'); 95 } 96 } 97 process.exit(1); 98 } 99 100 const { default: db } = await import('../src/config/database.js'); 19 101 20 102 let user; 21 if (arg) { 22 user = db.prepare('SELECT * FROM users WHERE username = ? OR LOWER(email) = LOWER(?)').get(arg, arg); 23 } else { 24 // No arg: pick the admin (god or admin role), otherwise the very first user. 25 user = 26 db.prepare("SELECT * FROM users WHERE role IN ('god','admin') ORDER BY created_at LIMIT 1").get() || 27 db.prepare('SELECT * FROM users ORDER BY created_at LIMIT 1').get(); 103 try { 104 if (arg) { 105 user = db.prepare('SELECT * FROM users WHERE username = ? OR LOWER(email) = LOWER(?)').get(arg, arg); 106 } else { 107 // No arg: pick the admin (god or admin role), otherwise the very first user. 108 user = 109 db.prepare("SELECT * FROM users WHERE role IN ('god','admin') ORDER BY created_at LIMIT 1").get() || 110 db.prepare('SELECT * FROM users ORDER BY created_at LIMIT 1').get(); 111 } 112 } catch (e) { 113 // Een database zonder users-tabel is geen lege site maar het verkeerde 114 // bestand -- of een checkout die nog nooit gestart is. 115 if (/no such table/i.test(e.message)) { 116 console.error(`De database op ${dbPad} heeft geen users-tabel.`); 117 console.error('Dat is een ander bestand dan je site, of een site die nooit gestart is.'); 118 process.exit(1); 119 } 120 throw e; 28 121 } 29 122 30 123 if (!user) { 31 124 console.error(arg ? `Geen user gevonden voor "${arg}".` : 'Geen god-user gevonden.'); 125 console.error(`Gezocht in ${dbPad}.`); 32 126 process.exit(1); 33 127 } … … 45 139 46 140 console.log(`Wachtwoord gereset voor ${user.username} <${user.email}> (rol: ${user.role}).`); 141 console.log(`Database: ${dbPad}`); 47 142 if (!pwArg) console.log(`Nieuw wachtwoord: ${newPw}`); 48 143 console.log('Log nu in via /auth/login en wijzig het eventueel in je account.');
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)