Add email functionality to AuthService; implement password reset email feature with nodemailer, including transporter initialization and email template for user notifications.
This commit is contained in:
178
backend/SQL_EXECUTION_ORDER.md
Normal file
178
backend/SQL_EXECUTION_ORDER.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# TimeClock v3 - SQL-Scripts Ausführungsreihenfolge
|
||||
|
||||
Diese Anleitung zeigt, welche SQL-Scripts in welcher Reihenfolge ausgeführt werden müssen.
|
||||
|
||||
## Auf dem Server ausführen:
|
||||
|
||||
```bash
|
||||
cd /var/www/timeclock/backend
|
||||
|
||||
# DB-Credentials aus .env
|
||||
DB_HOST=$(grep DB_HOST .env | cut -d= -f2)
|
||||
DB_USER=$(grep DB_USER .env | cut -d= -f2)
|
||||
DB_PASSWORD=$(grep DB_PASSWORD .env | cut -d= -f2)
|
||||
DB_NAME=$(grep DB_NAME .env | cut -d= -f2)
|
||||
|
||||
# Alias für einfachere Befehle
|
||||
alias dbexec="mysql -h $DB_HOST -u $DB_USER -p'$DB_PASSWORD' $DB_NAME"
|
||||
```
|
||||
|
||||
## 1. Basis-Schema (WICHTIG - zuerst!)
|
||||
|
||||
```bash
|
||||
# Erstellt alle Haupt-Tabellen
|
||||
dbexec < database-schema.sql
|
||||
|
||||
# Zeige erstellte Tabellen
|
||||
dbexec -e "SHOW TABLES;"
|
||||
```
|
||||
|
||||
## 2. Zusätzliche Tabellen
|
||||
|
||||
```bash
|
||||
# Invitation Table
|
||||
dbexec < create-invitation-table.sql
|
||||
|
||||
# Watcher Table
|
||||
dbexec < create-watcher-table.sql
|
||||
```
|
||||
|
||||
## 3. Indices für Performance
|
||||
|
||||
```bash
|
||||
# Sick Index
|
||||
dbexec < add-sick-index.sql
|
||||
|
||||
# Vacation Index
|
||||
dbexec < add-vacation-index.sql
|
||||
```
|
||||
|
||||
## 4. Timewish Setup (korrigierte Version!)
|
||||
|
||||
```bash
|
||||
# Timewish mit Zeiträumen
|
||||
dbexec < setup-timewish-complete.sql
|
||||
|
||||
# ODER falls noch Fehler: Nur die Spalten hinzufügen
|
||||
dbexec << 'EOF'
|
||||
-- Prüfe ob start_date existiert
|
||||
SET @col_exists = (SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'timewish'
|
||||
AND COLUMN_NAME = 'start_date');
|
||||
|
||||
SET @sql = IF(@col_exists = 0,
|
||||
'ALTER TABLE timewish ADD COLUMN start_date DATE DEFAULT ''2023-01-01'' AFTER end_time;',
|
||||
'SELECT ''start_date existiert bereits'';'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- end_date
|
||||
SET @col_exists = (SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'timewish'
|
||||
AND COLUMN_NAME = 'end_date');
|
||||
|
||||
SET @sql = IF(@col_exists = 0,
|
||||
'ALTER TABLE timewish ADD COLUMN end_date DATE DEFAULT NULL AFTER start_date;',
|
||||
'SELECT ''end_date existiert bereits'';'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
EOF
|
||||
```
|
||||
|
||||
## 5. Optionale Scripts (nur bei Bedarf!)
|
||||
|
||||
### User als Admin setzen
|
||||
```bash
|
||||
# Passe user_id an! (Deine User-ID aus der users-Tabelle)
|
||||
dbexec < set-user-admin.sql
|
||||
```
|
||||
|
||||
### Timezone-Fixes (nur falls Probleme mit Zeitzonen)
|
||||
```bash
|
||||
# Worklog Timezone korrigieren
|
||||
dbexec < fix-worklog-timezone.sql
|
||||
```
|
||||
|
||||
### Overtime Offset Update
|
||||
```bash
|
||||
dbexec < update-overtime-offset.sql
|
||||
```
|
||||
|
||||
### Wednesday-Fix (nur falls benötigt)
|
||||
```bash
|
||||
dbexec < add-missing-wednesday.sql
|
||||
```
|
||||
|
||||
## Überprüfung
|
||||
|
||||
```bash
|
||||
# Zeige alle Tabellen
|
||||
dbexec -e "SHOW TABLES;"
|
||||
|
||||
# Zeige timewish-Struktur
|
||||
dbexec -e "DESCRIBE timewish;"
|
||||
|
||||
# Zeige Anzahl User
|
||||
dbexec -e "SELECT COUNT(*) AS user_count FROM users;"
|
||||
|
||||
# Zeige deine Timewishes
|
||||
dbexec -e "SELECT * FROM timewish WHERE user_id = 1 ORDER BY day, start_date;"
|
||||
```
|
||||
|
||||
## Nach SQL-Ausführung: Backend neu starten
|
||||
|
||||
```bash
|
||||
# Backend neu starten damit es die neuen Tabellen/Spalten erkennt
|
||||
pm2 restart timeclock-backend
|
||||
|
||||
# Logs prüfen
|
||||
pm2 logs timeclock-backend --lines 30
|
||||
|
||||
# Sollte zeigen:
|
||||
# 🕐 TimeClock Server läuft auf Port 3010
|
||||
# 📍 API verfügbar unter http://localhost:3010/api
|
||||
```
|
||||
|
||||
## Schnell-Befehl (alle wichtigen Scripts):
|
||||
|
||||
```bash
|
||||
cd /var/www/timeclock/backend
|
||||
|
||||
# DB-Credentials setzen
|
||||
DB_HOST=$(grep DB_HOST .env | cut -d= -f2)
|
||||
DB_USER=$(grep DB_USER .env | cut -d= -f2)
|
||||
DB_PASSWORD=$(grep DB_PASSWORD .env | cut -d= -f2)
|
||||
DB_NAME=$(grep DB_NAME .env | cut -d= -f2)
|
||||
|
||||
echo "Führe SQL-Scripts aus..."
|
||||
|
||||
# 1. Basis-Schema
|
||||
mysql -h $DB_HOST -u $DB_USER -p"$DB_PASSWORD" $DB_NAME < database-schema.sql 2>&1 | grep -v "already exists" || true
|
||||
|
||||
# 2. Zusätzliche Tabellen
|
||||
mysql -h $DB_HOST -u $DB_USER -p"$DB_PASSWORD" $DB_NAME < create-invitation-table.sql 2>&1 | grep -v "already exists" || true
|
||||
mysql -h $DB_HOST -u $DB_USER -p"$DB_PASSWORD" $DB_NAME < create-watcher-table.sql 2>&1 | grep -v "already exists" || true
|
||||
|
||||
# 3. Indices
|
||||
mysql -h $DB_HOST -u $DB_USER -p"$DB_PASSWORD" $DB_NAME < add-sick-index.sql 2>&1 || true
|
||||
mysql -h $DB_HOST -u $DB_USER -p"$DB_PASSWORD" $DB_NAME < add-vacation-index.sql 2>&1 || true
|
||||
|
||||
# 4. Timewish (korrigiert)
|
||||
mysql -h $DB_HOST -u $DB_USER -p"$DB_PASSWORD" $DB_NAME < setup-timewish-complete.sql
|
||||
|
||||
echo "✅ SQL-Scripts ausgeführt!"
|
||||
|
||||
# Backend neu starten
|
||||
pm2 restart timeclock-backend
|
||||
|
||||
echo "✅ Backend neu gestartet!"
|
||||
```
|
||||
|
||||
Kopiere diesen Schnell-Befehl auf den Server und führe ihn aus! 🚀
|
||||
|
||||
96
backend/reset-user-password.js
Executable file
96
backend/reset-user-password.js
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Reset User Password für TimeClock v3
|
||||
// Verwendung: node reset-user-password.js "email@example.com" "neues-passwort"
|
||||
|
||||
require('dotenv').config();
|
||||
const bcrypt = require('bcrypt');
|
||||
const mysql = require('mysql2/promise');
|
||||
|
||||
async function resetPassword() {
|
||||
const email = process.argv[2];
|
||||
const newPassword = process.argv[3];
|
||||
|
||||
if (!email || !newPassword) {
|
||||
console.error('❌ Verwendung: node reset-user-password.js "email@example.com" "neues-passwort"');
|
||||
console.error('');
|
||||
console.error('Beispiel:');
|
||||
console.error(' node reset-user-password.js "tsschulz@gmx.net" "MeinNeuesPasswort123!"');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('🔐 Setze neues Passwort für TimeClock v3...');
|
||||
console.log('Email:', email);
|
||||
console.log('');
|
||||
|
||||
try {
|
||||
// Datenbank-Verbindung
|
||||
const connection = await mysql.createConnection({
|
||||
host: process.env.DB_HOST,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_NAME
|
||||
});
|
||||
|
||||
console.log('✅ Datenbank verbunden');
|
||||
|
||||
// Neuen Hash erstellen (Node.js bcrypt, kompatibel mit der neuen App)
|
||||
const saltRounds = 10;
|
||||
const passwordHash = await bcrypt.hash(newPassword, saltRounds);
|
||||
|
||||
console.log('✅ Passwort gehasht');
|
||||
console.log('Neuer Hash:', passwordHash);
|
||||
console.log('Hash-Format:', passwordHash.substring(0, 4));
|
||||
console.log('');
|
||||
|
||||
// Update authinfo
|
||||
const [result] = await connection.execute(
|
||||
`UPDATE authinfo
|
||||
SET password_hash = ?,
|
||||
password_method = 'bcrypt',
|
||||
email = ?,
|
||||
status = 1,
|
||||
failed_login_attempts = 0
|
||||
WHERE email = ? OR unverified_email = ?`,
|
||||
[passwordHash, email, email, email]
|
||||
);
|
||||
|
||||
if (result.affectedRows === 0) {
|
||||
console.error('❌ Kein Benutzer mit dieser E-Mail gefunden!');
|
||||
console.log('');
|
||||
console.log('Verfügbare Benutzer:');
|
||||
const [users] = await connection.execute(
|
||||
'SELECT id, user_id, email, unverified_email FROM authinfo'
|
||||
);
|
||||
console.table(users);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('✅ Passwort erfolgreich aktualisiert!');
|
||||
console.log('Betroffene Zeilen:', result.affectedRows);
|
||||
console.log('');
|
||||
|
||||
// Zeige aktualisierte Daten
|
||||
const [authInfo] = await connection.execute(
|
||||
'SELECT id, user_id, email, password_method, status, failed_login_attempts FROM authinfo WHERE email = ?',
|
||||
[email]
|
||||
);
|
||||
|
||||
console.log('📋 Aktualisierte AuthInfo:');
|
||||
console.table(authInfo);
|
||||
|
||||
console.log('');
|
||||
console.log('🎉 Fertig! Du kannst dich jetzt mit folgenden Daten einloggen:');
|
||||
console.log(' Email:', email);
|
||||
console.log(' Passwort:', newPassword);
|
||||
|
||||
await connection.end();
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
resetPassword();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const bcrypt = require('bcrypt');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const crypto = require('crypto');
|
||||
const nodemailer = require('nodemailer');
|
||||
const database = require('../config/database');
|
||||
|
||||
/**
|
||||
@@ -12,6 +13,28 @@ class AuthService {
|
||||
this.jwtSecret = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
|
||||
this.jwtExpiration = process.env.JWT_EXPIRATION || '24h';
|
||||
this.saltRounds = 10;
|
||||
this.emailTransporter = null;
|
||||
this.initializeEmailTransporter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialisiert den Email-Transporter
|
||||
*/
|
||||
initializeEmailTransporter() {
|
||||
if (process.env.EMAIL_HOST && process.env.EMAIL_USER && process.env.EMAIL_PASSWORD) {
|
||||
this.emailTransporter = nodemailer.createTransport({
|
||||
host: process.env.EMAIL_HOST,
|
||||
port: parseInt(process.env.EMAIL_PORT) || 587,
|
||||
secure: process.env.EMAIL_SECURE === 'true',
|
||||
auth: {
|
||||
user: process.env.EMAIL_USER,
|
||||
pass: process.env.EMAIL_PASSWORD
|
||||
}
|
||||
});
|
||||
console.log('✅ Email-Transporter konfiguriert');
|
||||
} else {
|
||||
console.warn('⚠️ Email-Konfiguration fehlt - Passwort-Reset-E-Mails können nicht versendet werden');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,6 +257,71 @@ class AuthService {
|
||||
email_token_role: 1 // 1 = Password Reset
|
||||
});
|
||||
|
||||
// E-Mail versenden (falls konfiguriert)
|
||||
if (this.emailTransporter) {
|
||||
const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5010';
|
||||
const resetUrl = `${frontendUrl}/password-reset?token=${resetToken}`;
|
||||
|
||||
const mailOptions = {
|
||||
from: `"${process.env.EMAIL_FROM_NAME || 'TimeClock'}" <${process.env.EMAIL_FROM}>`,
|
||||
to: email,
|
||||
subject: 'TimeClock - Passwort zurücksetzen',
|
||||
text: `Hallo,
|
||||
|
||||
du hast eine Passwort-Zurücksetzen-Anfrage für dein TimeClock-Konto gestellt.
|
||||
|
||||
Klicke auf folgenden Link um dein Passwort zurückzusetzen:
|
||||
${resetUrl}
|
||||
|
||||
Dieser Link ist 1 Stunde gültig.
|
||||
|
||||
Falls du diese Anfrage nicht gestellt hast, ignoriere diese E-Mail.
|
||||
|
||||
---
|
||||
TimeClock Zeiterfassung
|
||||
${frontendUrl}
|
||||
`,
|
||||
html: `
|
||||
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
|
||||
<h2 style="color: #333;">Passwort zurücksetzen</h2>
|
||||
<p>Hallo,</p>
|
||||
<p>du hast eine Passwort-Zurücksetzen-Anfrage für dein TimeClock-Konto gestellt.</p>
|
||||
<p>
|
||||
<a href="${resetUrl}" style="display: inline-block; padding: 12px 24px; background-color: #4CAF50; color: white; text-decoration: none; border-radius: 4px; margin: 16px 0;">
|
||||
Passwort zurücksetzen
|
||||
</a>
|
||||
</p>
|
||||
<p style="color: #666; font-size: 14px;">
|
||||
Oder kopiere diesen Link in deinen Browser:<br>
|
||||
<code style="background: #f5f5f5; padding: 4px 8px; border-radius: 4px; display: inline-block; margin-top: 8px;">${resetUrl}</code>
|
||||
</p>
|
||||
<p style="color: #666; font-size: 14px;">
|
||||
<strong>Dieser Link ist 1 Stunde gültig.</strong>
|
||||
</p>
|
||||
<p style="color: #666; font-size: 14px;">
|
||||
Falls du diese Anfrage nicht gestellt hast, ignoriere diese E-Mail.
|
||||
</p>
|
||||
<hr style="border: none; border-top: 1px solid #ddd; margin: 24px 0;">
|
||||
<p style="color: #999; font-size: 12px;">
|
||||
TimeClock Zeiterfassung<br>
|
||||
<a href="${frontendUrl}">${frontendUrl}</a>
|
||||
</p>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
|
||||
try {
|
||||
await this.emailTransporter.sendMail(mailOptions);
|
||||
console.log('✅ Passwort-Reset E-Mail gesendet an:', email);
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim E-Mail-Versand:', error.message);
|
||||
// Werfe keinen Fehler - Token wurde gespeichert, User kann es anders nutzen
|
||||
}
|
||||
} else {
|
||||
console.warn('⚠️ E-Mail-Transporter nicht konfiguriert - Reset-Token erstellt aber keine E-Mail versendet');
|
||||
console.log('Reset-Token:', resetToken);
|
||||
}
|
||||
|
||||
return resetToken;
|
||||
}
|
||||
|
||||
|
||||
115
backend/test-email.js
Executable file
115
backend/test-email.js
Executable file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Test E-Mail-Konfiguration
|
||||
// Verwendung: node test-email.js "empfaenger@example.com"
|
||||
|
||||
require('dotenv').config();
|
||||
const nodemailer = require('nodemailer');
|
||||
|
||||
const recipientEmail = process.argv[2] || 'tsschulz@gmx.net';
|
||||
|
||||
console.log('📧 Teste E-Mail-Konfiguration...');
|
||||
console.log('');
|
||||
console.log('SMTP-Server:', process.env.EMAIL_HOST);
|
||||
console.log('Port:', process.env.EMAIL_PORT);
|
||||
console.log('Secure:', process.env.EMAIL_SECURE);
|
||||
console.log('User:', process.env.EMAIL_USER);
|
||||
console.log('From:', process.env.EMAIL_FROM);
|
||||
console.log('An:', recipientEmail);
|
||||
console.log('');
|
||||
|
||||
// Erstelle Transporter
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: process.env.EMAIL_HOST,
|
||||
port: parseInt(process.env.EMAIL_PORT),
|
||||
secure: process.env.EMAIL_SECURE === 'true',
|
||||
auth: {
|
||||
user: process.env.EMAIL_USER,
|
||||
pass: process.env.EMAIL_PASSWORD
|
||||
}
|
||||
});
|
||||
|
||||
// Test-E-Mail senden
|
||||
async function sendTestEmail() {
|
||||
try {
|
||||
console.log('🔄 Verbinde mit SMTP-Server...');
|
||||
|
||||
// Verify connection
|
||||
await transporter.verify();
|
||||
console.log('✅ SMTP-Verbindung erfolgreich!');
|
||||
console.log('');
|
||||
|
||||
console.log('📤 Sende Test-E-Mail...');
|
||||
|
||||
const info = await transporter.sendMail({
|
||||
from: `"${process.env.EMAIL_FROM_NAME || 'TimeClock'}" <${process.env.EMAIL_FROM}>`,
|
||||
to: recipientEmail,
|
||||
subject: 'TimeClock v3 - Test E-Mail',
|
||||
text: `Dies ist eine Test-E-Mail von TimeClock v3.
|
||||
|
||||
Wenn du diese E-Mail erhältst, funktioniert die E-Mail-Konfiguration korrekt!
|
||||
|
||||
Gesendet am: ${new Date().toLocaleString('de-DE')}
|
||||
|
||||
---
|
||||
TimeClock v3 Zeiterfassung
|
||||
${process.env.FRONTEND_URL || 'https://stechuhr3.tsschulz.de'}
|
||||
`,
|
||||
html: `
|
||||
<h2>TimeClock v3 - Test E-Mail</h2>
|
||||
<p>Dies ist eine Test-E-Mail von TimeClock v3.</p>
|
||||
<p><strong>Wenn du diese E-Mail erhältst, funktioniert die E-Mail-Konfiguration korrekt!</strong></p>
|
||||
<p>Gesendet am: ${new Date().toLocaleString('de-DE')}</p>
|
||||
<hr>
|
||||
<p style="color: #666; font-size: 12px;">
|
||||
TimeClock v3 Zeiterfassung<br>
|
||||
<a href="${process.env.FRONTEND_URL || 'https://stechuhr3.tsschulz.de'}">${process.env.FRONTEND_URL || 'https://stechuhr3.tsschulz.de'}</a>
|
||||
</p>
|
||||
`
|
||||
});
|
||||
|
||||
console.log('');
|
||||
console.log('✅ E-Mail erfolgreich gesendet!');
|
||||
console.log('');
|
||||
console.log('Message ID:', info.messageId);
|
||||
console.log('Response:', info.response);
|
||||
console.log('');
|
||||
console.log('🎉 E-Mail-Konfiguration funktioniert!');
|
||||
console.log('');
|
||||
console.log('📬 Prüfe dein E-Mail-Postfach:', recipientEmail);
|
||||
console.log(' (inkl. Spam-Ordner)');
|
||||
|
||||
process.exit(0);
|
||||
|
||||
} catch (error) {
|
||||
console.error('');
|
||||
console.error('❌ Fehler beim E-Mail-Versand:');
|
||||
console.error('');
|
||||
console.error(error.message);
|
||||
console.error('');
|
||||
|
||||
if (error.code === 'EAUTH') {
|
||||
console.error('💡 SMTP-Authentifizierung fehlgeschlagen!');
|
||||
console.error(' Prüfe EMAIL_USER und EMAIL_PASSWORD in .env');
|
||||
} else if (error.code === 'ECONNECTION') {
|
||||
console.error('💡 Verbindung zum SMTP-Server fehlgeschlagen!');
|
||||
console.error(' Prüfe EMAIL_HOST und EMAIL_PORT in .env');
|
||||
} else if (error.code === 'ETIMEDOUT') {
|
||||
console.error('💡 Timeout beim Verbinden!');
|
||||
console.error(' Prüfe Firewall-Einstellungen (Port', process.env.EMAIL_PORT, ')');
|
||||
}
|
||||
|
||||
console.error('');
|
||||
console.error('Aktuelle Konfiguration:');
|
||||
console.error(' EMAIL_HOST:', process.env.EMAIL_HOST);
|
||||
console.error(' EMAIL_PORT:', process.env.EMAIL_PORT);
|
||||
console.error(' EMAIL_SECURE:', process.env.EMAIL_SECURE);
|
||||
console.error(' EMAIL_USER:', process.env.EMAIL_USER);
|
||||
console.error(' EMAIL_FROM:', process.env.EMAIL_FROM);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
sendTestEmail();
|
||||
|
||||
45
backend/test-password.js
Normal file
45
backend/test-password.js
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Test-Script für Passwort-Verifizierung
|
||||
// Verwendung: node test-password.js "dein-passwort"
|
||||
|
||||
const bcrypt = require('bcrypt');
|
||||
|
||||
const hash = '$2y$07$cSnPaBjKKlmtOTKtbTDTTuYQ0bZ0upNQfNWf7gf8OKiz8eEjwSGFG';
|
||||
const password = process.argv[2];
|
||||
|
||||
if (!password) {
|
||||
console.error('❌ Verwendung: node test-password.js "dein-passwort"');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('🔐 Teste Passwort-Verifizierung...');
|
||||
console.log('Hash:', hash);
|
||||
console.log('Hash-Format:', hash.substring(0, 4));
|
||||
console.log('');
|
||||
|
||||
// bcrypt.compare kann $2y$ Hashes lesen (PHP-Format)
|
||||
bcrypt.compare(password, hash)
|
||||
.then(isMatch => {
|
||||
if (isMatch) {
|
||||
console.log('✅ Passwort ist KORREKT!');
|
||||
console.log('');
|
||||
console.log('Das Passwort-Hashing funktioniert.');
|
||||
console.log('Problem liegt woanders (z.B. Salt, Email-Matching, etc.)');
|
||||
} else {
|
||||
console.log('❌ Passwort ist FALSCH!');
|
||||
console.log('');
|
||||
console.log('Entweder:');
|
||||
console.log('1. Falsches Passwort eingegeben');
|
||||
console.log('2. Hash wurde anders erstellt (Salt-Problem)');
|
||||
console.log('3. Passwort muss neu gesetzt werden');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('❌ Fehler beim Vergleich:', err.message);
|
||||
console.log('');
|
||||
console.log('Mögliche Ursachen:');
|
||||
console.log('- $2y$ Format wird nicht unterstützt');
|
||||
console.log('- Hash ist korrupt');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user