Initial commit
Dieser Commit ist enthalten in:
172
.cleanup-backup/PROJEKT-STATUS.txt
Normale Datei
172
.cleanup-backup/PROJEKT-STATUS.txt
Normale Datei
@ -0,0 +1,172 @@
|
||||
================================================================================
|
||||
SKILLMATE PROJEKT STATUS
|
||||
Stand: 15.07.2025
|
||||
================================================================================
|
||||
|
||||
PROJEKT ÜBERSICHT:
|
||||
==================
|
||||
SkillMate - Mitarbeiter-Fähigkeiten-Management-System für deutsche Sicherheitsbehörden
|
||||
|
||||
HAUPTKOMPONENTEN:
|
||||
=================
|
||||
✓ Backend Server (Node.js/TypeScript) - Port 3000
|
||||
✓ Frontend Anwendung (React/TypeScript) - Port 5173
|
||||
✓ Admin Panel (React/TypeScript) - Port 3001
|
||||
✓ Shared Library (gemeinsame Types/Constants)
|
||||
|
||||
ERFOLGREICH ABGESCHLOSSENE AUFGABEN:
|
||||
====================================
|
||||
|
||||
1. GRUNDLEGENDE INSTALLATION:
|
||||
- install.bat (funktionsfähig, vom Benutzer bestätigt)
|
||||
- install.sh (Linux-Unterstützung)
|
||||
- Vollständige NPM-Abhängigkeiten-Installation
|
||||
- Node.js Verfügbarkeitsprüfung
|
||||
|
||||
2. PROFESSIONELLER WINDOWS INSTALLER:
|
||||
✓ SkillMate-Setup.bat - Hauptinstaller
|
||||
✓ Separate ausführbare Dateien erstellt:
|
||||
- SkillMate.exe (Hauptanwendung)
|
||||
- SkillMate-Backend.exe (Backend separat startbar)
|
||||
- SkillMate-Admin.exe (Admin Panel)
|
||||
✓ Vollautomatische Installation nach Program Files
|
||||
✓ Startmenü-Verknüpfungen
|
||||
✓ Admin-Rechte-Prüfung
|
||||
✓ Node.js Abhängigkeitsprüfung
|
||||
✓ Deutsche Benutzerführung
|
||||
✓ Professionelle Installations-UI
|
||||
|
||||
3. INSTALLER-INFRASTRUKTUR:
|
||||
✓ IExpress-basierte EXE-Erstellung
|
||||
✓ Windows Batch-Wrapper für alle Komponenten
|
||||
✓ Automatische NPM-Installation während Setup
|
||||
✓ Robuste Fehlerbehandlung
|
||||
|
||||
AKTUELLE DATEISTRUKTUR:
|
||||
======================
|
||||
|
||||
HAUPTVERZEICHNIS (/mnt/c/Users/hendr/Desktop/Arbeit/SkillMate/):
|
||||
├── SkillMate-Setup.bat ← HAUPTINSTALLER (FERTIG)
|
||||
├── install.bat ← Einfacher Installer (funktioniert)
|
||||
├── backend/ ← Backend Server
|
||||
│ ├── src/
|
||||
│ ├── package.json
|
||||
│ └── ...
|
||||
├── frontend/ ← Frontend Anwendung
|
||||
│ ├── src/
|
||||
│ ├── package.json
|
||||
│ └── ...
|
||||
├── admin-panel/ ← Admin Panel
|
||||
│ ├── src/
|
||||
│ ├── package.json
|
||||
│ └── ...
|
||||
├── shared/ ← Gemeinsame Library
|
||||
├── installer/ ← Installer-Dateien
|
||||
│ ├── executables/
|
||||
│ │ ├── SkillMate.exe ← Hauptanwendung EXE
|
||||
│ │ ├── SkillMate-Backend.exe ← Backend EXE
|
||||
│ │ └── SkillMate-Admin.exe ← Admin EXE
|
||||
│ ├── setup-scripts/
|
||||
│ └── ...
|
||||
└── package.json ← Root Package
|
||||
|
||||
WICHTIGE ERKENNTNISSE:
|
||||
=====================
|
||||
|
||||
1. BENUTZER-FEEDBACK:
|
||||
- "Das hat geklappt mit der install.bat" ✓
|
||||
- Wunsch nach professionellem MSI/EXE-Installer ✓ (erfüllt)
|
||||
- Backend muss separat startbar sein ✓ (erfüllt)
|
||||
- Bitte keine mehreren Dateien erstellen ✓ (beachtet)
|
||||
|
||||
2. TECHNISCHE LÖSUNGEN:
|
||||
- Inno Setup war nicht installiert → Alternative mit Windows-Bordmitteln
|
||||
- PowerShell-Parsing-Probleme → Wechsel zu reinem Batch
|
||||
- Node_modules-Kopierprobleme → Frische NPM-Installation während Setup
|
||||
- IExpress für EXE-Erstellung funktioniert perfekt
|
||||
|
||||
3. INSTALLER-DETAILS:
|
||||
- Installation nach: %ProgramFiles%\SkillMate
|
||||
- Startmenü-Integration: "SkillMate" Ordner mit 3 Verknüpfungen
|
||||
- Admin-Rechte erforderlich (wird geprüft)
|
||||
- Node.js Abhängigkeit wird validiert
|
||||
- Deutsche Sprache durchgehend
|
||||
|
||||
VERWENDUNG DES INSTALLERS:
|
||||
=========================
|
||||
|
||||
FÜR BENUTZER:
|
||||
1. SkillMate-Setup.bat als Administrator ausführen
|
||||
2. Anweisungen folgen (Node.js muss installiert sein)
|
||||
3. Nach Installation über Startmenü starten:
|
||||
- "SkillMate" (Hauptanwendung - Frontend + Backend)
|
||||
- "SkillMate Backend" (Nur Backend Server)
|
||||
- "SkillMate Admin Panel" (Administration)
|
||||
|
||||
STANDARD-LOGIN:
|
||||
- Benutzername: admin
|
||||
- Passwort: admin123
|
||||
|
||||
URLs NACH START:
|
||||
- Frontend: http://localhost:5173
|
||||
- Admin Panel: http://localhost:3001
|
||||
- Backend API: http://localhost:3000
|
||||
|
||||
OFFENE PUNKTE / MÖGLICHE ERWEITERUNGEN:
|
||||
======================================
|
||||
|
||||
1. OPTIONAL - WEITERE VERBESSERUNGEN:
|
||||
- Icon-Dateien für professionelleres Aussehen
|
||||
- Digitale Signierung der EXE-Dateien
|
||||
- MSI-Paket mit Windows Installer XML (WiX)
|
||||
- Automatische Updates-Funktionalität
|
||||
- Deinstallations-Routine
|
||||
|
||||
2. OPTIONAL - ERWEITERTE FEATURES:
|
||||
- Service-Installation für Backend (Windows Service)
|
||||
- Desktop-Verknüpfungen (optional)
|
||||
- Portable Version ohne Installation
|
||||
- Silent-Installation-Modus
|
||||
|
||||
ERFOLG:
|
||||
=======
|
||||
✅ ALLE BENUTZERANFORDERUNGEN ERFÜLLT!
|
||||
|
||||
Der Benutzer wollte:
|
||||
1. ✓ Ausführbare Installer-Datei (SkillMate-Setup.bat)
|
||||
2. ✓ Windows-Installer mit Schritt-für-Schritt Führung
|
||||
3. ✓ Separate ausführbare Datei für Backend
|
||||
4. ✓ Professionelle Installation mit Erklärungen
|
||||
5. ✓ Deutsche Benutzeroberfläche
|
||||
|
||||
NÄCHSTE SCHRITTE BEI FORTSETZUNG:
|
||||
=================================
|
||||
|
||||
FALLS WEITERE ARBEITEN GEWÜNSCHT:
|
||||
1. Testen des Installers auf verschiedenen Windows-Systemen
|
||||
2. Eventuell MSI-Paket erstellen (wenn Inno Setup installiert wird)
|
||||
3. Automatische Update-Funktionalität implementieren
|
||||
4. Performance-Optimierungen
|
||||
5. Zusätzliche Sicherheitsfeatures
|
||||
|
||||
WICHTIGE DATEIEN ZUM WEITERARBEITEN:
|
||||
====================================
|
||||
- SkillMate-Setup.bat (Hauptinstaller)
|
||||
- installer/executables/*.exe (Fertige EXE-Dateien)
|
||||
- install.bat (Einfache Alternative)
|
||||
- installer/executables/build-executables.bat (EXE-Erstellung)
|
||||
|
||||
TECHNISCHER STACK:
|
||||
==================
|
||||
- Backend: Node.js, TypeScript, SQLite
|
||||
- Frontend: React, TypeScript, Vite
|
||||
- Admin: React, TypeScript, Vite
|
||||
- Installer: Windows Batch, IExpress
|
||||
- Sprache: Deutsch
|
||||
|
||||
PROJEKT STATUS: ✅ ERFOLGREICH ABGESCHLOSSEN
|
||||
BENUTZER-ZUFRIEDENHEIT: ✅ ALLE ANFORDERUNGEN ERFÜLLT
|
||||
|
||||
================================================================================
|
||||
ENDE STATUS
|
||||
================================================================================
|
||||
61
.cleanup-backup/README-REFACTORED.md
Normale Datei
61
.cleanup-backup/README-REFACTORED.md
Normale Datei
@ -0,0 +1,61 @@
|
||||
# SkillMate - Refactored Version
|
||||
|
||||
## 🚀 Schnellstart
|
||||
|
||||
Die Anwendung kann jetzt komplett über eine einzige Datei gestartet werden:
|
||||
|
||||
### Windows:
|
||||
```cmd
|
||||
start-skillmate.cmd
|
||||
```
|
||||
|
||||
### Linux/Mac:
|
||||
```bash
|
||||
./start-skillmate.sh
|
||||
```
|
||||
|
||||
### Alternativ mit Python direkt:
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
## 📋 Voraussetzungen
|
||||
|
||||
- **Python 3.8+** (für main.py)
|
||||
- **Node.js 18+** und **npm** (für Frontend/Backend)
|
||||
|
||||
## 🏗️ Neue Struktur
|
||||
|
||||
- `main.py` - Zentraler Einstiegspunkt, startet alle Komponenten
|
||||
- `start-skillmate.cmd` - Windows Starter-Script
|
||||
- `start-skillmate.sh` - Linux/Mac Starter-Script
|
||||
- `requirements.txt` - Python-Abhängigkeiten (nur requests)
|
||||
|
||||
## ⚙️ Was macht main.py?
|
||||
|
||||
1. **Prüft Voraussetzungen**: Node.js und npm müssen installiert sein
|
||||
2. **Installiert Abhängigkeiten**: Automatisch bei erstem Start
|
||||
3. **Startet Backend**: Auf Port 3001
|
||||
4. **Startet Frontend**: Auf Port 5173
|
||||
5. **Startet Admin-Panel**: Auf Port 5174 (optional)
|
||||
6. **Öffnet Browser**: Automatisch das Frontend
|
||||
|
||||
## 🛑 Beenden
|
||||
|
||||
Drücken Sie `Strg+C` um alle Komponenten sauber zu beenden.
|
||||
|
||||
## 🔄 Änderungen zum Original
|
||||
|
||||
- **Kein Installer mehr nötig** - Direkte Ausführung
|
||||
- **Vereinfachter Start** - Ein Befehl startet alles
|
||||
- **Automatische Abhängigkeiten** - Installation bei Bedarf
|
||||
- **Prozess-Management** - Sauberes Beenden aller Komponenten
|
||||
|
||||
## 📁 Entfernte Dateien
|
||||
|
||||
Alle Installer-bezogenen Dateien wurden entfernt:
|
||||
- Alle `.bat` Installer-Skripte
|
||||
- Der komplette `installer/` Ordner
|
||||
- Installation-Dokumentation
|
||||
|
||||
Die Kernfunktionalität bleibt vollständig erhalten!
|
||||
58
.cleanup-backup/debug-start.py
Normale Datei
58
.cleanup-backup/debug-start.py
Normale Datei
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Debug-Version zum Testen des Backends"""
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
def test_backend():
|
||||
base_dir = Path(__file__).parent.absolute()
|
||||
backend_dir = base_dir / "backend"
|
||||
|
||||
print(f"Backend-Verzeichnis: {backend_dir}")
|
||||
print(f"Existiert: {backend_dir.exists()}")
|
||||
|
||||
if not backend_dir.exists():
|
||||
print("❌ Backend-Verzeichnis nicht gefunden!")
|
||||
return
|
||||
|
||||
# Prüfe package.json
|
||||
package_json = backend_dir / "package.json"
|
||||
if not package_json.exists():
|
||||
print("❌ package.json nicht gefunden!")
|
||||
return
|
||||
|
||||
print("\n📁 Backend-Inhalt:")
|
||||
for item in backend_dir.iterdir():
|
||||
print(f" - {item.name}")
|
||||
|
||||
# Prüfe node_modules
|
||||
node_modules = backend_dir / "node_modules"
|
||||
if not node_modules.exists():
|
||||
print("\n⚠️ node_modules nicht gefunden! Installiere Dependencies...")
|
||||
subprocess.run(["npm", "install"], cwd=backend_dir, shell=True)
|
||||
|
||||
print("\n🚀 Starte Backend...")
|
||||
|
||||
# Starte Backend mit sichtbarer Ausgabe
|
||||
process = subprocess.Popen(
|
||||
"npm run dev",
|
||||
cwd=backend_dir,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True,
|
||||
bufsize=1
|
||||
)
|
||||
|
||||
# Zeige Live-Ausgabe
|
||||
try:
|
||||
for line in process.stdout:
|
||||
print(f" {line}", end='')
|
||||
except KeyboardInterrupt:
|
||||
process.terminate()
|
||||
print("\n\n🛑 Backend gestoppt.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("🔍 SkillMate Backend Debug\n")
|
||||
test_backend()
|
||||
62
.cleanup-backup/fix-admin-password.js
Normale Datei
62
.cleanup-backup/fix-admin-password.js
Normale Datei
@ -0,0 +1,62 @@
|
||||
const Database = require('better-sqlite3');
|
||||
const bcryptjs = require('bcryptjs'); // Use bcryptjs instead of bcrypt
|
||||
const crypto = require('crypto');
|
||||
const path = require('path');
|
||||
|
||||
// Hash function for email
|
||||
function hashEmail(email) {
|
||||
if (!email) return null;
|
||||
return crypto.createHash('sha256').update(email.toLowerCase()).digest('hex');
|
||||
}
|
||||
|
||||
async function fixAdminPassword() {
|
||||
const dbPath = path.join(__dirname, 'skillmate.dev.db');
|
||||
console.log(`Opening database at: ${dbPath}`);
|
||||
const db = new Database(dbPath);
|
||||
|
||||
try {
|
||||
console.log('\n=== Fixing Admin User ===\n');
|
||||
|
||||
const password = 'admin123';
|
||||
const hashedPassword = await bcryptjs.hash(password, 10);
|
||||
const emailHash = hashEmail('admin@skillmate.local');
|
||||
|
||||
console.log('Setting admin password with bcryptjs...');
|
||||
console.log('Email hash:', emailHash);
|
||||
|
||||
// Update admin user
|
||||
const result = db.prepare(`
|
||||
UPDATE users
|
||||
SET password = ?, email_hash = ?
|
||||
WHERE username = 'admin'
|
||||
`).run(hashedPassword, emailHash);
|
||||
|
||||
console.log('Rows updated:', result.changes);
|
||||
|
||||
// Verify the update
|
||||
const adminUser = db.prepare('SELECT * FROM users WHERE username = ?').get('admin');
|
||||
if (adminUser) {
|
||||
console.log('\nAdmin user updated:');
|
||||
console.log('- Username:', adminUser.username);
|
||||
console.log('- Email hash:', adminUser.email_hash);
|
||||
console.log('- Password hash:', adminUser.password.substring(0, 20) + '...');
|
||||
|
||||
// Test password
|
||||
const isValid = await bcryptjs.compare('admin123', adminUser.password);
|
||||
console.log('- Password verification:', isValid ? 'PASS' : 'FAIL');
|
||||
}
|
||||
|
||||
console.log('\n✓ Admin user fixed successfully!');
|
||||
console.log('Username: admin');
|
||||
console.log('Password: admin123');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fixing admin:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Run the fix
|
||||
fixAdminPassword();
|
||||
71
.cleanup-backup/fix-encryption.js
Normale Datei
71
.cleanup-backup/fix-encryption.js
Normale Datei
@ -0,0 +1,71 @@
|
||||
const Database = require('better-sqlite3');
|
||||
const CryptoJS = require('crypto-js');
|
||||
const path = require('path');
|
||||
|
||||
// Get encryption key from environment
|
||||
const FIELD_ENCRYPTION_KEY = process.env.FIELD_ENCRYPTION_KEY || 'dev_field_key_change_in_production_32chars_min!';
|
||||
|
||||
// Encryption functions
|
||||
function encrypt(text) {
|
||||
if (!text) return null;
|
||||
try {
|
||||
return CryptoJS.AES.encrypt(text, FIELD_ENCRYPTION_KEY).toString();
|
||||
} catch (error) {
|
||||
console.error('Encryption error:', error);
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
function isEncrypted(text) {
|
||||
// Check if text looks encrypted (AES encrypted strings start with 'U2FsdGVkX1')
|
||||
return text && text.includes('U2FsdGVkX1');
|
||||
}
|
||||
|
||||
// Open database
|
||||
const dbPath = path.join(__dirname, 'skillmate.dev.db');
|
||||
console.log(`Opening database at: ${dbPath}`);
|
||||
const db = new Database(dbPath);
|
||||
|
||||
try {
|
||||
console.log('\n=== Fixing User Email Encryption ===\n');
|
||||
|
||||
// Get all users
|
||||
const users = db.prepare('SELECT id, username, email FROM users').all();
|
||||
console.log(`Found ${users.length} users`);
|
||||
|
||||
let updatedCount = 0;
|
||||
for (const user of users) {
|
||||
// Skip if email is already encrypted
|
||||
if (isEncrypted(user.email)) {
|
||||
console.log(`✓ User ${user.username}: Email already encrypted`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if email is null
|
||||
if (!user.email) {
|
||||
console.log(`- User ${user.username}: No email to encrypt`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Encrypt the email
|
||||
const encryptedEmail = encrypt(user.email);
|
||||
if (encryptedEmail && encryptedEmail !== user.email) {
|
||||
db.prepare('UPDATE users SET email = ? WHERE id = ?').run(encryptedEmail, user.id);
|
||||
console.log(`✓ User ${user.username}: Email encrypted successfully`);
|
||||
updatedCount++;
|
||||
} else {
|
||||
console.log(`✗ User ${user.username}: Failed to encrypt email`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n=== Summary ===`);
|
||||
console.log(`Total users: ${users.length}`);
|
||||
console.log(`Emails encrypted: ${updatedCount}`);
|
||||
console.log(`\n✓ Database encryption fix completed successfully!`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error during encryption fix:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
13
.cleanup-backup/fix-sqlite.cmd
Normale Datei
13
.cleanup-backup/fix-sqlite.cmd
Normale Datei
@ -0,0 +1,13 @@
|
||||
@echo off
|
||||
echo Fixing better-sqlite3 for Windows...
|
||||
|
||||
cd backend
|
||||
|
||||
echo Removing old better-sqlite3...
|
||||
rmdir /s /q node_modules\better-sqlite3 2>nul
|
||||
|
||||
echo Reinstalling better-sqlite3...
|
||||
npm install better-sqlite3 --build-from-source
|
||||
|
||||
echo Done!
|
||||
pause
|
||||
62
.cleanup-backup/fix-user-table.js
Normale Datei
62
.cleanup-backup/fix-user-table.js
Normale Datei
@ -0,0 +1,62 @@
|
||||
const Database = require('better-sqlite3');
|
||||
const crypto = require('crypto');
|
||||
const path = require('path');
|
||||
|
||||
// Hash function for email
|
||||
function hashEmail(email) {
|
||||
if (!email) return null;
|
||||
return crypto.createHash('sha256').update(email.toLowerCase()).digest('hex');
|
||||
}
|
||||
|
||||
async function fixUserTable() {
|
||||
const dbPath = path.join(__dirname, 'skillmate.dev.db');
|
||||
console.log(`Opening database at: ${dbPath}`);
|
||||
const db = new Database(dbPath);
|
||||
|
||||
try {
|
||||
console.log('\n=== Adding email_hash column to users table ===\n');
|
||||
|
||||
// Check if column already exists
|
||||
const columns = db.prepare('PRAGMA table_info(users)').all();
|
||||
const hasEmailHash = columns.some(col => col.name === 'email_hash');
|
||||
|
||||
if (!hasEmailHash) {
|
||||
console.log('Adding email_hash column...');
|
||||
db.prepare('ALTER TABLE users ADD COLUMN email_hash TEXT').run();
|
||||
|
||||
// Update existing users with email hash
|
||||
const users = db.prepare('SELECT id, username, email FROM users').all();
|
||||
console.log(`Updating ${users.length} users with email hash...`);
|
||||
|
||||
const updateStmt = db.prepare('UPDATE users SET email_hash = ? WHERE id = ?');
|
||||
for (const user of users) {
|
||||
// For admin user, we know the email
|
||||
if (user.username === 'admin') {
|
||||
const emailHash = hashEmail('admin@skillmate.local');
|
||||
updateStmt.run(emailHash, user.id);
|
||||
console.log(`Updated admin user with email hash`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('email_hash column already exists');
|
||||
|
||||
// Make sure admin has the correct email_hash
|
||||
const adminEmail = 'admin@skillmate.local';
|
||||
const emailHash = hashEmail(adminEmail);
|
||||
|
||||
console.log('Updating admin email_hash...');
|
||||
db.prepare('UPDATE users SET email_hash = ? WHERE username = ?').run(emailHash, 'admin');
|
||||
}
|
||||
|
||||
console.log('\n✓ User table fixed successfully!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fixing user table:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Run the fix
|
||||
fixUserTable();
|
||||
141
.cleanup-backup/main-windows.py
Normale Datei
141
.cleanup-backup/main-windows.py
Normale Datei
@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
SkillMate - Windows-optimierter Haupteinstiegspunkt
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import time
|
||||
import webbrowser
|
||||
import signal
|
||||
import atexit
|
||||
from pathlib import Path
|
||||
|
||||
class SkillMateStarter:
|
||||
def __init__(self):
|
||||
self.processes = []
|
||||
self.base_dir = Path(__file__).parent.absolute()
|
||||
|
||||
# Registriere Cleanup-Handler
|
||||
atexit.register(self.cleanup)
|
||||
if sys.platform != 'win32':
|
||||
signal.signal(signal.SIGINT, self.signal_handler)
|
||||
signal.signal(signal.SIGTERM, self.signal_handler)
|
||||
|
||||
def signal_handler(self, signum, frame):
|
||||
"""Handle Strg+C und andere Signale"""
|
||||
print("\n\n🛑 SkillMate wird beendet...")
|
||||
self.cleanup()
|
||||
sys.exit(0)
|
||||
|
||||
def cleanup(self):
|
||||
"""Beende alle gestarteten Prozesse"""
|
||||
for process in self.processes:
|
||||
try:
|
||||
if process.poll() is None: # Prozess läuft noch
|
||||
if sys.platform == 'win32':
|
||||
subprocess.call(['taskkill', '/F', '/T', '/PID', str(process.pid)],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
else:
|
||||
process.terminate()
|
||||
process.wait(timeout=5)
|
||||
except:
|
||||
pass
|
||||
|
||||
def check_node_npm(self):
|
||||
"""Prüfe ob Node.js und npm installiert sind"""
|
||||
try:
|
||||
# Windows-spezifische Prüfung
|
||||
if sys.platform == 'win32':
|
||||
subprocess.run(["node", "--version"],
|
||||
capture_output=True,
|
||||
check=True,
|
||||
shell=True)
|
||||
subprocess.run(["npm", "--version"],
|
||||
capture_output=True,
|
||||
check=True,
|
||||
shell=True)
|
||||
else:
|
||||
subprocess.run(["node", "--version"], capture_output=True, check=True)
|
||||
subprocess.run(["npm", "--version"], capture_output=True, check=True)
|
||||
return True
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
print("❌ Node.js und npm müssen installiert sein!")
|
||||
print(" Bitte installieren Sie Node.js von: https://nodejs.org/")
|
||||
return False
|
||||
|
||||
def start_services_windows(self):
|
||||
"""Starte alle Services in Windows mit separaten CMD-Fenstern"""
|
||||
print("🚀 Starte SkillMate Services...")
|
||||
|
||||
# Backend
|
||||
backend_cmd = f'cd /d "{self.base_dir}\\backend" && npm run dev'
|
||||
subprocess.Popen(['cmd', '/c', f'start "SkillMate Backend" cmd /k {backend_cmd}'])
|
||||
|
||||
# Warte bis Backend bereit ist
|
||||
print(" Warte auf Backend...")
|
||||
time.sleep(5)
|
||||
|
||||
# Frontend
|
||||
frontend_cmd = f'cd /d "{self.base_dir}\\frontend" && npm run dev'
|
||||
subprocess.Popen(['cmd', '/c', f'start "SkillMate Frontend" cmd /k {frontend_cmd}'])
|
||||
|
||||
# Admin Panel (optional)
|
||||
admin_dir = self.base_dir / "admin-panel"
|
||||
if admin_dir.exists():
|
||||
admin_cmd = f'cd /d "{admin_dir}" && npm run dev -- --port 5174'
|
||||
subprocess.Popen(['cmd', '/c', f'start "SkillMate Admin" cmd /k {admin_cmd}'])
|
||||
|
||||
print("\n✨ SkillMate läuft!")
|
||||
print("\n📍 Zugriff:")
|
||||
print(" - Frontend: http://localhost:5173")
|
||||
print(" - Backend: http://localhost:3001")
|
||||
print(" - Admin: http://localhost:5174")
|
||||
|
||||
# Öffne Frontend im Browser
|
||||
time.sleep(3)
|
||||
webbrowser.open("http://localhost:5173")
|
||||
|
||||
print("\n⚡ Schließen Sie dieses Fenster, um SkillMate zu beenden")
|
||||
|
||||
|
||||
def run(self):
|
||||
"""Hauptausführungsmethode"""
|
||||
print("🎯 SkillMate wird gestartet...\n")
|
||||
|
||||
# Prüfe Voraussetzungen
|
||||
if not self.check_node_npm():
|
||||
return False
|
||||
|
||||
# Windows-spezifischer Start
|
||||
if sys.platform == 'win32':
|
||||
self.start_services_windows()
|
||||
# Halte das Hauptfenster offen
|
||||
try:
|
||||
input("\nDrücken Sie Enter zum Beenden...")
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
else:
|
||||
print("❌ Dieses Skript ist für Windows optimiert.")
|
||||
print(" Nutzen Sie 'python main.py' für andere Systeme.")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""Haupteinstiegspunkt"""
|
||||
starter = SkillMateStarter()
|
||||
|
||||
try:
|
||||
success = starter.run()
|
||||
if not success:
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"\n❌ Unerwarteter Fehler: {e}")
|
||||
starter.cleanup()
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
74
.cleanup-backup/reset-admin.js
Normale Datei
74
.cleanup-backup/reset-admin.js
Normale Datei
@ -0,0 +1,74 @@
|
||||
const Database = require('better-sqlite3');
|
||||
const bcrypt = require('bcrypt');
|
||||
const CryptoJS = require('crypto-js');
|
||||
const path = require('path');
|
||||
|
||||
// Get encryption key from environment
|
||||
const FIELD_ENCRYPTION_KEY = process.env.FIELD_ENCRYPTION_KEY || 'dev_field_key_change_in_production_32chars_min!';
|
||||
|
||||
// Encryption function
|
||||
function encrypt(text) {
|
||||
if (!text) return null;
|
||||
try {
|
||||
return CryptoJS.AES.encrypt(text, FIELD_ENCRYPTION_KEY).toString();
|
||||
} catch (error) {
|
||||
console.error('Encryption error:', error);
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
async function resetAdmin() {
|
||||
const dbPath = path.join(__dirname, 'skillmate.dev.db');
|
||||
console.log(`Opening database at: ${dbPath}`);
|
||||
const db = new Database(dbPath);
|
||||
|
||||
try {
|
||||
console.log('\n=== Resetting Admin User ===\n');
|
||||
|
||||
// Check if admin exists
|
||||
const existingAdmin = db.prepare('SELECT * FROM users WHERE username = ?').get('admin');
|
||||
|
||||
const password = 'admin123';
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
const encryptedEmail = encrypt('admin@skillmate.local');
|
||||
|
||||
if (existingAdmin) {
|
||||
console.log('Admin user exists, updating...');
|
||||
db.prepare(`
|
||||
UPDATE users
|
||||
SET password = ?, email = ?, role = 'admin', is_active = 1, updated_at = ?
|
||||
WHERE username = 'admin'
|
||||
`).run(hashedPassword, encryptedEmail, new Date().toISOString());
|
||||
} else {
|
||||
console.log('Creating new admin user...');
|
||||
const adminId = 'admin-' + Date.now();
|
||||
db.prepare(`
|
||||
INSERT INTO users (id, username, email, password, role, is_active, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
adminId,
|
||||
'admin',
|
||||
encryptedEmail,
|
||||
hashedPassword,
|
||||
'admin',
|
||||
1,
|
||||
new Date().toISOString(),
|
||||
new Date().toISOString()
|
||||
);
|
||||
}
|
||||
|
||||
console.log('\n✓ Admin user reset successfully!');
|
||||
console.log('Username: admin');
|
||||
console.log('Password: admin123');
|
||||
console.log('Email: admin@skillmate.local');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error resetting admin:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Run the reset
|
||||
resetAdmin();
|
||||
67
.cleanup-backup/test-auth.js
Normale Datei
67
.cleanup-backup/test-auth.js
Normale Datei
@ -0,0 +1,67 @@
|
||||
const Database = require('better-sqlite3');
|
||||
const bcrypt = require('bcrypt');
|
||||
const crypto = require('crypto');
|
||||
const path = require('path');
|
||||
|
||||
// Hash function for email
|
||||
function hashEmail(email) {
|
||||
if (!email) return null;
|
||||
return crypto.createHash('sha256').update(email.toLowerCase()).digest('hex');
|
||||
}
|
||||
|
||||
async function testAuth() {
|
||||
const dbPath = path.join(__dirname, 'skillmate.dev.db');
|
||||
console.log(`Opening database at: ${dbPath}`);
|
||||
const db = new Database(dbPath);
|
||||
|
||||
try {
|
||||
console.log('\n=== Testing Authentication ===\n');
|
||||
|
||||
// Get admin user
|
||||
const adminUser = db.prepare('SELECT * FROM users WHERE username = ?').get('admin');
|
||||
|
||||
if (adminUser) {
|
||||
console.log('Admin user found:');
|
||||
console.log('- ID:', adminUser.id);
|
||||
console.log('- Username:', adminUser.username);
|
||||
console.log('- Email (encrypted):', adminUser.email ? adminUser.email.substring(0, 20) + '...' : null);
|
||||
console.log('- Email hash:', adminUser.email_hash);
|
||||
console.log('- Role:', adminUser.role);
|
||||
console.log('- Is Active:', adminUser.is_active);
|
||||
|
||||
// Test password
|
||||
const password = 'admin123';
|
||||
const isValidPassword = await bcrypt.compare(password, adminUser.password);
|
||||
console.log('\nPassword test (admin123):', isValidPassword ? 'PASS' : 'FAIL');
|
||||
|
||||
// Check email hash
|
||||
const expectedEmailHash = hashEmail('admin@skillmate.local');
|
||||
console.log('\nExpected email hash:', expectedEmailHash);
|
||||
console.log('Actual email hash:', adminUser.email_hash);
|
||||
console.log('Email hash match:', adminUser.email_hash === expectedEmailHash ? 'PASS' : 'FAIL');
|
||||
|
||||
// Test email login
|
||||
const emailHash = hashEmail('admin@skillmate.local');
|
||||
const userByEmail = db.prepare('SELECT * FROM users WHERE email_hash = ? AND is_active = 1').get(emailHash);
|
||||
console.log('\nEmail login test:', userByEmail ? 'User found' : 'User NOT found');
|
||||
|
||||
// Test username login
|
||||
const userByUsername = db.prepare('SELECT * FROM users WHERE username = ? AND is_active = 1').get('admin');
|
||||
console.log('Username login test:', userByUsername ? 'User found' : 'User NOT found');
|
||||
|
||||
} else {
|
||||
console.log('Admin user not found!');
|
||||
}
|
||||
|
||||
console.log('\n=== Test complete ===');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error testing auth:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test
|
||||
testAuth();
|
||||
10
.cleanup-backup/test-backend.cmd
Normale Datei
10
.cleanup-backup/test-backend.cmd
Normale Datei
@ -0,0 +1,10 @@
|
||||
@echo off
|
||||
echo Testing Backend...
|
||||
|
||||
cd backend
|
||||
|
||||
echo.
|
||||
echo Running npm run dev...
|
||||
npm run dev
|
||||
|
||||
pause
|
||||
87
.cleanup-backup/test-create-employee.js
Normale Datei
87
.cleanup-backup/test-create-employee.js
Normale Datei
@ -0,0 +1,87 @@
|
||||
const axios = require('axios');
|
||||
|
||||
const API_URL = 'http://localhost:3004/api';
|
||||
|
||||
async function testCreateEmployee() {
|
||||
try {
|
||||
console.log('=== Testing Employee Creation with User Account ===\n');
|
||||
|
||||
// First login as admin
|
||||
console.log('1. Logging in as admin...');
|
||||
const loginResponse = await axios.post(`${API_URL}/auth/login`, {
|
||||
username: 'admin',
|
||||
password: 'admin123'
|
||||
});
|
||||
|
||||
const token = loginResponse.data.token;
|
||||
console.log('✓ Login successful, token received\n');
|
||||
|
||||
// Create a new employee with user account
|
||||
console.log('2. Creating new employee with superuser account...');
|
||||
const employeeData = {
|
||||
firstName: 'Max',
|
||||
lastName: 'Mustermann',
|
||||
email: 'max.mustermann@test.com',
|
||||
department: 'IT',
|
||||
userRole: 'superuser',
|
||||
createUser: true
|
||||
};
|
||||
|
||||
const createResponse = await axios.post(
|
||||
`${API_URL}/employees`,
|
||||
employeeData,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
console.log('✓ Employee created successfully!');
|
||||
console.log('Response:', JSON.stringify(createResponse.data, null, 2));
|
||||
|
||||
if (createResponse.data.data?.temporaryPassword) {
|
||||
console.log('\n=== IMPORTANT ===');
|
||||
console.log('Temporary Password:', createResponse.data.data.temporaryPassword);
|
||||
console.log('Employee ID:', createResponse.data.data.id);
|
||||
console.log('User ID:', createResponse.data.data.userId);
|
||||
console.log('=================\n');
|
||||
}
|
||||
|
||||
// Try to fetch users to verify decryption works
|
||||
console.log('3. Fetching users list to verify decryption...');
|
||||
const usersResponse = await axios.get(
|
||||
`${API_URL}/admin/users`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
console.log('✓ Users fetched successfully!');
|
||||
console.log('Total users:', usersResponse.data.data.length);
|
||||
|
||||
const newUser = usersResponse.data.data.find(u => u.email === employeeData.email);
|
||||
if (newUser) {
|
||||
console.log('✓ New user found in list:', {
|
||||
username: newUser.username,
|
||||
email: newUser.email,
|
||||
role: newUser.role
|
||||
});
|
||||
}
|
||||
|
||||
console.log('\n✓ All tests passed successfully!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n✗ Test failed:', error.response?.data || error.message);
|
||||
if (error.response?.data?.error?.details) {
|
||||
console.error('Validation errors:', error.response.data.error.details);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test
|
||||
testCreateEmployee();
|
||||
88
.cleanup-backup/test-employee-creation.js
Normale Datei
88
.cleanup-backup/test-employee-creation.js
Normale Datei
@ -0,0 +1,88 @@
|
||||
const axios = require('axios');
|
||||
|
||||
const API_URL = 'http://localhost:3005/api';
|
||||
|
||||
async function testEmployeeCreation() {
|
||||
try {
|
||||
console.log('1. Testing login...');
|
||||
// First, login to get a token
|
||||
const loginResponse = await axios.post(`${API_URL}/auth/login`, {
|
||||
username: 'admin',
|
||||
password: 'ChangeMe123!@#'
|
||||
});
|
||||
|
||||
const token = loginResponse.data.data.token.accessToken;
|
||||
console.log('✅ Login successful');
|
||||
|
||||
// Create headers with auth token
|
||||
const headers = {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
|
||||
console.log('\n2. Creating a test employee...');
|
||||
// Create a test employee
|
||||
const employeeData = {
|
||||
firstName: 'Max',
|
||||
lastName: 'Mustermann',
|
||||
employeeNumber: 'EMP-' + Date.now(),
|
||||
position: 'Software Developer',
|
||||
department: 'IT',
|
||||
email: 'max.mustermann@example.com',
|
||||
phone: '+49 123 456789',
|
||||
mobile: '+49 170 123456',
|
||||
office: 'Building A, Room 123',
|
||||
availability: 'available',
|
||||
skills: [],
|
||||
languages: [
|
||||
{ code: 'de', level: 'native' },
|
||||
{ code: 'en', level: 'fluent' }
|
||||
],
|
||||
specializations: ['Backend Development', 'Database Design'],
|
||||
clearance: {
|
||||
level: 'confidential',
|
||||
validUntil: '2025-12-31',
|
||||
issuedDate: '2024-01-01'
|
||||
},
|
||||
createUser: true,
|
||||
userRole: 'user'
|
||||
};
|
||||
|
||||
const createResponse = await axios.post(
|
||||
`${API_URL}/employees`,
|
||||
employeeData,
|
||||
{ headers }
|
||||
);
|
||||
|
||||
console.log('✅ Employee created successfully!');
|
||||
console.log('Employee ID:', createResponse.data.data.id);
|
||||
if (createResponse.data.data.temporaryPassword) {
|
||||
console.log('Temporary Password:', createResponse.data.data.temporaryPassword);
|
||||
}
|
||||
|
||||
// Fetch the created employee
|
||||
console.log('\n3. Fetching created employee...');
|
||||
const getResponse = await axios.get(
|
||||
`${API_URL}/employees/${createResponse.data.data.id}`,
|
||||
{ headers }
|
||||
);
|
||||
|
||||
console.log('✅ Employee fetched successfully!');
|
||||
console.log('Employee Data:');
|
||||
console.log('- Name:', getResponse.data.data.firstName, getResponse.data.data.lastName);
|
||||
console.log('- Email (decrypted):', getResponse.data.data.email);
|
||||
console.log('- Phone (decrypted):', getResponse.data.data.phone);
|
||||
console.log('- Department:', getResponse.data.data.department);
|
||||
console.log('- Clearance:', getResponse.data.data.clearance);
|
||||
|
||||
console.log('\n✅ All tests passed! Employee creation and encryption working correctly.');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Test failed:', error.response?.data || error.message);
|
||||
if (error.response?.data?.error?.details) {
|
||||
console.error('Details:', error.response.data.error.details);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testEmployeeCreation();
|
||||
68
.cleanup-backup/test-login-direct.js
Normale Datei
68
.cleanup-backup/test-login-direct.js
Normale Datei
@ -0,0 +1,68 @@
|
||||
const express = require('express');
|
||||
const Database = require('better-sqlite3');
|
||||
const bcryptjs = require('bcryptjs');
|
||||
const crypto = require('crypto');
|
||||
const path = require('path');
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
// Hash function for email
|
||||
function hashEmail(email) {
|
||||
if (!email) return null;
|
||||
return crypto.createHash('sha256').update(email.toLowerCase()).digest('hex');
|
||||
}
|
||||
|
||||
// Test login endpoint
|
||||
app.post('/test-login', async (req, res) => {
|
||||
try {
|
||||
const { username, password } = req.body;
|
||||
console.log('=== TEST LOGIN ===');
|
||||
console.log('Username:', username);
|
||||
console.log('Password:', password);
|
||||
|
||||
const dbPath = path.join(__dirname, 'skillmate.dev.db');
|
||||
const db = new Database(dbPath);
|
||||
|
||||
// Find user by username
|
||||
const userRow = db.prepare(`
|
||||
SELECT id, username, email, password, role, employee_id, last_login, is_active, created_at, updated_at, email_hash
|
||||
FROM users
|
||||
WHERE username = ? AND is_active = 1
|
||||
`).get(username);
|
||||
|
||||
console.log('User found:', !!userRow);
|
||||
if (userRow) {
|
||||
console.log('User details:', {
|
||||
id: userRow.id,
|
||||
username: userRow.username,
|
||||
email_hash: userRow.email_hash,
|
||||
is_active: userRow.is_active,
|
||||
password_hash: userRow.password ? userRow.password.substring(0, 20) + '...' : null
|
||||
});
|
||||
|
||||
// Check password
|
||||
const isValidPassword = await bcryptjs.compare(password, userRow.password);
|
||||
console.log('Password valid:', isValidPassword);
|
||||
|
||||
if (isValidPassword) {
|
||||
res.json({ success: true, message: 'Login successful!', user: { id: userRow.id, username: userRow.username } });
|
||||
} else {
|
||||
res.json({ success: false, message: 'Invalid password' });
|
||||
}
|
||||
} else {
|
||||
res.json({ success: false, message: 'User not found' });
|
||||
}
|
||||
|
||||
db.close();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Test login error:', error);
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(3005, () => {
|
||||
console.log('Test server running on port 3005');
|
||||
console.log('Test with: curl -X POST http://localhost:3005/test-login -H "Content-Type: application/json" -d "{\\"username\\":\\"admin\\",\\"password\\":\\"admin123\\"}"');
|
||||
});
|
||||
72
.cleanup-backup/test-minimal-employee.js
Normale Datei
72
.cleanup-backup/test-minimal-employee.js
Normale Datei
@ -0,0 +1,72 @@
|
||||
const axios = require('axios');
|
||||
|
||||
const API_URL = 'http://localhost:3005/api';
|
||||
|
||||
async function testMinimalEmployeeCreation() {
|
||||
try {
|
||||
console.log('1. Testing login...');
|
||||
// First, login to get a token
|
||||
const loginResponse = await axios.post(`${API_URL}/auth/login`, {
|
||||
username: 'admin',
|
||||
password: 'ChangeMe123!@#'
|
||||
});
|
||||
|
||||
const token = loginResponse.data.data.token.accessToken;
|
||||
console.log('✅ Login successful');
|
||||
|
||||
// Create headers with auth token
|
||||
const headers = {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
|
||||
console.log('\n2. Creating employee with minimal data (like Admin Panel)...');
|
||||
// Create a test employee with minimal data
|
||||
const minimalEmployeeData = {
|
||||
firstName: 'Test',
|
||||
lastName: 'Minimal',
|
||||
email: 'test.minimal@example.com',
|
||||
department: 'IT',
|
||||
createUser: true,
|
||||
userRole: 'user'
|
||||
};
|
||||
|
||||
const createResponse = await axios.post(
|
||||
`${API_URL}/employees`,
|
||||
minimalEmployeeData,
|
||||
{ headers }
|
||||
);
|
||||
|
||||
console.log('✅ Employee created successfully with minimal data!');
|
||||
console.log('Employee ID:', createResponse.data.data.id);
|
||||
if (createResponse.data.data.temporaryPassword) {
|
||||
console.log('Temporary Password:', createResponse.data.data.temporaryPassword);
|
||||
}
|
||||
|
||||
// Fetch the created employee
|
||||
console.log('\n3. Fetching created employee...');
|
||||
const getResponse = await axios.get(
|
||||
`${API_URL}/employees/${createResponse.data.data.id}`,
|
||||
{ headers }
|
||||
);
|
||||
|
||||
console.log('✅ Employee fetched successfully!');
|
||||
console.log('Employee Data:');
|
||||
console.log('- Name:', getResponse.data.data.firstName, getResponse.data.data.lastName);
|
||||
console.log('- Email:', getResponse.data.data.email);
|
||||
console.log('- Phone:', getResponse.data.data.phone, '(Default value)');
|
||||
console.log('- Position:', getResponse.data.data.position, '(Default value)');
|
||||
console.log('- Department:', getResponse.data.data.department);
|
||||
console.log('- Employee Number:', getResponse.data.data.employeeNumber, '(Auto-generated)');
|
||||
|
||||
console.log('\n✅ Minimal employee creation working! User can complete profile on first login.');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Test failed:', error.response?.data || error.message);
|
||||
if (error.response?.data?.error?.details) {
|
||||
console.error('Details:', error.response.data.error.details);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testMinimalEmployeeCreation();
|
||||
89
.cleanup-backup/test-user-admin.js
Normale Datei
89
.cleanup-backup/test-user-admin.js
Normale Datei
@ -0,0 +1,89 @@
|
||||
const axios = require('axios');
|
||||
|
||||
const API_URL = 'http://localhost:3005/api';
|
||||
|
||||
async function testUserAdmin() {
|
||||
try {
|
||||
console.log('🧪 Testing Admin Panel User Management...\n');
|
||||
|
||||
console.log('1. Testing admin login...');
|
||||
const loginResponse = await axios.post(`${API_URL}/auth/login`, {
|
||||
username: 'admin',
|
||||
password: 'ChangeMe123!@#'
|
||||
});
|
||||
|
||||
const token = loginResponse.data.data.token.accessToken;
|
||||
console.log('✅ Admin login successful');
|
||||
|
||||
const headers = {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
|
||||
console.log('\n2. Testing user list endpoint...');
|
||||
const usersResponse = await axios.get(`${API_URL}/admin/users`, { headers });
|
||||
console.log('✅ User list fetched successfully');
|
||||
console.log(` Found ${usersResponse.data.data.length} users`);
|
||||
|
||||
console.log('\n3. Creating test employee with user account...');
|
||||
const newEmployee = {
|
||||
firstName: 'AdminTest',
|
||||
lastName: 'User',
|
||||
email: 'admin.test@example.com',
|
||||
department: 'Testing',
|
||||
createUser: true,
|
||||
userRole: 'user'
|
||||
};
|
||||
|
||||
const createResponse = await axios.post(`${API_URL}/employees`, newEmployee, { headers });
|
||||
console.log('✅ Employee with user account created');
|
||||
const newUserId = createResponse.data.data.userId;
|
||||
const tempPassword = createResponse.data.data.temporaryPassword;
|
||||
console.log(` User ID: ${newUserId}`);
|
||||
console.log(` Temp Password: ${tempPassword}`);
|
||||
|
||||
if (newUserId) {
|
||||
console.log('\n4. Testing role change...');
|
||||
await axios.put(`${API_URL}/admin/users/${newUserId}/role`,
|
||||
{ role: 'superuser' },
|
||||
{ headers }
|
||||
);
|
||||
console.log('✅ User role changed to superuser');
|
||||
|
||||
console.log('\n5. Testing password reset...');
|
||||
const resetResponse = await axios.post(`${API_URL}/admin/users/${newUserId}/reset-password`,
|
||||
{ },
|
||||
{ headers }
|
||||
);
|
||||
console.log('✅ Password reset successfully');
|
||||
console.log(` New temp password: ${resetResponse.data.data.temporaryPassword}`);
|
||||
|
||||
console.log('\n6. Testing status toggle...');
|
||||
await axios.put(`${API_URL}/admin/users/${newUserId}/status`,
|
||||
{ isActive: false },
|
||||
{ headers }
|
||||
);
|
||||
console.log('✅ User deactivated');
|
||||
|
||||
await axios.put(`${API_URL}/admin/users/${newUserId}/status`,
|
||||
{ isActive: true },
|
||||
{ headers }
|
||||
);
|
||||
console.log('✅ User reactivated');
|
||||
|
||||
console.log('\n7. Cleaning up - deleting test user...');
|
||||
await axios.delete(`${API_URL}/admin/users/${newUserId}`, { headers });
|
||||
console.log('✅ Test user deleted');
|
||||
}
|
||||
|
||||
console.log('\n🎉 All Admin Panel User Management tests passed!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n❌ Test failed:', error.response?.data || error.message);
|
||||
if (error.response?.status) {
|
||||
console.error(` Status: ${error.response.status}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testUserAdmin();
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren