Update AUTH_README.md to clarify admin password setup process and provide usage instructions for the set-admin-password script. Change file permissions for deploy.sh, production-setup.sh, and fetch-template.sh to make them executable.
This commit is contained in:
@@ -7,9 +7,23 @@
|
|||||||
|
|
||||||
⚠️ **WICHTIG:** Ändern Sie dieses Passwort sofort nach der ersten Anmeldung!
|
⚠️ **WICHTIG:** Ändern Sie dieses Passwort sofort nach der ersten Anmeldung!
|
||||||
|
|
||||||
## Passwort-Hash generieren
|
## Admin-Passwort setzen
|
||||||
|
|
||||||
Um einen neuen Benutzer oder ein neues Passwort zu erstellen, können Sie folgenden Node.js-Code verwenden:
|
Das einfachste Verfahren ist das Script `scripts/set-admin-password.js`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Mit Passwort als Argument
|
||||||
|
node scripts/set-admin-password.js "mein-neues-passwort"
|
||||||
|
|
||||||
|
# Oder interaktiv (Passwort wird abgefragt)
|
||||||
|
node scripts/set-admin-password.js
|
||||||
|
```
|
||||||
|
|
||||||
|
Siehe auch: `scripts/README-set-admin-password.md`
|
||||||
|
|
||||||
|
## Passwort-Hash generieren (manuell)
|
||||||
|
|
||||||
|
Falls Sie einen Passwort-Hash manuell generieren möchten, können Sie folgenden Node.js-Code verwenden:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import bcrypt from 'bcryptjs'
|
import bcrypt from 'bcryptjs'
|
||||||
|
|||||||
0
production-setup.sh
Normal file → Executable file
0
production-setup.sh
Normal file → Executable file
56
scripts/README-set-admin-password.md
Normal file
56
scripts/README-set-admin-password.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Admin-Passwort setzen
|
||||||
|
|
||||||
|
Dieses Script ermöglicht es, das Passwort für den Admin-User (`admin@harheimertc.de`) zu setzen oder zu ändern.
|
||||||
|
|
||||||
|
## Verwendung
|
||||||
|
|
||||||
|
### Mit Passwort als Argument
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node scripts/set-admin-password.js "mein-neues-passwort"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Interaktiv (Passwort wird abgefragt)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node scripts/set-admin-password.js
|
||||||
|
```
|
||||||
|
|
||||||
|
Das Script fragt dann nach dem neuen Passwort.
|
||||||
|
|
||||||
|
## Funktionen
|
||||||
|
|
||||||
|
- **Findet oder erstellt den Admin-User**: Falls der Admin-User nicht existiert, wird er automatisch erstellt
|
||||||
|
- **Passwort-Hashing**: Das Passwort wird mit bcrypt gehasht (10 Runden)
|
||||||
|
- **Verschlüsselte Speicherung**: Die Benutzerdaten werden verschlüsselt gespeichert
|
||||||
|
- **Validierung**: Prüft, dass das Passwort mindestens 8 Zeichen lang ist
|
||||||
|
|
||||||
|
## Voraussetzungen
|
||||||
|
|
||||||
|
- `ENCRYPTION_KEY` muss in der `.env` Datei gesetzt sein (für verschlüsselte Speicherung)
|
||||||
|
- Die Datei `server/data/users.json` muss existieren oder wird automatisch erstellt
|
||||||
|
|
||||||
|
## Beispiel
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Passwort direkt setzen
|
||||||
|
node scripts/set-admin-password.js "MeinSicheresPasswort123!"
|
||||||
|
|
||||||
|
# Interaktiv
|
||||||
|
node scripts/set-admin-password.js
|
||||||
|
# Eingabeaufforderung: Neues Passwort für admin@harheimertc.de:
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sicherheit
|
||||||
|
|
||||||
|
- Das Passwort wird niemals im Klartext gespeichert
|
||||||
|
- Es wird mit bcrypt gehasht (10 Runden)
|
||||||
|
- Die Benutzerdaten werden verschlüsselt gespeichert
|
||||||
|
- Das Passwort wird nicht in der Kommandozeilen-Historie gespeichert (bei interaktiver Eingabe)
|
||||||
|
|
||||||
|
## Fehlerbehandlung
|
||||||
|
|
||||||
|
Falls die Entschlüsselung der Benutzerdaten fehlschlägt:
|
||||||
|
- Prüfe, ob `ENCRYPTION_KEY` in der `.env` Datei korrekt gesetzt ist
|
||||||
|
- Stelle sicher, dass der Schlüssel mit dem übereinstimmt, der zum Verschlüsseln verwendet wurde
|
||||||
|
|
||||||
0
scripts/fetch-template.sh
Normal file → Executable file
0
scripts/fetch-template.sh
Normal file → Executable file
200
scripts/set-admin-password.js
Executable file
200
scripts/set-admin-password.js
Executable file
@@ -0,0 +1,200 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* Script zum Setzen des Admin-Passworts
|
||||||
|
*
|
||||||
|
* Verwendung:
|
||||||
|
* node scripts/set-admin-password.js <neues-passwort>
|
||||||
|
*
|
||||||
|
* Oder interaktiv:
|
||||||
|
* node scripts/set-admin-password.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
import fs from 'fs/promises'
|
||||||
|
import path from 'path'
|
||||||
|
import { fileURLToPath } from 'url'
|
||||||
|
import bcrypt from 'bcryptjs'
|
||||||
|
import { decryptObject, encryptObject } from '../server/utils/encryption.js'
|
||||||
|
import dotenv from 'dotenv'
|
||||||
|
import readline from 'readline'
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url)
|
||||||
|
const __dirname = path.dirname(__filename)
|
||||||
|
|
||||||
|
// Lade .env Datei
|
||||||
|
dotenv.config({ path: path.join(__dirname, '..', '.env') })
|
||||||
|
|
||||||
|
const ADMIN_EMAIL = 'admin@harheimertc.de'
|
||||||
|
|
||||||
|
// Pfade bestimmen
|
||||||
|
function getDataPath(filename) {
|
||||||
|
const cwd = process.cwd()
|
||||||
|
if (cwd.endsWith('.output')) {
|
||||||
|
return path.join(cwd, '../server/data', filename)
|
||||||
|
}
|
||||||
|
return path.join(cwd, 'server/data', filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
const USERS_FILE = getDataPath('users.json')
|
||||||
|
|
||||||
|
// Get encryption key from environment
|
||||||
|
function getEncryptionKey() {
|
||||||
|
return process.env.ENCRYPTION_KEY || 'local_development_encryption_key_change_in_production'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prüft ob Daten verschlüsselt sind
|
||||||
|
function isEncrypted(data) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(data.trim())
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (typeof parsed === 'object' && parsed !== null && !parsed.encryptedData) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
} catch (e) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liest Benutzer aus Datei
|
||||||
|
async function readUsers() {
|
||||||
|
try {
|
||||||
|
const data = await fs.readFile(USERS_FILE, 'utf-8')
|
||||||
|
const encrypted = isEncrypted(data)
|
||||||
|
|
||||||
|
if (encrypted) {
|
||||||
|
const encryptionKey = getEncryptionKey()
|
||||||
|
try {
|
||||||
|
return decryptObject(data, encryptionKey)
|
||||||
|
} catch (decryptError) {
|
||||||
|
console.error('Fehler beim Entschlüsseln der Benutzerdaten:', decryptError.message)
|
||||||
|
throw new Error('Konnte Benutzerdaten nicht entschlüsseln. Bitte prüfe ENCRYPTION_KEY in .env')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return JSON.parse(data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code === 'ENOENT') {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schreibt Benutzer in Datei (immer verschlüsselt)
|
||||||
|
async function writeUsers(users) {
|
||||||
|
try {
|
||||||
|
const encryptionKey = getEncryptionKey()
|
||||||
|
const encryptedData = encryptObject(users, encryptionKey)
|
||||||
|
await fs.writeFile(USERS_FILE, encryptedData, 'utf-8')
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Fehler beim Schreiben der Benutzerdaten:', error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash-Passwort generieren
|
||||||
|
async function hashPassword(password) {
|
||||||
|
const salt = await bcrypt.genSalt(10)
|
||||||
|
return await bcrypt.hash(password, salt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fragt nach Passwort (wenn nicht als Argument übergeben)
|
||||||
|
function askPassword() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const rl = readline.createInterface({
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout
|
||||||
|
})
|
||||||
|
|
||||||
|
rl.question('Neues Passwort für admin@harheimertc.de: ', (password) => {
|
||||||
|
rl.close()
|
||||||
|
resolve(password)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hauptfunktion
|
||||||
|
async function main() {
|
||||||
|
console.log('🔐 Admin-Passwort setzen\n')
|
||||||
|
|
||||||
|
// Passwort aus Kommandozeilenargumenten oder interaktiv abfragen
|
||||||
|
let newPassword = process.argv[2]
|
||||||
|
|
||||||
|
if (!newPassword) {
|
||||||
|
newPassword = await askPassword()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newPassword || newPassword.trim().length === 0) {
|
||||||
|
console.error('❌ FEHLER: Passwort darf nicht leer sein!')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPassword.length < 8) {
|
||||||
|
console.error('❌ FEHLER: Passwort muss mindestens 8 Zeichen lang sein!')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Benutzer laden
|
||||||
|
console.log('📖 Lade Benutzerdaten...')
|
||||||
|
const users = await readUsers()
|
||||||
|
|
||||||
|
// Admin-User finden oder erstellen
|
||||||
|
let adminUser = users.find(u => u.email.toLowerCase() === ADMIN_EMAIL.toLowerCase())
|
||||||
|
|
||||||
|
if (!adminUser) {
|
||||||
|
console.log(`ℹ️ Admin-User (${ADMIN_EMAIL}) nicht gefunden, erstelle neuen Benutzer...`)
|
||||||
|
adminUser = {
|
||||||
|
id: Date.now().toString(),
|
||||||
|
email: ADMIN_EMAIL,
|
||||||
|
name: 'Administrator',
|
||||||
|
role: 'admin',
|
||||||
|
active: true,
|
||||||
|
created: new Date().toISOString(),
|
||||||
|
lastLogin: null
|
||||||
|
}
|
||||||
|
users.push(adminUser)
|
||||||
|
} else {
|
||||||
|
console.log(`✅ Admin-User gefunden: ${adminUser.name || ADMIN_EMAIL}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passwort hashen
|
||||||
|
console.log('🔐 Hashe Passwort...')
|
||||||
|
const hashedPassword = await hashPassword(newPassword)
|
||||||
|
|
||||||
|
// Passwort setzen
|
||||||
|
adminUser.password = hashedPassword
|
||||||
|
adminUser.updated = new Date().toISOString()
|
||||||
|
|
||||||
|
// Benutzer speichern
|
||||||
|
console.log('💾 Speichere Benutzerdaten...')
|
||||||
|
const success = await writeUsers(users)
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
console.log('\n✅ Passwort erfolgreich gesetzt!')
|
||||||
|
console.log(`📧 E-Mail: ${ADMIN_EMAIL}`)
|
||||||
|
console.log(`👤 Rolle: ${adminUser.role}`)
|
||||||
|
console.log(`✅ Status: ${adminUser.active ? 'Aktiv' : 'Inaktiv'}`)
|
||||||
|
} else {
|
||||||
|
console.error('\n❌ FEHLER: Konnte Benutzerdaten nicht speichern!')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('\n❌ FEHLER:', error.message)
|
||||||
|
if (error.message.includes('entschlüsseln')) {
|
||||||
|
console.error('\n💡 Tipp: Stelle sicher, dass ENCRYPTION_KEY in der .env Datei korrekt gesetzt ist.')
|
||||||
|
}
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Script ausführen
|
||||||
|
main().catch(error => {
|
||||||
|
console.error('Unerwarteter Fehler:', error)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
|
|
||||||
Reference in New Issue
Block a user