design anpasungen und url for image
This commit is contained in:
323
DEPLOYMENT.md
323
DEPLOYMENT.md
@@ -1,323 +0,0 @@
|
||||
# 🚀 NeoNail DB - Deployment Guide
|
||||
|
||||
## 📋 Schnellstart (5 Minuten)
|
||||
|
||||
### Option A: SQLite (Einfacher - Empfohlen)
|
||||
- ✅ Keine MySQL-Installation nötig
|
||||
- ✅ Einfache Datei-basierte Datenbank
|
||||
- ✅ Perfekt für kleinere bis mittlere Anwendungen
|
||||
- ✅ Einfaches Backup (nur eine Datei)
|
||||
|
||||
### Option B: MySQL/MariaDB
|
||||
- ✅ Für größere Anwendungen
|
||||
- ✅ Mehrere gleichzeitige Benutzer
|
||||
- ✅ Erweiterte Datenbank-Features
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ SQLite Deployment (Empfohlen)
|
||||
|
||||
### 1. Webspace vorbereiten
|
||||
- PHP 8.1+ installiert
|
||||
- SQLite3 PHP-Erweiterung aktiviert
|
||||
- Composer verfügbar (falls möglich)
|
||||
|
||||
### 2. .env für SQLite konfigurieren
|
||||
```env
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://ihre-domain.de
|
||||
|
||||
# SQLite Konfiguration
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=/path/to/database.sqlite
|
||||
# DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD nicht nötig!
|
||||
```
|
||||
|
||||
### 3. SQLite-Datenbank erstellen
|
||||
```bash
|
||||
# Auf dem Server:
|
||||
touch database.sqlite
|
||||
chmod 664 database.sqlite
|
||||
chown www-data:www-data database.sqlite # Falls verfügbar
|
||||
```
|
||||
|
||||
### 4. Deployment ausführen
|
||||
```bash
|
||||
composer install --optimize-autoloader --no-dev
|
||||
php artisan migrate --force
|
||||
php artisan storage:link
|
||||
php artisan config:cache
|
||||
```
|
||||
|
||||
### 5. Admin-User erstellen
|
||||
```bash
|
||||
php artisan tinker
|
||||
```
|
||||
```php
|
||||
use App\Models\User;
|
||||
User::create([
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@neonail.com',
|
||||
'password' => bcrypt('ihr_sicheres_passwort')
|
||||
]);
|
||||
```
|
||||
|
||||
## 🗄️ MySQL/MariaDB Deployment
|
||||
|
||||
### 1. Webspace vorbereiten
|
||||
- PHP 8.1+ installiert
|
||||
- MySQL/MariaDB Datenbank erstellt
|
||||
- Composer verfügbar (falls möglich)
|
||||
|
||||
### 2. Dateien hochladen
|
||||
```bash
|
||||
# Alle Dateien außer:
|
||||
# - node_modules/ (falls vorhanden)
|
||||
# - vendor/ (wird auf Server installiert)
|
||||
# - .git/ (nicht nötig)
|
||||
```
|
||||
|
||||
### 3. .env konfigurieren
|
||||
```env
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://ihre-domain.de
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=ihre_datenbank
|
||||
DB_USERNAME=ihr_username
|
||||
DB_PASSWORD=ihr_passwort
|
||||
```
|
||||
|
||||
### 4. Deployment ausführen
|
||||
```bash
|
||||
# Falls SSH verfügbar:
|
||||
chmod +x deploy.sh
|
||||
./deploy.sh
|
||||
|
||||
# Oder manuell:
|
||||
composer install --optimize-autoloader --no-dev
|
||||
php artisan storage:link
|
||||
php artisan migrate --force
|
||||
php artisan config:cache
|
||||
```
|
||||
|
||||
### 5. Admin-User erstellen
|
||||
```bash
|
||||
php artisan tinker
|
||||
```
|
||||
```php
|
||||
use App\Models\User;
|
||||
User::create([
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@neonail.com',
|
||||
'password' => bcrypt('ihr_sicheres_passwort')
|
||||
]);
|
||||
```
|
||||
|
||||
## 🔧 Detaillierte Anleitung
|
||||
|
||||
### SQLite vs MySQL Vergleich
|
||||
|
||||
| Feature | SQLite | MySQL |
|
||||
|---------|--------|-------|
|
||||
| Installation | ✅ Einfach | ❌ Komplexer |
|
||||
| Konfiguration | ✅ Minimal | ❌ Mehr Aufwand |
|
||||
| Backup | ✅ Eine Datei | ❌ Dump nötig |
|
||||
| Performance | ✅ Gut (klein/mittel) | ✅ Sehr gut (groß) |
|
||||
| Gleichzeitige User | ✅ Bis ~100 | ✅ Unbegrenzt |
|
||||
| Wartung | ✅ Minimal | ❌ Regelmäßig |
|
||||
|
||||
### Voraussetzungen prüfen
|
||||
|
||||
**SQLite PHP-Erweiterungen:**
|
||||
```bash
|
||||
php -m | grep -E "(sqlite3|pdo_sqlite)"
|
||||
```
|
||||
|
||||
**MySQL PHP-Erweiterungen:**
|
||||
```bash
|
||||
php -m | grep -E "(mysql|pdo_mysql)"
|
||||
```
|
||||
|
||||
**Composer installieren (falls nicht verfügbar):**
|
||||
```bash
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
mv composer.phar /usr/local/bin/composer
|
||||
```
|
||||
|
||||
### Datei-Struktur (SQLite)
|
||||
```
|
||||
public_html/
|
||||
├── public/ # Web-Root
|
||||
├── storage/ # Schreibrechte erforderlich
|
||||
├── bootstrap/cache/ # Schreibrechte erforderlich
|
||||
├── database.sqlite # SQLite-Datenbank
|
||||
└── .env # Konfiguration
|
||||
```
|
||||
|
||||
### Datei-Struktur (MySQL)
|
||||
```
|
||||
public_html/
|
||||
├── public/ # Web-Root
|
||||
├── storage/ # Schreibrechte erforderlich
|
||||
├── bootstrap/cache/ # Schreibrechte erforderlich
|
||||
└── .env # Konfiguration
|
||||
```
|
||||
|
||||
### Berechtigungen (SQLite)
|
||||
```bash
|
||||
chmod -R 755 storage/
|
||||
chmod -R 755 bootstrap/cache/
|
||||
chmod 664 database.sqlite
|
||||
chmod 644 .env
|
||||
```
|
||||
|
||||
### Berechtigungen (MySQL)
|
||||
```bash
|
||||
chmod -R 755 storage/
|
||||
chmod -R 755 bootstrap/cache/
|
||||
chmod 644 .env
|
||||
```
|
||||
|
||||
## 🛡️ Sicherheit
|
||||
|
||||
### Wichtige Einstellungen
|
||||
- `APP_DEBUG=false` in Produktion
|
||||
- Starke Passwörter verwenden
|
||||
- HTTPS aktivieren
|
||||
- `.env` nicht öffentlich zugänglich
|
||||
|
||||
### SQLite-spezifische Sicherheit
|
||||
```apache
|
||||
# .htaccess - SQLite-Datei schützen
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
```
|
||||
|
||||
### MySQL-spezifische Sicherheit
|
||||
```apache
|
||||
# .htaccess bereits konfiguriert
|
||||
# Zusätzliche Sicherheit:
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
```
|
||||
|
||||
## 📱 Mobile Optimierung
|
||||
|
||||
### PWA-Features (optional)
|
||||
- Manifest.json hinzufügen
|
||||
- Service Worker für Offline-Funktionalität
|
||||
- App-Icons erstellen
|
||||
|
||||
### Performance
|
||||
- Bilder komprimieren
|
||||
- CDN für statische Assets
|
||||
- Browser-Caching aktivieren
|
||||
|
||||
## 🔄 Backup-Strategie
|
||||
|
||||
### SQLite Backup
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# backup_sqlite.sh
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
cp database.sqlite backup_sqlite_$DATE.sqlite
|
||||
tar -czf storage_backup_$DATE.tar.gz storage/
|
||||
```
|
||||
|
||||
### MySQL Backup
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# backup_mysql.sh
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
mysqldump -u username -p database > backup_mysql_$DATE.sql
|
||||
tar -czf storage_backup_$DATE.tar.gz storage/
|
||||
```
|
||||
|
||||
### Cron-Job (täglich)
|
||||
```bash
|
||||
0 2 * * * /path/to/backup_sqlite.sh
|
||||
```
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### SQLite-spezifische Probleme
|
||||
|
||||
**1. "Database is locked"**
|
||||
```bash
|
||||
chmod 664 database.sqlite
|
||||
chown www-data:www-data database.sqlite
|
||||
```
|
||||
|
||||
**2. "SQLite3 not found"**
|
||||
```bash
|
||||
# PHP-Erweiterung aktivieren
|
||||
php -m | grep sqlite
|
||||
```
|
||||
|
||||
**3. Berechtigungsfehler**
|
||||
```bash
|
||||
chmod 664 database.sqlite
|
||||
chmod -R 755 storage/
|
||||
```
|
||||
|
||||
### MySQL-spezifische Probleme
|
||||
|
||||
**1. "Class not found" Fehler**
|
||||
```bash
|
||||
composer dump-autoload
|
||||
```
|
||||
|
||||
**2. Berechtigungsfehler**
|
||||
```bash
|
||||
chmod -R 755 storage/
|
||||
chmod -R 755 bootstrap/cache/
|
||||
```
|
||||
|
||||
**3. Datenbank-Verbindung**
|
||||
- Host, Port, Credentials prüfen
|
||||
- MySQL-Service läuft
|
||||
|
||||
**4. Bilder werden nicht angezeigt**
|
||||
```bash
|
||||
php artisan storage:link
|
||||
```
|
||||
|
||||
### Logs prüfen
|
||||
```bash
|
||||
tail -f storage/logs/laravel.log
|
||||
```
|
||||
|
||||
## 📞 Support
|
||||
|
||||
Bei Problemen:
|
||||
1. Logs prüfen (`storage/logs/laravel.log`)
|
||||
2. Debug-Modus temporär aktivieren
|
||||
3. Browser-Entwicklertools prüfen
|
||||
4. Server-Error-Logs prüfen
|
||||
|
||||
## 🎯 Nach dem Deployment
|
||||
|
||||
### Testen
|
||||
- [ ] Login funktioniert
|
||||
- [ ] Neuen Lack erstellen
|
||||
- [ ] Bild-Upload funktioniert
|
||||
- [ ] Mobile-Ansicht prüfen
|
||||
- [ ] Admin-Funktionen testen
|
||||
|
||||
### Monitoring
|
||||
- Server-Ressourcen überwachen
|
||||
- Datenbank-Performance prüfen
|
||||
- User-Feedback sammeln
|
||||
|
||||
---
|
||||
|
||||
**Viel Erfolg beim Deployment! 🎉**
|
||||
@@ -1,483 +0,0 @@
|
||||
# 🎨 NeoNail DB - Projekt Prompt
|
||||
|
||||
## 📋 Projekt-Übersicht
|
||||
|
||||
**NeoNail DB** ist eine Laravel-basierte Webanwendung zur Verwaltung von NeoNail-Nagellack-Sammlungen.
|
||||
|
||||
### 🎯 Hauptfunktionen
|
||||
- ✅ Kollaborative Nagellack-Datenbank
|
||||
- ✅ User können eigene Lacke hinzufügen (werden automatisch zum Hauptkatalog hinzugefügt)
|
||||
- ✅ Hersteller-Verwaltung für alle User (flexibel und kollaborativ)
|
||||
- ✅ Mobile-optimiert für Handy-Nutzung im Laden
|
||||
- ✅ Admin-Interface für User-Verwaltung
|
||||
- ✅ Bild-Upload mit automatischer Optimierung
|
||||
- ✅ Suchfunktion nach Name/Nummer
|
||||
- ✅ SQLite-Datenbank (einfach zu deployen)
|
||||
|
||||
## 🏗️ Technische Architektur
|
||||
|
||||
### Framework & Versionen
|
||||
- **Laravel 12.22.1** (PHP 8.4.11)
|
||||
- **Bootstrap 5** (Responsive Design)
|
||||
- **Intervention Image** (Bildverarbeitung)
|
||||
- **SQLite** (Datenbank)
|
||||
|
||||
### Datenbank-Schema
|
||||
```sql
|
||||
-- users (Laravel Standard + is_admin Spalte)
|
||||
-- manufacturers (Name, Description, Website, Country)
|
||||
-- nail_polishes (Name, Number, Manufacturer_ID, Image)
|
||||
-- user_nail_polishes (Pivot-Tabelle für User-Sammlungen)
|
||||
```
|
||||
|
||||
### Wichtige Models
|
||||
- `User` - Benutzer mit `nailPolishes()` Relationship
|
||||
- `Manufacturer` - Hersteller mit `nailPolishes()` Relationship
|
||||
- `NailPolish` - Nagellacke mit `users()` und `manufacturer()` Relationship
|
||||
|
||||
## 🔧 Aktuelle Deployment-Situation
|
||||
|
||||
### Webspace-Status
|
||||
- **URL:** http://192.168.30.81/
|
||||
- **Struktur:** Direkt im HTML-Verzeichnis
|
||||
- **Status:** Neue .env Datei erstellt, Setup bereit
|
||||
|
||||
### Datei-Struktur auf Webspace
|
||||
```
|
||||
/html/ (oder /var/www/html/)
|
||||
├── .htaccess ← Umleitung auf public/
|
||||
├── index.php ← Fallback-Umleitung
|
||||
├── .env ← Konfiguration (neu erstellt)
|
||||
├── database.sqlite ← SQLite-Datenbank im Hauptverzeichnis
|
||||
├── public/ ← Laravel Document Root
|
||||
├── app/ ← Laravel App
|
||||
├── bootstrap/ ← Laravel Bootstrap
|
||||
├── config/ ← Laravel Config
|
||||
├── database/ ← Migrationen
|
||||
├── resources/ ← Views, Assets
|
||||
├── routes/ ← Routen
|
||||
├── storage/ ← Speicher (777 Berechtigungen)
|
||||
├── vendor/ ← Composer Dependencies
|
||||
├── test.php ← PHP-Diagnose
|
||||
├── laravel-test.php ← Laravel-Diagnose
|
||||
├── fix-permissions.sh ← Berechtigungs-Script
|
||||
├── setup-html-directory.sh ← Neues Setup-Script
|
||||
└── env-production-example.txt ← Neue .env Vorlage
|
||||
```
|
||||
|
||||
### Aktuelle .env Konfiguration
|
||||
```env
|
||||
APP_NAME="NeoNail DB"
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:+LTZYPKjkZ+O3iFTgU2sS+9bNvxxvG8Kw8JSEPiG7Rs=
|
||||
APP_DEBUG=false
|
||||
APP_URL=http://192.168.30.81
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=database.sqlite # ✅ Korrekt - Datenbank im Hauptverzeichnis
|
||||
|
||||
# Weitere Standard-Laravel-Einstellungen...
|
||||
```
|
||||
|
||||
## 🚨 Offene Probleme
|
||||
|
||||
### 1. ✅ DB_DATABASE Pfad geklärt
|
||||
**Status:** Datenbank liegt im Hauptverzeichnis
|
||||
- **Pfad:** `/html/database.sqlite` (oder `/var/www/html/database.sqlite`)
|
||||
- **Konfiguration:** `DB_DATABASE=database.sqlite` ✅
|
||||
|
||||
### 2. ✅ Mail-System Problem behoben
|
||||
**Status:** SMTP-Konfiguration korrigiert und getestet
|
||||
- **SMTP-Server:** mail.selfhost.de:465 (SSL)
|
||||
- **Credentials:** postmaster@hjzyyqdm.mail.selfhost.de / Ikmyra
|
||||
- **From-Address:** neonail@vogt.de.com
|
||||
- **Test:** Erfolgreich an oliver@vogt.de.com gesendet
|
||||
- **Status:** User-Registrierung und Admin-Benachrichtigungen funktionieren
|
||||
|
||||
### 3. Deployment-Status
|
||||
- ✅ Berechtigungen korrigiert (777 für storage/, bootstrap/cache/)
|
||||
- ✅ APP_KEY generiert und gesetzt
|
||||
- ✅ .htaccess Umleitung funktioniert
|
||||
- ✅ SQLite-Datenbank-Pfad geklärt
|
||||
- ✅ Composer install ausgeführt
|
||||
- ✅ Migrationen ausgeführt (inkl. Hersteller-Feature)
|
||||
- ✅ is_admin Spalte zur users Tabelle hinzugefügt
|
||||
- ✅ Admin-User erstellt (admin@neonail.com / admin123)
|
||||
- ✅ Hersteller-Feature vollständig implementiert und deployed
|
||||
- ✅ Production-Probleme behoben (schwarzer Bildschirm, Login)
|
||||
- ✅ Mail-System vollständig funktionsfähig
|
||||
|
||||
## 🔄 Nächste Schritte
|
||||
|
||||
### Sofortige Aktionen
|
||||
1. ✅ **DB_DATABASE Pfad geklärt** - Datenbank im Hauptverzeichnis
|
||||
2. ✅ **Composer install** ausgeführt
|
||||
3. ✅ **Migrationen** ausgeführt: `php artisan migrate --force`
|
||||
4. ✅ **is_admin Spalte** zur users Tabelle hinzugefügt
|
||||
5. ✅ **Admin-User** erstellt (admin@neonail.com / admin123)
|
||||
6. ✅ **Anwendung getestet** - Hersteller-Feature funktioniert
|
||||
7. ✅ **HTTPS-Sicherheit** für alle Hersteller-Forms implementiert
|
||||
8. ✅ **Production-Probleme** behoben (schwarzer Bildschirm, Login)
|
||||
9. ✅ **Mail-System** konfiguriert und getestet (SMTP funktioniert)
|
||||
|
||||
### Admin-User erstellen
|
||||
```bash
|
||||
php artisan tinker
|
||||
```
|
||||
```php
|
||||
use App\Models\User;
|
||||
User::create([
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@neonail.com',
|
||||
'password' => bcrypt('admin123'),
|
||||
'is_admin' => true
|
||||
]);
|
||||
```
|
||||
|
||||
### Standard-Login-Daten
|
||||
**Email:** `admin@neonail.com`
|
||||
**Passwort:** `admin123`
|
||||
|
||||
## 📱 Anwendungs-Features
|
||||
|
||||
### User-Features
|
||||
- **Meine Sammlung** - Eigene Lacke anzeigen/verwalten
|
||||
- **Verfügbare Lacke** - Alle Lacke aus Hauptkatalog
|
||||
- **Neuen Lack hinzufügen** - Erstellt Lack im Hauptkatalog + fügt zur eigenen Sammlung hinzu
|
||||
- **Hersteller verwalten** - Hersteller erstellen, bearbeiten, löschen (für alle User)
|
||||
- **Bild-Upload** - Handykamera-Unterstützung, automatische Optimierung
|
||||
- **Suche** - Nach Name oder Nummer
|
||||
|
||||
### Admin-Features
|
||||
- **Dashboard** - Übersicht über User, Lacke und Hersteller
|
||||
- **User-Verwaltung** - User erstellen, bearbeiten, löschen
|
||||
- **Nagellack-Verwaltung** - Alle Lacke verwalten
|
||||
- **Hersteller-Verwaltung** - Alle Hersteller verwalten
|
||||
- **Statistiken** - Anwendungs-Statistiken inkl. Hersteller
|
||||
- **User-Sammlungen** - Sammlungen anderer User einsehen
|
||||
|
||||
## 🛠️ Wichtige Dateien
|
||||
|
||||
### Controllers
|
||||
- `UserNailPolishController` - User-Sammlungen verwalten (erweitert um Hersteller)
|
||||
- `NailPolishController` - Admin-Nagellack-Verwaltung
|
||||
- `ManufacturerController` - Hersteller-Verwaltung für alle User
|
||||
- `AdminController` - Admin-Dashboard und User-Verwaltung (erweitert um Hersteller-Statistiken)
|
||||
- `LoginController` - Authentifizierung
|
||||
|
||||
### Views
|
||||
- `user-nail-polishes/` - User-Sammlungs-Views (erweitert um Hersteller-Anzeige)
|
||||
- `nail-polishes/` - Admin-Nagellack-Views (erweitert um Hersteller-Anzeige)
|
||||
- `manufacturers/` - Hersteller-Verwaltungs-Views (index, create, edit, show)
|
||||
- `admin/` - Admin-Interface-Views
|
||||
- `auth/` - Login-Views
|
||||
|
||||
### Routes
|
||||
```php
|
||||
// User-Routes
|
||||
/my-collection - Eigene Sammlung
|
||||
/available - Verfügbare Lacke
|
||||
/create-nail-polish - Neuen Lack erstellen
|
||||
/add-to-collection/{id} - Lack zur Sammlung hinzufügen
|
||||
/remove-from-collection/{id} - Lack aus Sammlung entfernen
|
||||
|
||||
// Hersteller-Routes (für alle User)
|
||||
/manufacturers - Hersteller-Übersicht
|
||||
/manufacturers/create - Neuen Hersteller erstellen
|
||||
/manufacturers/{id} - Hersteller anzeigen
|
||||
/manufacturers/{id}/edit - Hersteller bearbeiten
|
||||
/manufacturers-search - AJAX-Suche nach Herstellern
|
||||
|
||||
// Admin-Routes
|
||||
/admin/dashboard - Admin-Dashboard
|
||||
/admin/users - User-Verwaltung
|
||||
/nail-polishes - Nagellack-Verwaltung
|
||||
/admin/statistics - Statistiken
|
||||
```
|
||||
|
||||
## 🔒 Sicherheit
|
||||
|
||||
### Admin-Zugang
|
||||
- **Email:** admin@neonail.com
|
||||
- **Passwort:** Muss noch gesetzt werden
|
||||
|
||||
### Middleware
|
||||
- `auth` - Authentifizierung erforderlich
|
||||
- `admin` - Nur für admin@neonail.com
|
||||
- `guest` - Nur für nicht-eingeloggte User
|
||||
|
||||
## 📊 Datenbank-Beziehungen
|
||||
|
||||
### Datenbank-Beziehungen
|
||||
```php
|
||||
// User Model
|
||||
public function nailPolishes() {
|
||||
return $this->belongsToMany(NailPolish::class, 'user_nail_polishes');
|
||||
}
|
||||
|
||||
// Manufacturer Model
|
||||
public function nailPolishes() {
|
||||
return $this->hasMany(NailPolish::class);
|
||||
}
|
||||
|
||||
// NailPolish Model
|
||||
public function users() {
|
||||
return $this->belongsToMany(User::class, 'user_nail_polishes');
|
||||
}
|
||||
|
||||
public function manufacturer() {
|
||||
return $this->belongsTo(Manufacturer::class);
|
||||
}
|
||||
```
|
||||
|
||||
### Pivot-Tabelle
|
||||
```sql
|
||||
user_nail_polishes (user_id, nail_polish_id, timestamps)
|
||||
```
|
||||
|
||||
### Hersteller-Feature
|
||||
- **Flexibilität:** Jeder User kann neue Hersteller erstellen
|
||||
- **Eindeutigkeit:** Hersteller-Namen müssen eindeutig sein
|
||||
- **Globale Verfügbarkeit:** Alle User können alle Hersteller nutzen
|
||||
- **Automatische Erstellung:** Beim Nagellack-Erstellen falls nicht vorhanden
|
||||
- **Referentielle Integrität:** Hersteller können nicht gelöscht werden, wenn Nagellacke zugeordnet sind
|
||||
|
||||
## 🎨 UI/UX Features
|
||||
|
||||
### Mobile-Optimierung
|
||||
- Responsive Bootstrap 5 Design
|
||||
- Touch-freundliche Buttons
|
||||
- Handykamera-Integration (`capture="environment"`)
|
||||
- Optimierte Bildgrößen (400x400px)
|
||||
- Intelligente Hersteller-Auswahl mit JavaScript
|
||||
|
||||
### Design-Elemente
|
||||
- Gradient-Hintergrund
|
||||
- Glassmorphism-Effekte
|
||||
- Font Awesome Icons
|
||||
- Bootstrap Cards und Grid-System
|
||||
|
||||
## 🔧 Deployment-Scripts
|
||||
|
||||
### fix-permissions.sh
|
||||
```bash
|
||||
# Berechtigungen korrigieren
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
chmod 664 database.sqlite
|
||||
chmod 644 .env
|
||||
```
|
||||
|
||||
### deploy-manufacturer-feature.sh
|
||||
```bash
|
||||
# Hersteller-Feature Deployment
|
||||
# - Migration-Reihenfolge korrigieren
|
||||
# - Migrationen ausführen
|
||||
# - Cache leeren
|
||||
# - Autoload aktualisieren
|
||||
# - Berechtigungen setzen
|
||||
```
|
||||
|
||||
### fix-production-issues.sh
|
||||
```bash
|
||||
# Production-Issues Fix
|
||||
# - Migration-Reihenfolge korrigieren
|
||||
# - Migrationen ausführen
|
||||
# - Cache leeren
|
||||
# - Autoload aktualisieren
|
||||
# - Berechtigungen setzen
|
||||
```
|
||||
|
||||
### fix-webspace-production.sh
|
||||
```bash
|
||||
# Webspace Production Fix
|
||||
# - Migration-Reset und Neuausführung
|
||||
# - Cache komplett leeren
|
||||
# - Autoload optimieren
|
||||
# - Datenbank-Tabellen prüfen
|
||||
```
|
||||
|
||||
### fix-black-screen.sh
|
||||
```bash
|
||||
# Schwarzer Bildschirm Fix
|
||||
# - Debug temporär aktivieren
|
||||
# - Cache komplett leeren
|
||||
# - Autoload neu generieren
|
||||
# - Datenbank-Verbindung testen
|
||||
```
|
||||
|
||||
### fix-user-login.sh
|
||||
```bash
|
||||
# User Login Fix
|
||||
# - is_admin Spalte hinzufügen
|
||||
# - Admin-User erstellen
|
||||
# - Cache leeren
|
||||
```
|
||||
|
||||
### test-mail-connection.sh
|
||||
```bash
|
||||
# Mail Connection Test
|
||||
# - SMTP-Verbindung testen
|
||||
# - Test-Mail an oliver@vogt.de.com senden
|
||||
# - Mail-Konfiguration prüfen
|
||||
# - Fehler-Diagnose
|
||||
```
|
||||
|
||||
### fix-mail-config.sh
|
||||
```bash
|
||||
# Mail Configuration Fix
|
||||
# - Mail-Konfiguration auf log-Modus setzen
|
||||
# - Backup der .env erstellen
|
||||
# - Cache leeren
|
||||
# - Test-Mail senden
|
||||
```
|
||||
|
||||
### setup-webspace.sh
|
||||
```bash
|
||||
# Vollständiges Setup
|
||||
# - .env erstellen
|
||||
# - Berechtigungen setzen
|
||||
# - Composer install
|
||||
# - Laravel Setup
|
||||
```
|
||||
|
||||
### deploy-sqlite.sh
|
||||
```bash
|
||||
# SQLite-spezifisches Deployment
|
||||
# - SQLite-Datenbank erstellen
|
||||
# - Optimierte Einstellungen
|
||||
```
|
||||
|
||||
## 🐛 Bekannte Probleme & Lösungen
|
||||
|
||||
### 1. "Permission denied" Fehler
|
||||
**Lösung:** `chmod -R 777 storage/ bootstrap/cache/`
|
||||
|
||||
### 2. "APP_KEY" Fehler
|
||||
**Lösung:** `php artisan key:generate` oder manueller Key
|
||||
|
||||
### 3. "Database connection failed"
|
||||
**Lösung:** SQLite-Datei erstellen, Berechtigungen prüfen
|
||||
|
||||
### 4. "Class not found"
|
||||
**Lösung:** `composer install` oder `composer dump-autoload`
|
||||
|
||||
### 5. "Images not displayed"
|
||||
**Lösung:** `php artisan storage:link`
|
||||
|
||||
### 6. "no such table: manufacturers"
|
||||
**Lösung:** Migrationen ausführen: `php artisan migrate --force`
|
||||
|
||||
### 7. "Migration-Reihenfolge Fehler"
|
||||
**Lösung:** Migration `add_manufacturer_id_to_nail_polishes_table` nach `create_nail_polishes_table` verschieben
|
||||
|
||||
### 8. "Schwarzer Bildschirm in Production"
|
||||
**Lösung:** `fix-black-screen.sh` ausführen oder manuell Debug aktivieren und Cache leeren
|
||||
|
||||
### 9. "User-Login funktioniert nicht nach Migrationen"
|
||||
**Lösung:** `is_admin` Spalte zur users Tabelle hinzufügen und Admin-User erstellen
|
||||
|
||||
### 10. "E-Mails werden nicht versendet"
|
||||
**Lösung:** SMTP-Konfiguration in .env prüfen und `test-mail-connection.sh` ausführen
|
||||
|
||||
## 🌐 Production-Deployment
|
||||
|
||||
### Production-Einstellungen (.env)
|
||||
```env
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://neonail.vogt.de.com
|
||||
```
|
||||
|
||||
### Standard-Login-Daten
|
||||
**Email:** `admin@neonail.com`
|
||||
**Passwort:** `admin123`
|
||||
|
||||
### Production-Fix Scripts
|
||||
- `fix-production-issues.sh` - Allgemeine Production-Probleme
|
||||
- `fix-webspace-production.sh` - Webspace-spezifische Probleme
|
||||
- `fix-black-screen.sh` - Schwarzer Bildschirm Problem
|
||||
- `fix-user-login.sh` - User-Login Problem
|
||||
- `test-mail-connection.sh` - Mail-Verbindung testen
|
||||
- `fix-mail-config.sh` - Mail-Konfiguration reparieren
|
||||
|
||||
### Manuelle Production-Fixes
|
||||
```bash
|
||||
# Schwarzer Bildschirm
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
php artisan config:clear
|
||||
# Cache leeren, Fehler beheben, dann APP_DEBUG=false setzen
|
||||
|
||||
# User-Login Problem
|
||||
php artisan tinker --execute="use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; Schema::table('users', function (Blueprint \$table) { \$table->boolean('is_admin')->default(false)->after('password'); });"
|
||||
php artisan tinker --execute="use App\Models\User; use Illuminate\Support\Facades\Hash; User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => Hash::make('admin123'), 'is_admin' => true]);"
|
||||
|
||||
# Mail-System Problem
|
||||
# .env korrekte SMTP-Daten:
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mail.selfhost.de
|
||||
MAIL_PORT=465
|
||||
MAIL_USERNAME=postmaster@hjzyyqdm.mail.selfhost.de
|
||||
MAIL_PASSWORD=Ikmyra
|
||||
MAIL_ENCRYPTION=SSL
|
||||
MAIL_FROM_ADDRESS="neonail@vogt.de.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
# Cache leeren nach .env Änderung
|
||||
php artisan config:clear
|
||||
|
||||
# Mail-Verbindung testen
|
||||
php artisan tinker --execute="use Illuminate\Support\Facades\Mail; Mail::raw('Test-Mail von NeoNail DB - ' . now(), function(\$message) { \$message->to('oliver@vogt.de.com')->subject('NeoNail DB - SMTP Test')->from('neonail@vogt.de.com', 'NeoNail DB'); }); echo 'Test-Mail gesendet';"
|
||||
```
|
||||
|
||||
## 📞 Support-Informationen
|
||||
|
||||
### Logs
|
||||
- `storage/logs/laravel.log` - Laravel-Logs
|
||||
- `storage/logs/` - Weitere Logs
|
||||
|
||||
### Debug-Modus
|
||||
```env
|
||||
APP_DEBUG=true # Für Fehlerdiagnose
|
||||
```
|
||||
|
||||
### Test-Dateien
|
||||
- `test.php` - PHP-Diagnose
|
||||
- `laravel-test.php` - Laravel-spezifische Diagnose
|
||||
- `test-mail-connection.sh` - Mail-Verbindung testen
|
||||
- `smtp-mail-setup.md` - Mail-Konfiguration Anleitung
|
||||
- `mail-configuration-fix.md` - Mail-Problem Lösung
|
||||
|
||||
## 🎯 Projekt-Ziele
|
||||
|
||||
### Erreicht ✅
|
||||
- Kollaborative Datenbank
|
||||
- Mobile-Optimierung
|
||||
- Admin-Interface
|
||||
- Bild-Upload
|
||||
- Suchfunktion
|
||||
- SQLite-Deployment
|
||||
- Hersteller-Verwaltung für alle User
|
||||
- HTTPS-Sicherheit für alle Forms
|
||||
- Intelligente Hersteller-Auswahl
|
||||
- Production-Ready Deployment
|
||||
- Vollständige User-Authentifizierung
|
||||
- Fehlerbehebung für alle Production-Probleme
|
||||
- Vollständiges Mail-System (SMTP funktioniert)
|
||||
- User-Registrierung mit E-Mail-Benachrichtigungen
|
||||
- Admin-Benachrichtigungen bei neuen Usern
|
||||
|
||||
### Nächste Schritte 🚀
|
||||
1. ✅ Webspace-Deployment abgeschlossen
|
||||
2. ✅ Admin-User erstellt (admin@neonail.com / admin123)
|
||||
3. ✅ Anwendung getestet (inkl. Hersteller-Feature)
|
||||
4. ✅ Production-Probleme behoben
|
||||
5. ✅ Mail-System vollständig funktionsfähig
|
||||
6. User-Feedback sammeln
|
||||
7. Weitere Features entwickeln
|
||||
|
||||
---
|
||||
|
||||
**Projekt-Status:** 100% abgeschlossen, Production-Ready
|
||||
**Letzte Aktion:** Mail-System vollständig funktionsfähig, SMTP-Test erfolgreich
|
||||
**Nächste Aktion:** User-Feedback sammeln und weitere Features entwickeln
|
||||
@@ -1,205 +0,0 @@
|
||||
# 🌐 Webspace Setup - NeoNail DB
|
||||
|
||||
## 🚨 Problem: Verzeichnisliste wird angezeigt
|
||||
|
||||
Wenn Sie eine Verzeichnisliste sehen statt der Laravel-Anwendung, liegt das daran, dass der Webserver nicht auf das `public/` Verzeichnis zeigt.
|
||||
|
||||
## 🔧 Lösungen je nach Hosting-Provider
|
||||
|
||||
### **Option A: Shared Hosting (cPanel, Plesk, etc.)**
|
||||
|
||||
**1. Document Root ändern:**
|
||||
- Gehen Sie zu Ihrem Hosting-Panel
|
||||
- Suchen Sie "Document Root" oder "Web Root"
|
||||
- Ändern Sie von `/neonail/` zu `/neonail/public/`
|
||||
|
||||
**2. Oder Unterverzeichnis erstellen:**
|
||||
```
|
||||
public_html/
|
||||
└── neonail/
|
||||
└── public/ ← Hier alle Laravel-Dateien
|
||||
```
|
||||
|
||||
### **Option B: VPS/Dedicated Server**
|
||||
|
||||
**1. Apache Virtual Host:**
|
||||
```apache
|
||||
<VirtualHost *:80>
|
||||
ServerName ihre-domain.de
|
||||
DocumentRoot /var/www/neonail/public
|
||||
|
||||
<Directory /var/www/neonail/public>
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
**2. Nginx:**
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name ihre-domain.de;
|
||||
root /var/www/neonail/public;
|
||||
|
||||
index index.php index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **Option C: Automatische Umleitung (Empfohlen)**
|
||||
|
||||
**1. .htaccess im Hauptverzeichnis (bereits erstellt):**
|
||||
```apache
|
||||
RewriteEngine On
|
||||
RewriteRule ^$ public/ [L]
|
||||
RewriteRule (.*) public/$1 [L]
|
||||
```
|
||||
|
||||
**2. index.php im Hauptverzeichnis (bereits erstellt):**
|
||||
```php
|
||||
<?php
|
||||
$publicPath = __DIR__ . '/public';
|
||||
if (file_exists($publicPath . '/index.php')) {
|
||||
require_once $publicPath . '/index.php';
|
||||
}
|
||||
```
|
||||
|
||||
## 📋 Schritt-für-Schritt Setup
|
||||
|
||||
### **1. Dateien hochladen**
|
||||
```
|
||||
/neonail/
|
||||
├── .htaccess ← Neue Datei (Umleitung)
|
||||
├── index.php ← Neue Datei (Umleitung)
|
||||
├── public/ ← Laravel public Verzeichnis
|
||||
├── app/ ← Laravel App-Verzeichnis
|
||||
├── bootstrap/ ← Laravel Bootstrap
|
||||
├── config/ ← Laravel Konfiguration
|
||||
├── database/ ← Datenbank-Migrationen
|
||||
├── resources/ ← Views, Assets
|
||||
├── routes/ ← Routen
|
||||
├── storage/ ← Speicher (Schreibrechte!)
|
||||
└── vendor/ ← Composer Dependencies
|
||||
```
|
||||
|
||||
### **2. .env erstellen**
|
||||
```bash
|
||||
# Kopieren Sie env-sqlite-example.txt zu .env
|
||||
cp env-sqlite-example.txt .env
|
||||
```
|
||||
|
||||
**In .env anpassen:**
|
||||
```env
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://ihre-domain.de/neonail
|
||||
|
||||
# SQLite (einfachste Option)
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=/path/to/neonail/database.sqlite
|
||||
```
|
||||
|
||||
### **3. Berechtigungen setzen**
|
||||
```bash
|
||||
chmod -R 755 storage/
|
||||
chmod -R 755 bootstrap/cache/
|
||||
chmod 644 .env
|
||||
```
|
||||
|
||||
### **4. SQLite-Datenbank erstellen**
|
||||
```bash
|
||||
touch database.sqlite
|
||||
chmod 664 database.sqlite
|
||||
```
|
||||
|
||||
### **5. Composer installieren (falls verfügbar)**
|
||||
```bash
|
||||
composer install --optimize-autoloader --no-dev
|
||||
```
|
||||
|
||||
### **6. Laravel Setup**
|
||||
```bash
|
||||
php artisan migrate --force
|
||||
php artisan storage:link
|
||||
php artisan config:cache
|
||||
```
|
||||
|
||||
### **7. Admin-User erstellen**
|
||||
```bash
|
||||
php artisan tinker
|
||||
```
|
||||
```php
|
||||
use App\Models\User;
|
||||
User::create([
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@neonail.com',
|
||||
'password' => bcrypt('ihr_passwort')
|
||||
]);
|
||||
```
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### **Problem: "500 Internal Server Error"**
|
||||
**Lösung:**
|
||||
1. `.env` Datei prüfen
|
||||
2. Berechtigungen prüfen
|
||||
3. PHP-Version prüfen (8.1+)
|
||||
4. Logs prüfen: `storage/logs/laravel.log`
|
||||
|
||||
### **Problem: "Class not found"**
|
||||
**Lösung:**
|
||||
```bash
|
||||
composer dump-autoload
|
||||
```
|
||||
|
||||
### **Problem: "Database connection failed"**
|
||||
**Lösung:**
|
||||
1. SQLite-Datei erstellen
|
||||
2. Berechtigungen prüfen
|
||||
3. Pfad in .env prüfen
|
||||
|
||||
### **Problem: "Permission denied"**
|
||||
**Lösung:**
|
||||
```bash
|
||||
chmod -R 755 storage/
|
||||
chmod -R 755 bootstrap/cache/
|
||||
chmod 664 database.sqlite
|
||||
```
|
||||
|
||||
## 📱 Testen
|
||||
|
||||
### **Nach dem Setup:**
|
||||
1. **URL aufrufen:** `https://ihre-domain.de/neonail`
|
||||
2. **Login testen:** `admin@neonail.com`
|
||||
3. **Neuen Lack erstellen**
|
||||
4. **Bild-Upload testen**
|
||||
5. **Mobile-Ansicht prüfen**
|
||||
|
||||
### **Erwartetes Ergebnis:**
|
||||
- ✅ Login-Seite wird angezeigt
|
||||
- ✅ Keine Verzeichnisliste mehr
|
||||
- ✅ Laravel-Anwendung läuft
|
||||
- ✅ Alle Funktionen funktionieren
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
**Falls nichts funktioniert:**
|
||||
1. Hosting-Provider kontaktieren
|
||||
2. PHP-Version prüfen (8.1+)
|
||||
3. mod_rewrite aktiviert?
|
||||
4. .htaccess erlaubt?
|
||||
|
||||
---
|
||||
|
||||
**Viel Erfolg beim Setup! 🎉**
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "👑 Admin-Rolle aktivieren"
|
||||
echo "========================"
|
||||
|
||||
# 1. Admin-Rolle zur Datenbank hinzufügen
|
||||
echo "🗄️ Füge Admin-Rolle zur Datenbank hinzu..."
|
||||
sqlite3 database.sqlite "ALTER TABLE users ADD COLUMN is_admin BOOLEAN DEFAULT 0;" 2>/dev/null || echo "⚠️ Spalte existiert bereits"
|
||||
|
||||
# 2. Bestehende Admin-User als Admin markieren
|
||||
echo "👤 Markiere bestehende Admin-User..."
|
||||
sqlite3 database.sqlite "UPDATE users SET is_admin = 1 WHERE email IN ('admin@neonail.com', 'neueradmin@neonail.com');"
|
||||
|
||||
# 3. Laravel Cache leeren
|
||||
echo "🧹 Leere Laravel Cache..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
|
||||
# 4. Admin-User prüfen
|
||||
echo "🔍 Prüfe Admin-User..."
|
||||
sqlite3 database.sqlite "SELECT id, name, email, is_admin FROM users;" 2>/dev/null || echo "⚠️ Keine User gefunden"
|
||||
|
||||
# 5. Test-Admin-User erstellen (falls gewünscht)
|
||||
echo "🧪 Erstelle Test-Admin-User..."
|
||||
sqlite3 database.sqlite "INSERT OR IGNORE INTO users (name, email, password, is_admin, created_at, updated_at) VALUES ('Test Admin', 'testadmin@neonail.com', '\$2y\$12\$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 1, datetime('now'), datetime('now'));"
|
||||
|
||||
echo ""
|
||||
echo "✅ Admin-Rolle aktiviert!"
|
||||
echo ""
|
||||
echo "📋 Admin-Funktionen:"
|
||||
echo "1. User bearbeiten: https://neonail.vogt.de.com/admin/users"
|
||||
echo "2. Admin-Rechte gewähren: Checkbox in User-Bearbeitung"
|
||||
echo "3. Admin-Status anzeigen: Badge in User-Liste"
|
||||
echo ""
|
||||
echo "🔑 Test-Admin-Login:"
|
||||
echo "Email: testadmin@neonail.com"
|
||||
echo "Passwort: password"
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
// Migration: Admin-Rolle zu Users-Tabelle hinzufügen
|
||||
// Führen Sie dies aus, um die Admin-Rolle zu aktivieren
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
// 1. Spalte zur users-Tabelle hinzufügen
|
||||
DB::statement('ALTER TABLE users ADD COLUMN is_admin BOOLEAN DEFAULT 0');
|
||||
|
||||
// 2. Bestehende Admin-User als Admin markieren
|
||||
DB::statement("UPDATE users SET is_admin = 1 WHERE email IN ('admin@neonail.com', 'neueradmin@neonail.com')");
|
||||
|
||||
echo "✅ Admin-Rolle erfolgreich hinzugefügt!\n";
|
||||
echo "📋 Admin-User aktualisiert\n";
|
||||
?>
|
||||
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
// Einfacher Admin-User Check
|
||||
echo "<h1>🔍 Admin-User Check</h1>";
|
||||
|
||||
try {
|
||||
// Laravel laden
|
||||
require_once 'vendor/autoload.php';
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// User Model verwenden
|
||||
$users = \App\Models\User::all();
|
||||
|
||||
echo "<h2>Benutzer in der Datenbank:</h2>";
|
||||
if ($users->count() > 0) {
|
||||
echo "<p>✅ <strong>{$users->count()}</strong> Benutzer gefunden</p>";
|
||||
|
||||
foreach ($users as $user) {
|
||||
echo "<div style='border: 1px solid #ccc; padding: 10px; margin: 5px;'>";
|
||||
echo "<strong>ID:</strong> {$user->id}<br>";
|
||||
echo "<strong>Name:</strong> {$user->name}<br>";
|
||||
echo "<strong>Email:</strong> {$user->email}<br>";
|
||||
echo "<strong>Erstellt:</strong> {$user->created_at}<br>";
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
// Admin-User prüfen
|
||||
$admin = \App\Models\User::where('email', 'admin@neonail.com')->first();
|
||||
if ($admin) {
|
||||
echo "<h2>👑 Admin-User gefunden!</h2>";
|
||||
echo "<p>Sie können sich mit <strong>admin@neonail.com</strong> anmelden.</p>";
|
||||
echo "<p><a href='http://192.168.30.81' style='background: #007bff; color: white; padding: 10px; text-decoration: none; border-radius: 5px;'>🚀 Zur Anwendung</a></p>";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo "<p>❌ Keine Benutzer gefunden</p>";
|
||||
echo "<h3>Admin-User erstellen:</h3>";
|
||||
echo "<code>php artisan tinker</code><br>";
|
||||
echo "<code>use App\Models\User;</code><br>";
|
||||
echo "<code>User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('ihr_passwort')]);</code>";
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "<h2>❌ Fehler:</h2>";
|
||||
echo "<p>{$e->getMessage()}</p>";
|
||||
}
|
||||
?>
|
||||
@@ -1,28 +0,0 @@
|
||||
# Apache Virtual Host Konfiguration für NeoNail DB
|
||||
# Datei: /etc/apache2/sites-available/neonail.conf
|
||||
|
||||
<VirtualHost *:80>
|
||||
ServerName 192.168.30.81
|
||||
DocumentRoot /var/www/html/public
|
||||
|
||||
<Directory /var/www/html/public>
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
# Sicherheit - Zugriff auf sensible Dateien verhindern
|
||||
<Directory /var/www/html>
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
</Directory>
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/neonail_error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/neonail_access.log combined
|
||||
</VirtualHost>
|
||||
@@ -1,74 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔍 Apache Diagnose für NeoNail DB"
|
||||
echo "================================"
|
||||
|
||||
echo "1. 📁 Verzeichnis-Struktur prüfen:"
|
||||
echo "--------------------------------"
|
||||
ls -la /var/www/html/
|
||||
echo ""
|
||||
|
||||
echo "2. 📁 Public-Ordner prüfen:"
|
||||
echo "--------------------------"
|
||||
ls -la /var/www/html/public/
|
||||
echo ""
|
||||
|
||||
echo "3. 🌐 Apache DocumentRoot prüfen:"
|
||||
echo "-------------------------------"
|
||||
apache2ctl -S 2>/dev/null | grep "DocumentRoot" || echo "⚠️ Apache2ctl nicht verfügbar"
|
||||
echo ""
|
||||
|
||||
echo "4. 📋 Apache Sites prüfen:"
|
||||
echo "------------------------"
|
||||
ls -la /etc/apache2/sites-enabled/
|
||||
echo ""
|
||||
|
||||
echo "5. 📋 Apache Sites verfügbar:"
|
||||
echo "----------------------------"
|
||||
ls -la /etc/apache2/sites-available/
|
||||
echo ""
|
||||
|
||||
echo "6. 🔧 Apache Konfiguration prüfen:"
|
||||
echo "--------------------------------"
|
||||
if [ -f "/etc/apache2/sites-enabled/neonail.conf" ]; then
|
||||
echo "✅ neonail.conf ist aktiviert"
|
||||
cat /etc/apache2/sites-enabled/neonail.conf
|
||||
else
|
||||
echo "❌ neonail.conf ist NICHT aktiviert"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "7. 📝 .htaccess im Hauptverzeichnis:"
|
||||
echo "----------------------------------"
|
||||
if [ -f "/var/www/html/.htaccess" ]; then
|
||||
echo "✅ .htaccess gefunden:"
|
||||
cat /var/www/html/.htaccess
|
||||
else
|
||||
echo "❌ .htaccess nicht gefunden"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "8. 📝 .htaccess im public-Ordner:"
|
||||
echo "-------------------------------"
|
||||
if [ -f "/var/www/html/public/.htaccess" ]; then
|
||||
echo "✅ public/.htaccess gefunden:"
|
||||
cat /var/www/html/public/.htaccess
|
||||
else
|
||||
echo "❌ public/.htaccess nicht gefunden"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "9. 🔍 Apache-Logs prüfen:"
|
||||
echo "-----------------------"
|
||||
tail -5 /var/log/apache2/error.log
|
||||
echo ""
|
||||
|
||||
echo "10. 🧪 Test-Request:"
|
||||
echo "------------------"
|
||||
curl -I http://192.168.30.81 2>/dev/null || echo "⚠️ curl nicht verfügbar"
|
||||
echo ""
|
||||
|
||||
echo "📋 Nächste Schritte:"
|
||||
echo "1. Falls public/index.php fehlt: Laravel nicht vollständig"
|
||||
echo "2. Falls .htaccess fehlt: Umleitung nicht konfiguriert"
|
||||
echo "3. Falls Apache-Site nicht aktiviert: Virtual Host nicht konfiguriert"
|
||||
@@ -109,7 +109,8 @@ class UserNailPolishController extends Controller
|
||||
"number" => "required|string|max:50",
|
||||
"manufacturer_id" => "required_without:new_manufacturer|exists:manufacturers,id",
|
||||
"new_manufacturer" => "required_without:manufacturer_id|string|max:255|unique:manufacturers,name",
|
||||
"image" => "nullable|image|max:10240", // Max 10MB
|
||||
"image" => "nullable|image|max:10240",
|
||||
"image_url" => "nullable|url|max:500",
|
||||
], [
|
||||
"name.required" => "Der Name des Lackes ist erforderlich.",
|
||||
"number.required" => "Die Nummer des Lackes ist erforderlich.",
|
||||
@@ -118,6 +119,7 @@ class UserNailPolishController extends Controller
|
||||
"new_manufacturer.unique" => "Ein Hersteller mit diesem Namen existiert bereits.",
|
||||
"image.image" => "Die Datei muss ein Bild sein.",
|
||||
"image.max" => "Das Bild darf maximal 10MB groß sein.",
|
||||
"image_url.url" => "Bitte geben Sie eine gültige URL ein (https://...).",
|
||||
]);
|
||||
|
||||
try {
|
||||
@@ -138,19 +140,45 @@ class UserNailPolishController extends Controller
|
||||
$nailPolish->number = trim($request->number);
|
||||
$nailPolish->manufacturer_id = $manufacturerId;
|
||||
|
||||
// Vereinfachte Bildverarbeitung ohne Intervention Image
|
||||
// Bild per Datei-Upload
|
||||
if ($request->hasFile("image") && $request->file("image")->isValid()) {
|
||||
$image = $request->file("image");
|
||||
|
||||
// Erstelle einen eindeutigen Dateinamen
|
||||
$filename = "nail_polish_" . time() . "_" . uniqid() . "." . $image->getClientOriginalExtension();
|
||||
$path = "nail_polishes/" . $filename;
|
||||
|
||||
// Speichere das Bild direkt ohne Verarbeitung
|
||||
Storage::disk("public")->putFileAs("nail_polishes", $image, $filename);
|
||||
$nailPolish->image_path = $path;
|
||||
|
||||
\Log::info("Bild erfolgreich gespeichert: " . $path);
|
||||
// Bild per URL herunterladen
|
||||
} elseif ($request->filled("image_url")) {
|
||||
$imageUrl = trim($request->image_url);
|
||||
try {
|
||||
$response = \Illuminate\Support\Facades\Http::timeout(15)
|
||||
->withHeaders(['User-Agent' => 'Mozilla/5.0'])
|
||||
->get($imageUrl);
|
||||
|
||||
if (!$response->successful()) {
|
||||
throw new \Exception("HTTP-Status " . $response->status());
|
||||
}
|
||||
|
||||
$contentType = strtolower($response->header('Content-Type') ?? '');
|
||||
if (!str_starts_with($contentType, 'image/')) {
|
||||
throw new \Exception("URL enthält kein Bild (Content-Type: {$contentType})");
|
||||
}
|
||||
|
||||
$ext = 'jpg';
|
||||
if (str_contains($contentType, 'png')) $ext = 'png';
|
||||
elseif (str_contains($contentType, 'gif')) $ext = 'gif';
|
||||
elseif (str_contains($contentType, 'webp')) $ext = 'webp';
|
||||
|
||||
$filename = "nail_polish_" . time() . "_" . uniqid() . "." . $ext;
|
||||
$path = "nail_polishes/" . $filename;
|
||||
Storage::disk("public")->put($path, $response->body());
|
||||
$nailPolish->image_path = $path;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::warning("Bild-URL konnte nicht geladen werden: " . $e->getMessage());
|
||||
// Lack wird ohne Bild gespeichert, kein Abbruch
|
||||
}
|
||||
}
|
||||
|
||||
$nailPolish->save();
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
# 🖥️ Schwarzer Bildschirm in Production - Lösung
|
||||
|
||||
## 🚨 **Problem:**
|
||||
- Seite zeigt nur schwarzen Bildschirm
|
||||
- Keine Fehlermeldung sichtbar
|
||||
- Logs zeigen unvollständige Fehler
|
||||
|
||||
## 🔍 **Ursache:**
|
||||
Ein kritischer Fehler tritt auf, aber wird nicht angezeigt.
|
||||
|
||||
## 🔧 **Lösung:**
|
||||
|
||||
### **Schritt 1: Auf dem Webspace ausführen**
|
||||
|
||||
```bash
|
||||
# 1. Ins Laravel-Verzeichnis wechseln
|
||||
cd /var/www/html
|
||||
|
||||
# 2. Black Screen Fix ausführen
|
||||
./fix-black-screen.sh
|
||||
```
|
||||
|
||||
### **Schritt 2: Manuell (falls Script nicht funktioniert)**
|
||||
|
||||
```bash
|
||||
# 1. Temporär Debug aktivieren
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
php artisan config:clear
|
||||
|
||||
# 2. Logs leeren
|
||||
> storage/logs/laravel.log
|
||||
|
||||
# 3. Cache komplett leeren
|
||||
php artisan config:clear
|
||||
php artisan route:clear
|
||||
php artisan view:clear
|
||||
php artisan cache:clear
|
||||
php artisan optimize:clear
|
||||
|
||||
# 4. Composer Autoload neu generieren
|
||||
composer dump-autoload --optimize
|
||||
|
||||
# 5. Berechtigungen prüfen
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
chmod 664 database.sqlite
|
||||
chmod 644 .env
|
||||
|
||||
# 6. Datenbank-Verbindung testen
|
||||
php artisan tinker --execute="echo 'DB Test: '; try { DB::connection()->getPdo(); echo 'OK'; } catch(Exception \$e) { echo 'FEHLER: ' . \$e->getMessage(); }"
|
||||
|
||||
# 7. Routen testen
|
||||
php artisan route:list | head -10
|
||||
|
||||
# 8. Storage-Link prüfen
|
||||
if [ ! -L "public/storage" ]; then
|
||||
php artisan storage:link
|
||||
fi
|
||||
```
|
||||
|
||||
### **Schritt 3: Fehlermeldung analysieren**
|
||||
|
||||
1. **Seite aufrufen** - sollte jetzt Fehlermeldung zeigen
|
||||
2. **Fehlermeldung notieren**
|
||||
3. **Logs prüfen:**
|
||||
```bash
|
||||
tail -f storage/logs/laravel.log
|
||||
```
|
||||
|
||||
### **Schritt 4: Häufige Fehler beheben**
|
||||
|
||||
#### **Fehler: "Class not found"**
|
||||
```bash
|
||||
composer dump-autoload --optimize
|
||||
```
|
||||
|
||||
#### **Fehler: "Table not found"**
|
||||
```bash
|
||||
php artisan migrate --force
|
||||
```
|
||||
|
||||
#### **Fehler: "Permission denied"**
|
||||
```bash
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
```
|
||||
|
||||
#### **Fehler: "View not found"**
|
||||
```bash
|
||||
php artisan view:clear
|
||||
```
|
||||
|
||||
### **Schritt 5: Production-Modus wiederherstellen**
|
||||
|
||||
```bash
|
||||
# Debug deaktivieren
|
||||
sed -i 's/APP_DEBUG=true/APP_DEBUG=false/' .env
|
||||
php artisan config:clear
|
||||
|
||||
# Cache optimieren
|
||||
php artisan optimize
|
||||
```
|
||||
|
||||
## 🎯 **Häufige Ursachen:**
|
||||
|
||||
### **1. Autoload-Probleme**
|
||||
- Neue Klassen nicht gefunden
|
||||
- Composer Autoload nicht aktualisiert
|
||||
|
||||
### **2. Cache-Probleme**
|
||||
- Alte Konfigurationen im Cache
|
||||
- Route-Cache-Probleme
|
||||
|
||||
### **3. Datenbank-Probleme**
|
||||
- Fehlende Tabellen
|
||||
- Verbindungsprobleme
|
||||
|
||||
### **4. Berechtigungs-Probleme**
|
||||
- Storage nicht beschreibbar
|
||||
- Cache nicht beschreibbar
|
||||
|
||||
## 📋 **Checklist:**
|
||||
|
||||
- [ ] Debug temporär aktiviert
|
||||
- [ ] Cache geleert
|
||||
- [ ] Autoload aktualisiert
|
||||
- [ ] Berechtigungen korrekt
|
||||
- [ ] Datenbank getestet
|
||||
- [ ] Fehlermeldung analysiert
|
||||
- [ ] Fehler behoben
|
||||
- [ ] Debug deaktiviert
|
||||
|
||||
## 🚀 **Nach dem Fix:**
|
||||
|
||||
Die Seite sollte jetzt funktionieren!
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
// Admin-User Status prüfen
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
try {
|
||||
// Laravel App initialisieren
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
echo "<h1>🔍 Admin-User Status</h1>";
|
||||
|
||||
// Alle User anzeigen
|
||||
$users = User::all();
|
||||
|
||||
if ($users->count() > 0) {
|
||||
echo "<h2>✅ Benutzer gefunden:</h2>";
|
||||
echo "<table border='1' style='border-collapse: collapse;'>";
|
||||
echo "<tr><th>ID</th><th>Name</th><th>Email</th><th>Erstellt</th></tr>";
|
||||
|
||||
foreach ($users as $user) {
|
||||
echo "<tr>";
|
||||
echo "<td>{$user->id}</td>";
|
||||
echo "<td>{$user->name}</td>";
|
||||
echo "<td>{$user->email}</td>";
|
||||
echo "<td>{$user->created_at}</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
|
||||
// Admin-User finden
|
||||
$admin = User::where('email', 'admin@neonail.com')->first();
|
||||
if ($admin) {
|
||||
echo "<h2>👑 Admin-User gefunden:</h2>";
|
||||
echo "<p><strong>Name:</strong> {$admin->name}</p>";
|
||||
echo "<p><strong>Email:</strong> {$admin->email}</p>";
|
||||
echo "<p><strong>ID:</strong> {$admin->id}</p>";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo "<h2>❌ Keine Benutzer gefunden</h2>";
|
||||
echo "<p>Bitte Admin-User erstellen:</p>";
|
||||
echo "<code>php artisan tinker</code><br>";
|
||||
echo "<code>use App\Models\User;</code><br>";
|
||||
echo "<code>User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('ihr_passwort')]);</code>";
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "<h2>❌ Fehler:</h2>";
|
||||
echo "<p>{$e->getMessage()}</p>";
|
||||
}
|
||||
?>
|
||||
@@ -1,45 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔍 Laravel Logs prüfen"
|
||||
echo "====================="
|
||||
|
||||
echo "1. 📝 Laravel Log-Datei:"
|
||||
echo "----------------------"
|
||||
if [ -f "storage/logs/laravel.log" ]; then
|
||||
echo "✅ Laravel Log gefunden"
|
||||
echo "Letzte 20 Zeilen:"
|
||||
tail -20 storage/logs/laravel.log
|
||||
else
|
||||
echo "❌ Laravel Log nicht gefunden"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "2. 📝 Apache Error Log:"
|
||||
echo "---------------------"
|
||||
if [ -f "/var/log/apache2/neonail_error.log" ]; then
|
||||
echo "✅ NeoNail Error Log gefunden"
|
||||
echo "Letzte 10 Zeilen:"
|
||||
tail -10 /var/log/apache2/neonail_error.log
|
||||
else
|
||||
echo "❌ NeoNail Error Log nicht gefunden"
|
||||
echo "Standard Apache Error Log:"
|
||||
tail -10 /var/log/apache2/error.log
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "3. 🔧 Laravel Debug aktivieren:"
|
||||
echo "-----------------------------"
|
||||
echo "Setze APP_DEBUG=true in .env..."
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
echo "✅ Debug aktiviert"
|
||||
echo ""
|
||||
|
||||
echo "4. 🧪 Test-Request mit Debug:"
|
||||
echo "---------------------------"
|
||||
curl -I http://192.168.30.81
|
||||
echo ""
|
||||
|
||||
echo "📋 Nächste Schritte:"
|
||||
echo "1. Browser öffnen: http://192.168.30.81"
|
||||
echo "2. Fehlermeldung anzeigen lassen"
|
||||
echo "3. Logs prüfen für Details"
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php
|
||||
// User-Sammlung prüfen
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\NailPolish;
|
||||
|
||||
try {
|
||||
// Laravel App initialisieren
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
echo "<h1>🔍 User-Sammlung prüfen</h1>";
|
||||
|
||||
// Admin-User finden
|
||||
$admin = User::where('email', 'admin@neonail.com')->first();
|
||||
|
||||
if ($admin) {
|
||||
echo "<h2>👑 Admin-User gefunden:</h2>";
|
||||
echo "<p><strong>Name:</strong> {$admin->name}</p>";
|
||||
echo "<p><strong>Email:</strong> {$admin->email}</p>";
|
||||
echo "<p><strong>ID:</strong> {$admin->id}</p>";
|
||||
|
||||
// Sammlung prüfen
|
||||
$collection = $admin->nailPolishes;
|
||||
|
||||
echo "<h2>📦 Sammlung ({$collection->count()} Lacke):</h2>";
|
||||
|
||||
if ($collection->count() > 0) {
|
||||
echo "<table border='1' style='border-collapse: collapse;'>";
|
||||
echo "<tr><th>ID</th><th>Name</th><th>Nummer</th><th>Bild</th></tr>";
|
||||
|
||||
foreach ($collection as $polish) {
|
||||
echo "<tr>";
|
||||
echo "<td>{$polish->id}</td>";
|
||||
echo "<td>{$polish->name}</td>";
|
||||
echo "<td>{$polish->number}</td>";
|
||||
echo "<td>" . ($polish->image_path ? "✅" : "❌") . "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
} else {
|
||||
echo "<p>❌ Keine Lacke in der Sammlung</p>";
|
||||
}
|
||||
|
||||
// Alle Lacke prüfen
|
||||
echo "<h2>🗄️ Alle Lacke in der Datenbank:</h2>";
|
||||
$allPolishes = NailPolish::all();
|
||||
|
||||
if ($allPolishes->count() > 0) {
|
||||
echo "<table border='1' style='border-collapse: collapse;'>";
|
||||
echo "<tr><th>ID</th><th>Name</th><th>Nummer</th><th>Bild</th><th>In Sammlung</th></tr>";
|
||||
|
||||
foreach ($allPolishes as $polish) {
|
||||
$inCollection = $admin->nailPolishes()->where('nail_polish_id', $polish->id)->exists();
|
||||
echo "<tr>";
|
||||
echo "<td>{$polish->id}</td>";
|
||||
echo "<td>{$polish->name}</td>";
|
||||
echo "<td>{$polish->number}</td>";
|
||||
echo "<td>" . ($polish->image_path ? "✅" : "❌") . "</td>";
|
||||
echo "<td>" . ($inCollection ? "✅" : "❌") . "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
} else {
|
||||
echo "<p>❌ Keine Lacke in der Datenbank</p>";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo "<h2>❌ Admin-User nicht gefunden</h2>";
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "<h2>❌ Fehler:</h2>";
|
||||
echo "<p>{$e->getMessage()}</p>";
|
||||
}
|
||||
?>
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🧹 Route-Cache leeren"
|
||||
echo "===================="
|
||||
|
||||
# 1. Laravel Cache leeren
|
||||
echo "1. Laravel Cache leeren..."
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen"
|
||||
|
||||
# 2. Bootstrap Cache leeren
|
||||
echo "2. Bootstrap Cache leeren..."
|
||||
rm -f bootstrap/cache/*.php 2>/dev/null || echo "⚠️ bootstrap/cache/*.php nicht gefunden"
|
||||
|
||||
# 3. Route-Test ausführen
|
||||
echo "3. Route-Test ausführen..."
|
||||
php test-route-fix.php
|
||||
|
||||
# 4. Debug-Modus aktivieren
|
||||
echo "4. Debug-Modus aktivieren..."
|
||||
if [ -f .env ]; then
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
sed -i 's/APP_ENV=production/APP_ENV=local/' .env
|
||||
echo "✅ Debug-Modus aktiviert"
|
||||
else
|
||||
echo "❌ .env Datei nicht gefunden"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ Route-Cache geleert!"
|
||||
echo ""
|
||||
echo "🔗 Testen Sie jetzt:"
|
||||
echo "1. https://neonail.vogt.de.com/create-nail-polish"
|
||||
echo "2. Versuchen Sie einen neuen Lack zu erstellen"
|
||||
echo "3. Falls Problem besteht: php artisan route:list | grep create"
|
||||
@@ -1,72 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔧 NeoNail DB - Vollständige Reparatur"
|
||||
echo "====================================="
|
||||
|
||||
# 1. SQLite-Treiber installieren
|
||||
echo "🗄️ Installiere SQLite-Treiber..."
|
||||
apt update
|
||||
apt install -y sqlite3 php-sqlite3 php-pdo-sqlite
|
||||
|
||||
# 2. Cache-Dateien löschen (Pail-Problem)
|
||||
echo "🧹 Lösche Cache-Dateien..."
|
||||
rm -f bootstrap/cache/packages.php
|
||||
rm -f bootstrap/cache/services.php
|
||||
rm -f bootstrap/cache/config.php
|
||||
|
||||
# 3. .env erstellen
|
||||
echo "📝 Erstelle .env Datei..."
|
||||
if [ ! -f ".env" ]; then
|
||||
cp env-production-example.txt .env
|
||||
fi
|
||||
|
||||
# 4. SQLite-Datenbank erstellen
|
||||
echo "🗄️ Erstelle SQLite-Datenbank..."
|
||||
touch database.sqlite
|
||||
chmod 664 database.sqlite
|
||||
|
||||
# 5. Berechtigungen setzen
|
||||
echo "🔐 Setze Berechtigungen..."
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
chmod 644 .env
|
||||
|
||||
# 6. Composer autoload neu generieren
|
||||
echo "🔄 Generiere autoload neu..."
|
||||
if command -v composer &> /dev/null; then
|
||||
composer dump-autoload --optimize
|
||||
elif [ -f "composer.phar" ]; then
|
||||
php composer.phar dump-autoload --optimize
|
||||
else
|
||||
echo "⚠️ Composer nicht verfügbar"
|
||||
fi
|
||||
|
||||
# 7. Laravel Cache leeren
|
||||
echo "🧹 Leere Laravel Cache..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
|
||||
# 8. Migrationen ausführen
|
||||
echo "🗃️ Führe Migrationen aus..."
|
||||
php artisan migrate --force 2>/dev/null || echo "⚠️ Migrationen übersprungen"
|
||||
|
||||
# 9. Storage Link erstellen
|
||||
echo "🔗 Prüfe Storage Link..."
|
||||
if [ ! -L "public/storage" ]; then
|
||||
php artisan storage:link 2>/dev/null || echo "⚠️ Storage Link übersprungen"
|
||||
else
|
||||
echo "✅ Storage Link bereits vorhanden"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ Vollständige Reparatur abgeschlossen!"
|
||||
echo ""
|
||||
echo "📋 Testen Sie:"
|
||||
echo "1. php artisan --version"
|
||||
echo "2. php -m | grep sqlite"
|
||||
echo "3. http://192.168.30.81"
|
||||
echo ""
|
||||
echo "📋 Admin-User erstellen:"
|
||||
echo "php artisan tinker"
|
||||
echo "use App\Models\User;"
|
||||
echo "User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('ihr_passwort')]);"
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
// Admin-User erstellen
|
||||
echo "<h1>👑 Admin-User erstellen</h1>";
|
||||
|
||||
try {
|
||||
// Laravel laden
|
||||
require_once 'vendor/autoload.php';
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// Prüfen ob Admin bereits existiert
|
||||
$existingAdmin = \App\Models\User::where('email', 'admin@neonail.com')->first();
|
||||
|
||||
if ($existingAdmin) {
|
||||
echo "<h2>✅ Admin-User existiert bereits!</h2>";
|
||||
echo "<p><strong>Name:</strong> {$existingAdmin->name}</p>";
|
||||
echo "<p><strong>Email:</strong> {$existingAdmin->email}</p>";
|
||||
echo "<p><strong>ID:</strong> {$existingAdmin->id}</p>";
|
||||
echo "<p><a href='http://192.168.30.81' style='background: #28a745; color: white; padding: 10px; text-decoration: none; border-radius: 5px;'>🚀 Zur Anwendung</a></p>";
|
||||
} else {
|
||||
// Admin-User erstellen
|
||||
$admin = \App\Models\User::create([
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@neonail.com',
|
||||
'password' => bcrypt('admin123')
|
||||
]);
|
||||
|
||||
echo "<h2>✅ Admin-User erstellt!</h2>";
|
||||
echo "<p><strong>Name:</strong> {$admin->name}</p>";
|
||||
echo "<p><strong>Email:</strong> {$admin->email}</p>";
|
||||
echo "<p><strong>Passwort:</strong> admin123</p>";
|
||||
echo "<p><strong>ID:</strong> {$admin->id}</p>";
|
||||
echo "<p><a href='http://192.168.30.81' style='background: #28a745; color: white; padding: 10px; text-decoration: none; border-radius: 5px;'>🚀 Zur Anwendung</a></p>";
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "<h2>❌ Fehler:</h2>";
|
||||
echo "<p>{$e->getMessage()}</p>";
|
||||
}
|
||||
?>
|
||||
@@ -1,118 +0,0 @@
|
||||
<?php
|
||||
// Debug-Script für HTTP 405 Method Not Allowed Fehler
|
||||
// Führen Sie dies aus, um das Problem zu diagnostizieren
|
||||
|
||||
echo "🔍 Debug: HTTP 405 Method Not Allowed\n";
|
||||
echo "====================================\n\n";
|
||||
|
||||
// 1. Prüfe Laravel-Umgebung
|
||||
echo "1. Laravel-Umgebung:\n";
|
||||
echo " - APP_ENV: " . (getenv('APP_ENV') ?: 'nicht gesetzt') . "\n";
|
||||
echo " - APP_DEBUG: " . (getenv('APP_DEBUG') ?: 'nicht gesetzt') . "\n";
|
||||
echo " - APP_URL: " . (getenv('APP_URL') ?: 'nicht gesetzt') . "\n\n";
|
||||
|
||||
// 2. Prüfe Datenbankverbindung
|
||||
echo "2. Datenbankverbindung:\n";
|
||||
try {
|
||||
$pdo = new PDO('sqlite:database.sqlite');
|
||||
echo " ✅ SQLite-Verbindung erfolgreich\n";
|
||||
|
||||
// Prüfe users-Tabelle
|
||||
$stmt = $pdo->query("SELECT COUNT(*) FROM users");
|
||||
$userCount = $stmt->fetchColumn();
|
||||
echo " - User in Datenbank: $userCount\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Datenbankfehler: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
// 3. Prüfe Laravel-Routes
|
||||
echo "\n3. Laravel-Routes:\n";
|
||||
try {
|
||||
// Simuliere Laravel-Bootstrap
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Erstelle Laravel-App
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// Hole Router
|
||||
$router = $app->make('router');
|
||||
|
||||
// Prüfe spezifische Route
|
||||
$routes = $router->getRoutes();
|
||||
$foundRoute = false;
|
||||
|
||||
foreach ($routes as $route) {
|
||||
if ($route->getName() === 'user-nail-polishes.store') {
|
||||
echo " ✅ Route 'user-nail-polishes.store' gefunden\n";
|
||||
echo " - URI: " . $route->uri() . "\n";
|
||||
echo " - Method: " . implode('|', $route->methods()) . "\n";
|
||||
echo " - Controller: " . $route->getActionName() . "\n";
|
||||
$foundRoute = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$foundRoute) {
|
||||
echo " ❌ Route 'user-nail-polishes.store' nicht gefunden\n";
|
||||
}
|
||||
|
||||
// Zeige alle POST-Routes
|
||||
echo "\n 📋 Alle POST-Routes:\n";
|
||||
foreach ($routes as $route) {
|
||||
if (in_array('POST', $route->methods())) {
|
||||
echo " - " . $route->uri() . " -> " . $route->getName() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Laravel-Fehler: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
// 4. Prüfe Dateisystem
|
||||
echo "\n4. Dateisystem:\n";
|
||||
$files = [
|
||||
'routes/web.php' => 'Route-Definitionen',
|
||||
'app/Http/Controllers/UserNailPolishController.php' => 'Controller',
|
||||
'resources/views/user-nail-polishes/create.blade.php' => 'Create-View',
|
||||
'bootstrap/app.php' => 'Laravel-Bootstrap',
|
||||
'vendor/autoload.php' => 'Composer Autoload'
|
||||
];
|
||||
|
||||
foreach ($files as $file => $description) {
|
||||
if (file_exists($file)) {
|
||||
echo " ✅ $description: $file\n";
|
||||
} else {
|
||||
echo " ❌ $description fehlt: $file\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Prüfe .htaccess
|
||||
echo "\n5. .htaccess-Konfiguration:\n";
|
||||
$htaccessFiles = [
|
||||
'.htaccess' => 'Hauptverzeichnis',
|
||||
'public/.htaccess' => 'Public-Verzeichnis'
|
||||
];
|
||||
|
||||
foreach ($htaccessFiles as $file => $location) {
|
||||
if (file_exists($file)) {
|
||||
echo " ✅ $location .htaccess gefunden\n";
|
||||
$content = file_get_contents($file);
|
||||
if (strpos($content, 'RewriteEngine On') !== false) {
|
||||
echo " - RewriteEngine aktiviert\n";
|
||||
}
|
||||
if (strpos($content, 'index.php') !== false) {
|
||||
echo " - index.php Weiterleitung konfiguriert\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ $location .htaccess fehlt\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n🔧 Nächste Schritte:\n";
|
||||
echo "1. Prüfen Sie die Laravel-Logs: storage/logs/laravel.log\n";
|
||||
echo "2. Aktivieren Sie APP_DEBUG=true in .env\n";
|
||||
echo "3. Leeren Sie den Cache: php artisan cache:clear\n";
|
||||
echo "4. Prüfen Sie die Apache-Logs für weitere Details\n";
|
||||
?>
|
||||
@@ -1,131 +0,0 @@
|
||||
<?php
|
||||
// Debug-Script für HTTP 500 Internal Server Error
|
||||
// Führen Sie dies aus, um das Problem zu diagnostizieren
|
||||
|
||||
echo "🔍 Debug: HTTP 500 Internal Server Error\n";
|
||||
echo "=======================================\n\n";
|
||||
|
||||
// 1. Prüfe Laravel-Logs
|
||||
echo "1. Laravel-Logs prüfen:\n";
|
||||
$logFiles = [
|
||||
'storage/logs/laravel.log',
|
||||
'storage/logs/laravel-' . date('Y-m-d') . '.log'
|
||||
];
|
||||
|
||||
foreach ($logFiles as $logFile) {
|
||||
if (file_exists($logFile)) {
|
||||
echo " 📋 $logFile gefunden\n";
|
||||
echo " 📄 Letzte 10 Zeilen:\n";
|
||||
$lines = file($logFile);
|
||||
$lastLines = array_slice($lines, -10);
|
||||
foreach ($lastLines as $line) {
|
||||
echo " " . trim($line) . "\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ $logFile nicht gefunden\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Prüfe PHP-Fehler
|
||||
echo "\n2. PHP-Fehler prüfen:\n";
|
||||
$errorLog = ini_get('error_log');
|
||||
if ($errorLog && file_exists($errorLog)) {
|
||||
echo " 📋 PHP Error Log: $errorLog\n";
|
||||
$lines = file($errorLog);
|
||||
$lastLines = array_slice($lines, -5);
|
||||
foreach ($lastLines as $line) {
|
||||
echo " " . trim($line) . "\n";
|
||||
}
|
||||
} else {
|
||||
echo " ⚠️ PHP Error Log nicht verfügbar\n";
|
||||
}
|
||||
|
||||
// 3. Prüfe Apache-Logs
|
||||
echo "\n3. Apache-Logs prüfen:\n";
|
||||
$apacheLogs = [
|
||||
'/var/log/apache2/error.log',
|
||||
'/var/log/apache2/neonail_error.log'
|
||||
];
|
||||
|
||||
foreach ($apacheLogs as $logFile) {
|
||||
if (file_exists($logFile)) {
|
||||
echo " 📋 $logFile gefunden\n";
|
||||
echo " 📄 Letzte 5 Zeilen:\n";
|
||||
$lines = file($logFile);
|
||||
$lastLines = array_slice($lines, -5);
|
||||
foreach ($lastLines as $line) {
|
||||
echo " " . trim($line) . "\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ $logFile nicht gefunden\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Prüfe Dateisystem
|
||||
echo "\n4. Dateisystem prüfen:\n";
|
||||
$criticalFiles = [
|
||||
'public/index.php' => 'Laravel Entry Point',
|
||||
'bootstrap/app.php' => 'Laravel Bootstrap',
|
||||
'vendor/autoload.php' => 'Composer Autoload',
|
||||
'config/app.php' => 'App Config',
|
||||
'.env' => 'Environment File',
|
||||
'database.sqlite' => 'Database File'
|
||||
];
|
||||
|
||||
foreach ($criticalFiles as $file => $description) {
|
||||
if (file_exists($file)) {
|
||||
$perms = substr(sprintf('%o', fileperms($file)), -4);
|
||||
echo " ✅ $description: $file (Perms: $perms)\n";
|
||||
} else {
|
||||
echo " ❌ $description fehlt: $file\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Prüfe Verzeichnisberechtigungen
|
||||
echo "\n5. Verzeichnisberechtigungen prüfen:\n";
|
||||
$directories = [
|
||||
'storage' => 'Storage Directory',
|
||||
'storage/logs' => 'Logs Directory',
|
||||
'storage/framework' => 'Framework Directory',
|
||||
'storage/framework/cache' => 'Cache Directory',
|
||||
'storage/framework/sessions' => 'Sessions Directory',
|
||||
'storage/framework/views' => 'Views Directory',
|
||||
'bootstrap/cache' => 'Bootstrap Cache'
|
||||
];
|
||||
|
||||
foreach ($directories as $dir => $description) {
|
||||
if (is_dir($dir)) {
|
||||
$perms = substr(sprintf('%o', fileperms($dir)), -4);
|
||||
$writable = is_writable($dir) ? 'writable' : 'not writable';
|
||||
echo " ✅ $description: $dir (Perms: $perms, $writable)\n";
|
||||
} else {
|
||||
echo " ❌ $description fehlt: $dir\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Prüfe Laravel-Bootstrap
|
||||
echo "\n6. Laravel-Bootstrap Test:\n";
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
echo " ✅ Composer Autoload erfolgreich\n";
|
||||
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
echo " ✅ Laravel App erstellt\n";
|
||||
|
||||
$kernel = $app->make('Illuminate\Contracts\Console\Kernel');
|
||||
echo " ✅ Kernel erstellt\n";
|
||||
|
||||
$kernel->bootstrap();
|
||||
echo " ✅ Laravel Bootstrap erfolgreich\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Laravel-Fehler: " . $e->getMessage() . "\n";
|
||||
echo " 📍 Datei: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
}
|
||||
|
||||
echo "\n🔧 Nächste Schritte:\n";
|
||||
echo "1. Prüfen Sie die Laravel-Logs für detaillierte Fehlermeldungen\n";
|
||||
echo "2. Aktivieren Sie APP_DEBUG=true in .env\n";
|
||||
echo "3. Prüfen Sie die Apache-Logs für Server-Fehler\n";
|
||||
echo "4. Stellen Sie sicher, dass alle Verzeichnisse beschreibbar sind\n";
|
||||
?>
|
||||
@@ -1,194 +0,0 @@
|
||||
<?php
|
||||
// Debug: Bild-Upload Problem
|
||||
echo "🔍 Debug: Bild-Upload Problem\n";
|
||||
echo "============================\n\n";
|
||||
|
||||
// 1. PHP-Upload-Einstellungen
|
||||
echo "1. PHP-Upload-Einstellungen:\n";
|
||||
$uploadSettings = [
|
||||
'upload_max_filesize' => ini_get('upload_max_filesize'),
|
||||
'post_max_size' => ini_get('post_max_size'),
|
||||
'max_file_uploads' => ini_get('max_file_uploads'),
|
||||
'memory_limit' => ini_get('memory_limit'),
|
||||
'max_execution_time' => ini_get('max_execution_time'),
|
||||
'max_input_time' => ini_get('max_input_time'),
|
||||
'file_uploads' => ini_get('file_uploads'),
|
||||
'upload_tmp_dir' => ini_get('upload_tmp_dir')
|
||||
];
|
||||
|
||||
foreach ($uploadSettings as $setting => $value) {
|
||||
echo " - $setting: $value\n";
|
||||
}
|
||||
|
||||
// 2. GD Extension prüfen
|
||||
echo "\n2. GD Extension prüfen:\n";
|
||||
if (extension_loaded('gd')) {
|
||||
echo " ✅ GD Extension geladen\n";
|
||||
$gdInfo = gd_info();
|
||||
echo " - GD Version: " . $gdInfo['GD Version'] . "\n";
|
||||
echo " - JPEG Support: " . ($gdInfo['JPEG Support'] ? 'Ja' : 'Nein') . "\n";
|
||||
echo " - PNG Support: " . ($gdInfo['PNG Support'] ? 'Ja' : 'Nein') . "\n";
|
||||
echo " - GIF Support: " . ($gdInfo['GIF Support'] ? 'Ja' : 'Nein') . "\n";
|
||||
} else {
|
||||
echo " ❌ GD Extension nicht geladen\n";
|
||||
}
|
||||
|
||||
// 3. Intervention Image prüfen
|
||||
echo "\n3. Intervention Image prüfen:\n";
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
if (class_exists('Intervention\Image\ImageManager')) {
|
||||
echo " ✅ Intervention Image verfügbar\n";
|
||||
|
||||
// Test ImageManager
|
||||
$manager = new \Intervention\Image\ImageManager(new \Intervention\Image\Drivers\Gd\Driver());
|
||||
echo " ✅ ImageManager funktioniert\n";
|
||||
} else {
|
||||
echo " ❌ Intervention Image nicht verfügbar\n";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Intervention Image Fehler: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
// 4. Storage-Verzeichnisse prüfen
|
||||
echo "\n4. Storage-Verzeichnisse prüfen:\n";
|
||||
$storagePaths = [
|
||||
'storage' => 'Storage Root',
|
||||
'storage/app' => 'Storage App',
|
||||
'storage/app/public' => 'Storage Public',
|
||||
'storage/app/public/nail_polishes' => 'Nail Polishes Storage',
|
||||
'public/storage' => 'Public Storage Link'
|
||||
];
|
||||
|
||||
foreach ($storagePaths as $path => $description) {
|
||||
if (file_exists($path)) {
|
||||
$perms = substr(sprintf('%o', fileperms($path)), -4);
|
||||
$writable = is_writable($path) ? 'writable' : 'not writable';
|
||||
$type = is_dir($path) ? 'directory' : (is_link($path) ? 'symlink' : 'file');
|
||||
echo " ✅ $description: $path ($type, perms: $perms, $writable)\n";
|
||||
} else {
|
||||
echo " ❌ $description: $path (nicht gefunden)\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Laravel Storage Link prüfen
|
||||
echo "\n5. Laravel Storage Link prüfen:\n";
|
||||
$publicStoragePath = 'public/storage';
|
||||
if (is_link($publicStoragePath)) {
|
||||
$target = readlink($publicStoragePath);
|
||||
echo " ✅ Storage Link existiert: $publicStoragePath -> $target\n";
|
||||
} else {
|
||||
echo " ⚠️ Storage Link existiert nicht\n";
|
||||
|
||||
// Versuche Storage Link zu erstellen
|
||||
try {
|
||||
if (file_exists('storage/app/public')) {
|
||||
if (is_dir('public/storage')) {
|
||||
rmdir('public/storage');
|
||||
}
|
||||
symlink('../storage/app/public', 'public/storage');
|
||||
echo " ✅ Storage Link erstellt\n";
|
||||
} else {
|
||||
echo " ❌ storage/app/public existiert nicht\n";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Storage Link erstellen fehlgeschlagen: " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Laravel-Logs prüfen
|
||||
echo "\n6. Laravel-Logs prüfen:\n";
|
||||
$logFiles = [
|
||||
'storage/logs/laravel.log',
|
||||
'storage/logs/laravel-' . date('Y-m-d') . '.log'
|
||||
];
|
||||
|
||||
foreach ($logFiles as $logFile) {
|
||||
if (file_exists($logFile)) {
|
||||
echo " 📋 $logFile gefunden\n";
|
||||
$lines = file($logFile);
|
||||
$lastLines = array_slice($lines, -5);
|
||||
echo " 📄 Letzte 5 Zeilen:\n";
|
||||
foreach ($lastLines as $line) {
|
||||
if (strpos($line, 'error') !== false || strpos($line, 'Exception') !== false || strpos($line, 'upload') !== false) {
|
||||
echo " " . trim($line) . "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo " ❌ $logFile nicht gefunden\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Test-Bild erstellen
|
||||
echo "\n7. Test-Bild erstellen:\n";
|
||||
try {
|
||||
$testImagePath = 'storage/app/public/nail_polishes/test.jpg';
|
||||
|
||||
if (extension_loaded('gd')) {
|
||||
// Erstelle ein einfaches Test-Bild
|
||||
$image = imagecreate(100, 100);
|
||||
$bgColor = imagecolorallocate($image, 255, 255, 255);
|
||||
$textColor = imagecolorallocate($image, 0, 0, 0);
|
||||
imagestring($image, 5, 10, 40, 'TEST', $textColor);
|
||||
|
||||
if (imagejpeg($image, $testImagePath, 80)) {
|
||||
echo " ✅ Test-Bild erstellt: $testImagePath\n";
|
||||
|
||||
// Prüfe ob Bild über Web erreichbar ist
|
||||
$webPath = 'public/storage/nail_polishes/test.jpg';
|
||||
if (file_exists($webPath)) {
|
||||
echo " ✅ Test-Bild über Web erreichbar\n";
|
||||
} else {
|
||||
echo " ❌ Test-Bild nicht über Web erreichbar\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Test-Bild erstellen fehlgeschlagen\n";
|
||||
}
|
||||
|
||||
imagedestroy($image);
|
||||
} else {
|
||||
echo " ❌ GD Extension nicht verfügbar für Test-Bild\n";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Test-Bild Fehler: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
// 8. Controller-Code prüfen
|
||||
echo "\n8. Controller-Code prüfen:\n";
|
||||
$controllerPath = 'app/Http/Controllers/UserNailPolishController.php';
|
||||
if (file_exists($controllerPath)) {
|
||||
$content = file_get_contents($controllerPath);
|
||||
|
||||
// Prüfe ImageManager Import
|
||||
if (strpos($content, 'use Intervention\\Image\\ImageManager') !== false) {
|
||||
echo " ✅ ImageManager Import vorhanden\n";
|
||||
} else {
|
||||
echo " ❌ ImageManager Import fehlt\n";
|
||||
}
|
||||
|
||||
// Prüfe Driver Import
|
||||
if (strpos($content, 'use Intervention\\Image\\Drivers\\Gd\\Driver') !== false) {
|
||||
echo " ✅ Driver Import vorhanden\n";
|
||||
} else {
|
||||
echo " ❌ Driver Import fehlt\n";
|
||||
}
|
||||
|
||||
// Prüfe Bildverarbeitungscode
|
||||
if (strpos($content, 'new ImageManager(new Driver())') !== false) {
|
||||
echo " ✅ Bildverarbeitungscode vorhanden\n";
|
||||
} else {
|
||||
echo " ❌ Bildverarbeitungscode fehlt\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Controller nicht gefunden\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Bild-Upload Debug abgeschlossen!\n";
|
||||
echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/create-nail-polish\n";
|
||||
echo "\n📋 Nächste Schritte:\n";
|
||||
echo "1. Prüfen Sie die Laravel-Logs für spezifische Fehlermeldungen\n";
|
||||
echo "2. Testen Sie mit einem kleinen Bild (< 1MB)\n";
|
||||
echo "3. Prüfen Sie Browser-Entwicklertools (F12) für Netzwerk-Fehler\n";
|
||||
echo "4. Schauen Sie in Apache-Logs für Server-Fehler\n";
|
||||
?>
|
||||
@@ -1,202 +0,0 @@
|
||||
<?php
|
||||
// Debug: Logout-Problem detailliert debuggen
|
||||
echo "🔍 Debug: Logout-Problem detailliert debuggen\n";
|
||||
echo "============================================\n\n";
|
||||
|
||||
// 1. Aktuelles Layout prüfen
|
||||
echo "1. 🎨 Aktuelles Layout prüfen...\n";
|
||||
$layoutPath = 'resources/views/layouts/app.blade.php';
|
||||
if (file_exists($layoutPath)) {
|
||||
$content = file_get_contents($layoutPath);
|
||||
|
||||
// Zeige alle Logout-bezogenen Zeilen
|
||||
$lines = explode("\n", $content);
|
||||
$logoutLines = [];
|
||||
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
$logoutLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($logoutLines)) {
|
||||
echo " ✅ Logout-bezogene Zeilen gefunden:\n";
|
||||
foreach ($logoutLines as $line) {
|
||||
echo " 📋 $line\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Keine Logout-bezogenen Zeilen gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Layout-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 2. Routes prüfen
|
||||
echo "\n2. 🛣️ Routes prüfen...\n";
|
||||
$routesPath = 'routes/web.php';
|
||||
if (file_exists($routesPath)) {
|
||||
$content = file_get_contents($routesPath);
|
||||
|
||||
// Zeige alle Logout-bezogenen Zeilen
|
||||
$lines = explode("\n", $content);
|
||||
$logoutLines = [];
|
||||
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
$logoutLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($logoutLines)) {
|
||||
echo " ✅ Logout-Routes gefunden:\n";
|
||||
foreach ($logoutLines as $line) {
|
||||
echo " 📋 $line\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Keine Logout-Routes gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Routes-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 3. LoginController prüfen
|
||||
echo "\n3. 🔐 LoginController prüfen...\n";
|
||||
$controllerPath = 'app/Http/Controllers/Auth/LoginController.php';
|
||||
if (file_exists($controllerPath)) {
|
||||
$content = file_get_contents($controllerPath);
|
||||
|
||||
if (strpos($content, 'public function logout') !== false) {
|
||||
echo " ✅ Logout-Methode vorhanden\n";
|
||||
|
||||
// Zeige Logout-Methode
|
||||
$lines = explode("\n", $content);
|
||||
$inLogoutMethod = false;
|
||||
$methodLines = [];
|
||||
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'public function logout') !== false) {
|
||||
$inLogoutMethod = true;
|
||||
$methodLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
} elseif ($inLogoutMethod && strpos($line, 'public function') !== false) {
|
||||
$inLogoutMethod = false;
|
||||
} elseif ($inLogoutMethod) {
|
||||
$methodLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
echo " 📋 Logout-Methode:\n";
|
||||
foreach ($methodLines as $line) {
|
||||
echo " $line\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Logout-Methode nicht gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ LoginController nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 4. Einfache Logout-Route erstellen
|
||||
echo "\n4. 🛣️ Einfache Logout-Route erstellen...\n";
|
||||
$routesPath = 'routes/web.php';
|
||||
if (file_exists($routesPath)) {
|
||||
$content = file_get_contents($routesPath);
|
||||
|
||||
// Prüfe ob GET Logout-Route existiert
|
||||
if (strpos($content, "Route::get('/logout', [LoginController::class, 'logout'])->name('logout');") === false) {
|
||||
// Füge GET Logout-Route hinzu
|
||||
$newRoute = "\n// Einfache Logout-Route für Debugging\nRoute::get('/logout', [App\\Http\\Controllers\\Auth\\LoginController::class, 'logout'])->name('logout');\n";
|
||||
|
||||
// Füge am Ende der Datei hinzu
|
||||
$content .= $newRoute;
|
||||
file_put_contents($routesPath, $content);
|
||||
echo " ✅ GET Logout-Route hinzugefügt\n";
|
||||
} else {
|
||||
echo " ℹ️ GET Logout-Route bereits vorhanden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Routes-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 5. LoginController erweitern
|
||||
echo "\n5. 🔐 LoginController erweitern...\n";
|
||||
$controllerPath = 'app/Http/Controllers/Auth/LoginController.php';
|
||||
if (file_exists($controllerPath)) {
|
||||
$content = file_get_contents($controllerPath);
|
||||
|
||||
// Prüfe ob Logout-Methode GET und POST unterstützt
|
||||
if (strpos($content, 'public function logout(Request $request)') !== false) {
|
||||
echo " ✅ Logout-Methode unterstützt bereits GET und POST\n";
|
||||
} else {
|
||||
echo " ℹ️ Logout-Methode prüfen...\n";
|
||||
}
|
||||
|
||||
// Zeige aktuelle Logout-Methode
|
||||
$lines = explode("\n", $content);
|
||||
$inLogoutMethod = false;
|
||||
$methodLines = [];
|
||||
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'public function logout') !== false) {
|
||||
$inLogoutMethod = true;
|
||||
$methodLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
} elseif ($inLogoutMethod && strpos($line, 'public function') !== false) {
|
||||
$inLogoutMethod = false;
|
||||
} elseif ($inLogoutMethod) {
|
||||
$methodLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
echo " 📋 Aktuelle Logout-Methode:\n";
|
||||
foreach ($methodLines as $line) {
|
||||
echo " $line\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ LoginController nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 6. Cache leeren
|
||||
echo "\n6. 🧹 Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
// 7. Test-Logout-Links erstellen
|
||||
echo "\n7. 🧪 Test-Logout-Links erstellen...\n";
|
||||
$testLinks = [
|
||||
'https://neonail.vogt.de.com/logout (GET)',
|
||||
'https://neonail.vogt.de.com/logout (POST)',
|
||||
'https://neonail.vogt.de.com/',
|
||||
'https://neonail.vogt.de.com/login'
|
||||
];
|
||||
|
||||
foreach ($testLinks as $link) {
|
||||
echo " 🔗 $link\n";
|
||||
}
|
||||
|
||||
// 8. Debug-Anleitung
|
||||
echo "\n8. 🔍 Debug-Anleitung...\n";
|
||||
echo " 📋 1. Öffnen Sie: https://neonail.vogt.de.com\n";
|
||||
echo " 📋 2. Melden Sie sich an\n";
|
||||
echo " 📋 3. Öffnen Sie Browser-Entwicklertools (F12)\n";
|
||||
echo " 📋 4. Gehen Sie zu Console-Tab\n";
|
||||
echo " 📋 5. Klicken Sie auf Ihren Benutzernamen\n";
|
||||
echo " 📋 6. Wählen Sie 'Abmelden'\n";
|
||||
echo " 📋 7. Schauen Sie nach JavaScript-Fehlern\n";
|
||||
echo " 📋 8. Gehen Sie zu Network-Tab\n";
|
||||
echo " 📋 9. Schauen Sie welche URL aufgerufen wird\n";
|
||||
echo " 📋 10. Testen Sie direkt: https://neonail.vogt.de.com/logout\n";
|
||||
|
||||
echo "\n✅ Detailliertes Logout-Debug abgeschlossen!\n";
|
||||
echo "🔗 Testen Sie jetzt:\n";
|
||||
echo "1. Das normale Logout über das Dropdown\n";
|
||||
echo "2. Den direkten Link: https://neonail.vogt.de.com/logout\n";
|
||||
echo "3. Teilen Sie alle Fehlermeldungen mit\n";
|
||||
?>
|
||||
218
debug-logout.php
218
debug-logout.php
@@ -1,218 +0,0 @@
|
||||
<?php
|
||||
// Debug: Logout-Problem systematisch debuggen
|
||||
echo "🚪 Debug: Logout-Problem systematisch debuggen\n";
|
||||
echo "=============================================\n\n";
|
||||
|
||||
// 1. Aktuelles Layout prüfen
|
||||
echo "1. 🎨 Aktuelles Layout prüfen...\n";
|
||||
$layoutPath = 'resources/views/layouts/app.blade.php';
|
||||
if (file_exists($layoutPath)) {
|
||||
$content = file_get_contents($layoutPath);
|
||||
|
||||
// Suche nach Logout-Form
|
||||
if (strpos($content, 'logout-form') !== false) {
|
||||
echo " ✅ Logout-Form gefunden\n";
|
||||
|
||||
// Zeige Logout-Form Details
|
||||
$lines = explode("\n", $content);
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
echo " 📋 Zeile " . ($lineNumber + 1) . ": " . trim($line) . "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Logout-Form nicht gefunden\n";
|
||||
}
|
||||
|
||||
// Prüfe Route-Verwendung
|
||||
if (strpos($content, '{{ route("logout") }}') !== false) {
|
||||
echo " ✅ Laravel Route wird verwendet\n";
|
||||
} elseif (strpos($content, 'https://neonail.vogt.de.com/logout') !== false) {
|
||||
echo " ❌ Hardcodierte URL wird verwendet\n";
|
||||
} else {
|
||||
echo " ❓ Unbekannte Logout-Konfiguration\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Layout-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 2. Routes prüfen
|
||||
echo "\n2. 🛣️ Routes prüfen...\n";
|
||||
$routesPath = 'routes/web.php';
|
||||
if (file_exists($routesPath)) {
|
||||
$content = file_get_contents($routesPath);
|
||||
|
||||
// Zeige alle Logout-bezogenen Zeilen
|
||||
$lines = explode("\n", $content);
|
||||
$logoutLines = [];
|
||||
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
$logoutLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($logoutLines)) {
|
||||
echo " ✅ Logout-Routes gefunden:\n";
|
||||
foreach ($logoutLines as $line) {
|
||||
echo " 📋 $line\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Keine Logout-Routes gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Routes-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 3. LoginController prüfen
|
||||
echo "\n3. 🔐 LoginController prüfen...\n";
|
||||
$controllerPath = 'app/Http/Controllers/Auth/LoginController.php';
|
||||
if (file_exists($controllerPath)) {
|
||||
$content = file_get_contents($controllerPath);
|
||||
|
||||
if (strpos($content, 'logout') !== false) {
|
||||
echo " ✅ Logout-Methode gefunden\n";
|
||||
|
||||
// Zeige Logout-Methode
|
||||
$lines = explode("\n", $content);
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
echo " 📋 Zeile " . ($lineNumber + 1) . ": " . trim($line) . "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Logout-Methode nicht gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ LoginController nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 4. Laravel Route-Liste generieren
|
||||
echo "\n4. 🛣️ Laravel Route-Liste generieren...\n";
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Laravel Bootstrap
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// Route-Liste abrufen
|
||||
$routes = \Illuminate\Support\Facades\Route::getRoutes();
|
||||
|
||||
$logoutRoutes = [];
|
||||
foreach ($routes as $route) {
|
||||
$uri = $route->uri();
|
||||
$methods = $route->methods();
|
||||
$name = $route->getName();
|
||||
|
||||
if (strpos($uri, 'logout') !== false || strpos($name, 'logout') !== false) {
|
||||
$logoutRoutes[] = [
|
||||
'uri' => $uri,
|
||||
'methods' => $methods,
|
||||
'name' => $name
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($logoutRoutes)) {
|
||||
echo " ❌ Keine Logout-Routes in Laravel registriert\n";
|
||||
} else {
|
||||
echo " ✅ Logout-Routes in Laravel gefunden:\n";
|
||||
foreach ($logoutRoutes as $route) {
|
||||
$methods = implode('|', $route['methods']);
|
||||
$name = $route['name'] ?: 'kein Name';
|
||||
echo " 📋 $methods $uri ($name)\n";
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Fehler beim Abrufen der Routes: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
// 5. Cache-Status prüfen
|
||||
echo "\n5. 🧹 Cache-Status prüfen...\n";
|
||||
$cacheFiles = [
|
||||
'bootstrap/cache/packages.php' => 'Packages Cache',
|
||||
'bootstrap/cache/services.php' => 'Services Cache',
|
||||
'bootstrap/cache/routes.php' => 'Routes Cache',
|
||||
'bootstrap/cache/config.php' => 'Config Cache'
|
||||
];
|
||||
|
||||
foreach ($cacheFiles as $cacheFile => $description) {
|
||||
if (file_exists($cacheFile)) {
|
||||
echo " ⚠️ Cache vorhanden: $description\n";
|
||||
} else {
|
||||
echo " ✅ Cache geleert: $description\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Test-Logout-URLs generieren
|
||||
echo "\n6. 🔗 Test-Logout-URLs:\n";
|
||||
$testUrls = [
|
||||
'https://neonail.vogt.de.com/logout',
|
||||
'https://neonail.vogt.de.com/logout (POST)',
|
||||
'https://neonail.vogt.de.com/logout (GET)',
|
||||
'https://neonail.vogt.de.com/',
|
||||
'https://neonail.vogt.de.com/login'
|
||||
];
|
||||
|
||||
foreach ($testUrls as $url) {
|
||||
echo " 🔗 $url\n";
|
||||
}
|
||||
|
||||
// 7. Layout korrigieren (falls nötig)
|
||||
echo "\n7. 🔧 Layout korrigieren...\n";
|
||||
$layoutPath = 'resources/views/layouts/app.blade.php';
|
||||
if (file_exists($layoutPath)) {
|
||||
$content = file_get_contents($layoutPath);
|
||||
|
||||
// Ersetze alle hardcodierten Logout-URLs
|
||||
$replacements = [
|
||||
'action="https://neonail.vogt.de.com/logout"' => 'action="{{ route("logout") }}"',
|
||||
'href="https://neonail.vogt.de.com/logout"' => 'href="{{ route("logout") }}"',
|
||||
'action="http://neonail.vogt.de.com/logout"' => 'action="{{ route("logout") }}"',
|
||||
'href="http://neonail.vogt.de.com/logout"' => 'href="{{ route("logout") }}"'
|
||||
];
|
||||
|
||||
$modified = false;
|
||||
foreach ($replacements as $old => $new) {
|
||||
if (strpos($content, $old) !== false) {
|
||||
$content = str_replace($old, $new, $content);
|
||||
$modified = true;
|
||||
echo " ✅ Ersetzt: $old → $new\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($modified) {
|
||||
file_put_contents($layoutPath, $content);
|
||||
echo " ✅ Layout aktualisiert\n";
|
||||
} else {
|
||||
echo " ℹ️ Keine Änderungen nötig\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Layout-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 8. Cache leeren
|
||||
echo "\n8. 🧹 Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
echo "\n✅ Logout-Debug abgeschlossen!\n";
|
||||
echo "🔗 Testen Sie jetzt:\n";
|
||||
echo "1. Klicken Sie auf Ihren Benutzernamen (oben rechts)\n";
|
||||
echo "2. Wählen Sie 'Abmelden' aus dem Dropdown\n";
|
||||
echo "3. Falls das nicht funktioniert, versuchen Sie direkt:\n";
|
||||
echo " - https://neonail.vogt.de.com/logout\n";
|
||||
echo "\n📋 Falls Problem besteht:\n";
|
||||
echo "- Prüfen Sie Browser-Entwicklertools (F12) für Fehler\n";
|
||||
echo "- Schauen Sie in die Laravel-Logs: tail -f storage/logs/laravel.log\n";
|
||||
echo "- Teilen Sie die Debug-Ausgabe mit\n";
|
||||
?>
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# NeoNail DB - Hersteller-Feature Deployment Script
|
||||
# Führt die neuen Migrationen aus und aktualisiert die Anwendung
|
||||
|
||||
echo "🎨 NeoNail DB - Hersteller-Feature Deployment"
|
||||
echo "=============================================="
|
||||
|
||||
# Prüfe, ob wir im richtigen Verzeichnis sind
|
||||
if [ ! -f "artisan" ]; then
|
||||
echo "❌ Fehler: artisan Datei nicht gefunden. Bitte führen Sie das Script im Laravel-Root-Verzeichnis aus."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📋 Prüfe Migration-Reihenfolge..."
|
||||
# Stelle sicher, dass die manufacturer_id Migration nach der nail_polishes Migration kommt
|
||||
if [ -f "database/migrations/2025_01_15_000001_add_manufacturer_id_to_nail_polishes_table.php" ]; then
|
||||
echo "🔄 Korrigiere Migration-Reihenfolge..."
|
||||
mv database/migrations/2025_01_15_000001_add_manufacturer_id_to_nail_polishes_table.php \
|
||||
database/migrations/2025_08_10_020524_add_manufacturer_id_to_nail_polishes_table.php
|
||||
echo "✅ Migration-Reihenfolge korrigiert"
|
||||
fi
|
||||
|
||||
echo "📋 Führe Migrationen aus..."
|
||||
php artisan migrate --force
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Migrationen erfolgreich ausgeführt"
|
||||
else
|
||||
echo "❌ Fehler beim Ausführen der Migrationen"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔄 Cache leeren..."
|
||||
php artisan config:clear
|
||||
php artisan route:clear
|
||||
php artisan view:clear
|
||||
|
||||
echo "📦 Composer Autoload aktualisieren..."
|
||||
composer dump-autoload
|
||||
|
||||
echo "🔗 Storage-Link prüfen..."
|
||||
if [ ! -L "public/storage" ]; then
|
||||
echo "📎 Storage-Link erstellen..."
|
||||
php artisan storage:link
|
||||
else
|
||||
echo "✅ Storage-Link bereits vorhanden"
|
||||
fi
|
||||
|
||||
echo "🔒 Berechtigungen setzen..."
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
chmod 664 database.sqlite
|
||||
|
||||
echo "✅ Hersteller-Feature erfolgreich deployed!"
|
||||
echo ""
|
||||
echo "🎯 Neue Features:"
|
||||
echo " - Hersteller-Verwaltung für alle User"
|
||||
echo " - Hersteller-Auswahl beim Erstellen von Nagellacken"
|
||||
echo " - Automatische Hersteller-Erstellung"
|
||||
echo " - Hersteller-Statistiken im Admin-Bereich"
|
||||
echo ""
|
||||
echo "🌐 Zugriff:"
|
||||
echo " - Hersteller-Übersicht: /manufacturers"
|
||||
echo " - Neuen Hersteller erstellen: /manufacturers/create"
|
||||
echo ""
|
||||
echo "🚀 Anwendung ist bereit!"
|
||||
@@ -1,64 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# NeoNail DB SQLite Deployment Script
|
||||
echo "🚀 NeoNail DB SQLite Deployment gestartet..."
|
||||
|
||||
# 1. SQLite-Datenbank erstellen (falls nicht vorhanden)
|
||||
echo "🗄️ SQLite-Datenbank erstellen..."
|
||||
if [ ! -f database.sqlite ]; then
|
||||
touch database.sqlite
|
||||
echo "✅ SQLite-Datenbank erstellt"
|
||||
else
|
||||
echo "✅ SQLite-Datenbank bereits vorhanden"
|
||||
fi
|
||||
|
||||
# 2. Berechtigungen für SQLite-Datenbank setzen
|
||||
echo "🔐 SQLite-Berechtigungen setzen..."
|
||||
chmod 664 database.sqlite
|
||||
if command -v chown &> /dev/null; then
|
||||
chown www-data:www-data database.sqlite 2>/dev/null || echo "⚠️ chown nicht verfügbar"
|
||||
fi
|
||||
|
||||
# 3. Composer Dependencies optimieren
|
||||
echo "📦 Composer Dependencies optimieren..."
|
||||
composer install --optimize-autoloader --no-dev
|
||||
|
||||
# 4. Cache leeren
|
||||
echo "🧹 Cache leeren..."
|
||||
php artisan config:clear
|
||||
php artisan cache:clear
|
||||
php artisan view:clear
|
||||
php artisan route:clear
|
||||
|
||||
# 5. Storage-Link erstellen
|
||||
echo "🔗 Storage-Link erstellen..."
|
||||
php artisan storage:link
|
||||
|
||||
# 6. Berechtigungen setzen
|
||||
echo "🔐 Berechtigungen setzen..."
|
||||
chmod -R 755 storage/
|
||||
chmod -R 755 bootstrap/cache/
|
||||
chmod 644 .env
|
||||
|
||||
# 7. Datenbank-Migrationen
|
||||
echo "🗄️ Datenbank-Migrationen..."
|
||||
php artisan migrate --force
|
||||
|
||||
# 8. Cache optimieren
|
||||
echo "⚡ Cache optimieren..."
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
|
||||
echo "✅ SQLite Deployment abgeschlossen!"
|
||||
echo ""
|
||||
echo "📋 Nächste Schritte:"
|
||||
echo "1. Admin-User erstellen: php artisan tinker"
|
||||
echo "2. Testen der Anwendung"
|
||||
echo "3. HTTPS aktivieren"
|
||||
echo "4. Backup-Strategie einrichten"
|
||||
echo ""
|
||||
echo "💡 SQLite Vorteile:"
|
||||
echo "- Keine MySQL-Installation nötig"
|
||||
echo "- Einfaches Backup (nur eine Datei)"
|
||||
echo "- Minimaler Konfigurationsaufwand"
|
||||
43
deploy.sh
43
deploy.sh
@@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# NeoNail DB Deployment Script
|
||||
echo "🚀 NeoNail DB Deployment gestartet..."
|
||||
|
||||
# 1. Composer Dependencies optimieren
|
||||
echo "📦 Composer Dependencies optimieren..."
|
||||
composer install --optimize-autoloader --no-dev
|
||||
|
||||
# 2. Cache leeren
|
||||
echo "🧹 Cache leeren..."
|
||||
php artisan config:clear
|
||||
php artisan cache:clear
|
||||
php artisan view:clear
|
||||
php artisan route:clear
|
||||
|
||||
# 3. Storage-Link erstellen
|
||||
echo "🔗 Storage-Link erstellen..."
|
||||
php artisan storage:link
|
||||
|
||||
# 4. Berechtigungen setzen
|
||||
echo "🔐 Berechtigungen setzen..."
|
||||
chmod -R 755 storage/
|
||||
chmod -R 755 bootstrap/cache/
|
||||
chmod 644 .env
|
||||
|
||||
# 5. Datenbank-Migrationen
|
||||
echo "🗄️ Datenbank-Migrationen..."
|
||||
php artisan migrate --force
|
||||
|
||||
# 6. Cache optimieren
|
||||
echo "⚡ Cache optimieren..."
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
|
||||
echo "✅ Deployment abgeschlossen!"
|
||||
echo ""
|
||||
echo "📋 Nächste Schritte:"
|
||||
echo "1. Admin-User erstellen: php artisan tinker"
|
||||
echo "2. Testen der Anwendung"
|
||||
echo "3. HTTPS aktivieren"
|
||||
echo "4. Backup-Strategie einrichten"
|
||||
@@ -1,111 +0,0 @@
|
||||
# NeoNail DB - Deployment Checklist
|
||||
|
||||
## Vorbereitung (Lokal)
|
||||
|
||||
### 1. Produktions-Umgebung konfigurieren
|
||||
```bash
|
||||
# .env.production erstellen
|
||||
cp .env .env.production
|
||||
|
||||
# Produktions-Einstellungen in .env.production:
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://ihre-domain.de
|
||||
|
||||
# Datenbank-Einstellungen
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=ihre_datenbank
|
||||
DB_USERNAME=ihr_username
|
||||
DB_PASSWORD=ihr_passwort
|
||||
```
|
||||
|
||||
### 2. Dependencies optimieren
|
||||
```bash
|
||||
composer install --optimize-autoloader --no-dev
|
||||
npm run build # falls vorhanden
|
||||
```
|
||||
|
||||
### 3. Cache leeren und optimieren
|
||||
```bash
|
||||
php artisan config:clear
|
||||
php artisan cache:clear
|
||||
php artisan view:clear
|
||||
php artisan route:clear
|
||||
```
|
||||
|
||||
### 4. Storage-Link erstellen
|
||||
```bash
|
||||
php artisan storage:link
|
||||
```
|
||||
|
||||
## Upload zum Webspace
|
||||
|
||||
### 1. Dateien hochladen
|
||||
- Alle Dateien außer `node_modules/`, `vendor/` (falls vorhanden)
|
||||
- `.env.production` als `.env` hochladen
|
||||
- `storage/` und `bootstrap/cache/` Ordner mit Schreibrechten
|
||||
|
||||
### 2. Composer installieren (falls verfügbar)
|
||||
```bash
|
||||
composer install --optimize-autoloader --no-dev
|
||||
```
|
||||
|
||||
### 3. Datenbank-Migrationen
|
||||
```bash
|
||||
php artisan migrate --force
|
||||
```
|
||||
|
||||
### 4. Berechtigungen setzen
|
||||
```bash
|
||||
chmod -R 755 storage/
|
||||
chmod -R 755 bootstrap/cache/
|
||||
chmod 644 .env
|
||||
```
|
||||
|
||||
## Nach dem Upload
|
||||
|
||||
### 1. Cache optimieren
|
||||
```bash
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
```
|
||||
|
||||
### 2. Admin-User erstellen
|
||||
```bash
|
||||
php artisan tinker
|
||||
```
|
||||
```php
|
||||
use App\Models\User;
|
||||
User::create([
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@neonail.com',
|
||||
'password' => bcrypt('ihr_admin_passwort')
|
||||
]);
|
||||
```
|
||||
|
||||
### 3. Testen
|
||||
- Login mit admin@neonail.com
|
||||
- Neuen Lack erstellen
|
||||
- Bild-Upload testen
|
||||
- Mobile-Ansicht prüfen
|
||||
|
||||
## Wichtige Hinweise
|
||||
|
||||
### Sicherheit
|
||||
- APP_KEY muss gesetzt sein
|
||||
- Starke Passwörter verwenden
|
||||
- HTTPS verwenden
|
||||
- .env nicht öffentlich zugänglich
|
||||
|
||||
### Performance
|
||||
- OPcache aktivieren (falls verfügbar)
|
||||
- Redis für Cache (optional)
|
||||
- CDN für Bilder (optional)
|
||||
|
||||
### Backup
|
||||
- Regelmäßige Datenbank-Backups
|
||||
- Storage-Ordner sichern
|
||||
- Code-Backup
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🚨 EMERGENCY: Apache komplett reparieren"
|
||||
echo "======================================="
|
||||
|
||||
# 1. Apache-Status prüfen
|
||||
echo "1. 🔍 Apache-Status prüfen..."
|
||||
systemctl status apache2 2>/dev/null || service apache2 status 2>/dev/null || echo " ⚠️ Apache-Status nicht verfügbar"
|
||||
|
||||
# 2. Apache stoppen
|
||||
echo "2. 🛑 Apache stoppen..."
|
||||
systemctl stop apache2 2>/dev/null || service apache2 stop 2>/dev/null || echo " ⚠️ Apache stop fehlgeschlagen"
|
||||
|
||||
# 3. .htaccess zurücksetzen
|
||||
echo "3. 🔄 .htaccess zurücksetzen..."
|
||||
if [ -f public/.htaccess.backup ]; then
|
||||
cp public/.htaccess.backup public/.htaccess
|
||||
echo " ✅ .htaccess aus Backup wiederhergestellt"
|
||||
elif [ -f public/.htaccess.simple ]; then
|
||||
cp public/.htaccess.simple public/.htaccess
|
||||
echo " ✅ .htaccess aus simple wiederhergestellt"
|
||||
else
|
||||
# Erstelle minimale .htaccess
|
||||
cat > public/.htaccess << 'EOF'
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
EOF
|
||||
echo " ✅ Minimale .htaccess erstellt"
|
||||
fi
|
||||
|
||||
# 4. Apache-Module zurücksetzen
|
||||
echo "4. 🔧 Apache-Module zurücksetzen..."
|
||||
a2dismod headers 2>/dev/null || echo " ⚠️ mod_headers deaktivieren fehlgeschlagen"
|
||||
a2enmod rewrite 2>/dev/null || echo " ⚠️ mod_rewrite aktivieren fehlgeschlagen"
|
||||
|
||||
# 5. Apache-Konfiguration testen
|
||||
echo "5. 🧪 Apache-Konfiguration testen..."
|
||||
apache2ctl -t 2>/dev/null && echo " ✅ Apache-Konfiguration OK" || echo " ❌ Apache-Konfiguration fehlerhaft"
|
||||
|
||||
# 6. Apache starten
|
||||
echo "6. 🚀 Apache starten..."
|
||||
systemctl start apache2 2>/dev/null || service apache2 start 2>/dev/null || echo " ⚠️ Apache start fehlgeschlagen"
|
||||
|
||||
# 7. Apache-Status prüfen
|
||||
echo "7. 🔍 Apache-Status nach Start..."
|
||||
systemctl status apache2 2>/dev/null || service apache2 status 2>/dev/null || echo " ⚠️ Apache-Status nicht verfügbar"
|
||||
|
||||
# 8. Test-Request
|
||||
echo "8. 🧪 Test-Request..."
|
||||
curl -I http://localhost/ 2>/dev/null && echo " ✅ Apache antwortet" || echo " ❌ Apache antwortet nicht"
|
||||
|
||||
echo ""
|
||||
echo "✅ Emergency Apache Fix abgeschlossen!"
|
||||
echo ""
|
||||
echo "🔗 Testen Sie jetzt:"
|
||||
echo "1. http://neonail.vogt.de.com"
|
||||
echo "2. https://neonail.vogt.de.com"
|
||||
echo ""
|
||||
echo "📝 Falls Problem besteht:"
|
||||
echo "- Prüfen Sie: systemctl status apache2"
|
||||
echo "- Schauen Sie in: /var/log/apache2/error.log"
|
||||
echo "- Führen Sie: apache2ctl -t"
|
||||
@@ -1,55 +0,0 @@
|
||||
APP_NAME="NeoNail DB"
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:+LTZYPKjkZ+O3iFTgU2sS+9bNvxxvG8Kw8JSEPiG7Rs=
|
||||
APP_DEBUG=false
|
||||
APP_URL=http://192.168.30.81
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=database.sqlite
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailpit
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_HOST=
|
||||
PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
@@ -1,64 +0,0 @@
|
||||
APP_NAME="NeoNail DB"
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:YOUR_APP_KEY_HERE
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://ihre-domain.de
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=error
|
||||
|
||||
# SQLite Konfiguration (Einfachste Option)
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=/path/to/database.sqlite
|
||||
|
||||
# MySQL Konfiguration (Alternative)
|
||||
# DB_CONNECTION=mysql
|
||||
# DB_HOST=localhost
|
||||
# DB_PORT=3306
|
||||
# DB_DATABASE=ihre_datenbank
|
||||
# DB_USERNAME=ihr_username
|
||||
# DB_PASSWORD=ihr_passwort
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailpit
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_HOST=
|
||||
PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
@@ -1,55 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔧 Fix: HTTP 405 Method Not Allowed"
|
||||
echo "==================================="
|
||||
|
||||
# 1. Debug-Script ausführen
|
||||
echo "1. 🔍 Diagnose ausführen..."
|
||||
php debug-405-error.php
|
||||
|
||||
echo ""
|
||||
echo "2. 🧹 Laravel Cache leeren..."
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen"
|
||||
|
||||
echo ""
|
||||
echo "3. 🔄 Route-Cache neu generieren..."
|
||||
php artisan route:cache 2>/dev/null || echo "⚠️ route:cache übersprungen"
|
||||
|
||||
echo ""
|
||||
echo "4. 📝 .env Debug aktivieren..."
|
||||
if [ -f .env ]; then
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
sed -i 's/APP_ENV=production/APP_ENV=local/' .env
|
||||
echo "✅ Debug-Modus aktiviert"
|
||||
else
|
||||
echo "❌ .env Datei nicht gefunden"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "5. 🔍 Apache-Logs prüfen..."
|
||||
if [ -f /var/log/apache2/error.log ]; then
|
||||
echo "📋 Letzte Apache-Fehler:"
|
||||
tail -10 /var/log/apache2/error.log | grep -E "(405|Method|Not Allowed)" || echo "Keine 405-Fehler gefunden"
|
||||
else
|
||||
echo "⚠️ Apache-Logs nicht verfügbar"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "6. 🧪 Route-Test..."
|
||||
echo "📋 Teste POST-Route direkt:"
|
||||
curl -X POST https://neonail.vogt.de.com/create-nail-polish \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-d "name=Test&number=123&_token=test" \
|
||||
-w "\nHTTP-Status: %{http_code}\n" \
|
||||
2>/dev/null || echo "❌ curl nicht verfügbar"
|
||||
|
||||
echo ""
|
||||
echo "✅ Fix abgeschlossen!"
|
||||
echo ""
|
||||
echo "🔧 Nächste Schritte:"
|
||||
echo "1. Testen Sie das Formular erneut"
|
||||
echo "2. Prüfen Sie die Browser-Entwicklertools (F12) für Details"
|
||||
echo "3. Schauen Sie in storage/logs/laravel.log für Laravel-Fehler"
|
||||
echo "4. Falls Problem besteht: php artisan route:list | grep store"
|
||||
@@ -1,284 +0,0 @@
|
||||
<?php
|
||||
// Fix: AdminController mit automatischer E-Mail-Versendung erweitern
|
||||
echo "📧 Fix: AdminController mit E-Mail-Versendung erweitern\n";
|
||||
echo "=====================================================\n\n";
|
||||
|
||||
// 1. AdminController erweitern
|
||||
echo "1. 🔧 AdminController erweitern...\n";
|
||||
|
||||
$controllerContent = '<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\NailPolish;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class AdminController extends Controller
|
||||
{
|
||||
/**
|
||||
* Dashboard für Administratoren
|
||||
*/
|
||||
public function dashboard()
|
||||
{
|
||||
$totalUsers = User::count();
|
||||
$totalNailPolishes = NailPolish::count();
|
||||
$recentUsers = User::latest()->take(5)->get();
|
||||
$recentNailPolishes = NailPolish::latest()->take(5)->get();
|
||||
|
||||
return view("admin.dashboard", compact("totalUsers", "totalNailPolishes", "recentUsers", "recentNailPolishes"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste aller Benutzer
|
||||
*/
|
||||
public function users(Request $request)
|
||||
{
|
||||
$search = $request->get("search");
|
||||
|
||||
$users = User::when($search, function($query) use ($search) {
|
||||
return $query->where("name", "like", "%{$search}%")
|
||||
->orWhere("email", "like", "%{$search}%");
|
||||
})->orderBy("name")->paginate(20);
|
||||
|
||||
return view("admin.users.index", compact("users", "search"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formular zum Erstellen eines neuen Benutzers
|
||||
*/
|
||||
public function createUser()
|
||||
{
|
||||
return view("admin.users.create");
|
||||
}
|
||||
|
||||
/**
|
||||
* Neuen Benutzer speichern
|
||||
*/
|
||||
public function storeUser(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
"name" => "required|string|max:255",
|
||||
"email" => "required|string|email|max:255|unique:users",
|
||||
"password" => "required|string|min:8|confirmed",
|
||||
]);
|
||||
|
||||
// Passwort für E-Mail speichern (wird nach dem Speichern gelöscht)
|
||||
$plainPassword = $request->password;
|
||||
|
||||
// User erstellen
|
||||
$user = User::create([
|
||||
"name" => $request->name,
|
||||
"email" => $request->email,
|
||||
"password" => Hash::make($request->password),
|
||||
"is_admin" => $request->has("is_admin"),
|
||||
]);
|
||||
|
||||
// Willkommens-E-Mail senden
|
||||
try {
|
||||
Mail::send("emails.welcome-user", [
|
||||
"user" => $user,
|
||||
"password" => $plainPassword
|
||||
], function($message) use ($user) {
|
||||
$message->to($user->email, $user->name)
|
||||
->subject("🎨 Willkommen bei der NeoNail DB - Ihre Login-Daten")
|
||||
->from(config("mail.from.address"), config("mail.from.name"));
|
||||
});
|
||||
|
||||
// Admin-Bestätigung senden
|
||||
Mail::raw("Hallo Admin!
|
||||
|
||||
Ein neuer User wurde erfolgreich erstellt und eine Willkommens-E-Mail gesendet.
|
||||
|
||||
📋 User-Details:
|
||||
- Name: {$user->name}
|
||||
- E-Mail: {$user->email}
|
||||
- Admin-Status: " . ($user->isAdmin() ? "Ja" : "Nein") . "
|
||||
- Erstellt: " . now() . "
|
||||
|
||||
Die Willkommens-E-Mail enthält:
|
||||
- Login-Daten (Website, E-Mail, Passwort)
|
||||
- Aufforderung zum Passwort-Ändern
|
||||
- Feature-Übersicht
|
||||
- Direkte Links zur Anwendung
|
||||
|
||||
Viele Grüße,
|
||||
NeoNail DB System", function($message) {
|
||||
$message->to("oliver@vogt.de.com", "Admin")
|
||||
->subject("✅ NeoNail DB - Neuer User erstellt")
|
||||
->from(config("mail.from.address"), config("mail.from.name"));
|
||||
});
|
||||
|
||||
$successMessage = "Benutzer erfolgreich erstellt! Willkommens-E-Mail wurde gesendet.";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// User wurde erstellt, aber E-Mail fehlgeschlagen
|
||||
\Log::error("Fehler beim Senden der Willkommens-E-Mail: " . $e->getMessage());
|
||||
$successMessage = "Benutzer erfolgreich erstellt! E-Mail konnte nicht gesendet werden.";
|
||||
}
|
||||
|
||||
return redirect()->route("admin.users.index")
|
||||
->with("success", $successMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formular zum Bearbeiten eines Benutzers
|
||||
*/
|
||||
public function editUser(User $user)
|
||||
{
|
||||
return view("admin.users.edit", compact("user"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Benutzer aktualisieren
|
||||
*/
|
||||
public function updateUser(Request $request, User $user)
|
||||
{
|
||||
$request->validate([
|
||||
"name" => "required|string|max:255",
|
||||
"email" => "required|string|email|max:255|unique:users,email," . $user->id,
|
||||
"password" => "nullable|string|min:8|confirmed",
|
||||
]);
|
||||
|
||||
$user->name = $request->name;
|
||||
$user->email = $request->email;
|
||||
$user->is_admin = $request->has("is_admin");
|
||||
|
||||
if ($request->filled("password")) {
|
||||
$user->password = Hash::make($request->password);
|
||||
}
|
||||
|
||||
$user->save();
|
||||
|
||||
return redirect()->route("admin.users.index")
|
||||
->with("success", "Benutzer erfolgreich aktualisiert!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Benutzer löschen
|
||||
*/
|
||||
public function destroyUser(User $user)
|
||||
{
|
||||
$userName = $user->name;
|
||||
$userEmail = $user->email;
|
||||
|
||||
$user->delete();
|
||||
|
||||
// Admin-Benachrichtigung über gelöschten User
|
||||
try {
|
||||
Mail::raw("Hallo Admin!
|
||||
|
||||
Ein User wurde erfolgreich gelöscht.
|
||||
|
||||
📋 Gelöschter User:
|
||||
- Name: {$userName}
|
||||
- E-Mail: {$userEmail}
|
||||
- Gelöscht: " . now() . "
|
||||
|
||||
Viele Grüße,
|
||||
NeoNail DB System", function($message) {
|
||||
$message->to("oliver@vogt.de.com", "Admin")
|
||||
->subject("🗑️ NeoNail DB - User gelöscht")
|
||||
->from(config("mail.from.address"), config("mail.from.name"));
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("Fehler beim Senden der Lösch-Benachrichtigung: " . $e->getMessage());
|
||||
}
|
||||
|
||||
return redirect()->route("admin.users.index")
|
||||
->with("success", "Benutzer erfolgreich gelöscht!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Statistiken anzeigen
|
||||
*/
|
||||
public function statistics()
|
||||
{
|
||||
$totalUsers = User::count();
|
||||
$totalNailPolishes = NailPolish::count();
|
||||
$usersWithCollections = User::has("nailPolishes")->count();
|
||||
$averageCollectionSize = User::withCount("nailPolishes")->avg("nail_polishes_count");
|
||||
|
||||
$topUsers = User::withCount("nailPolishes")
|
||||
->orderBy("nail_polishes_count", "desc")
|
||||
->take(10)
|
||||
->get();
|
||||
|
||||
return view("admin.statistics", compact(
|
||||
"totalUsers",
|
||||
"totalNailPolishes",
|
||||
"usersWithCollections",
|
||||
"averageCollectionSize",
|
||||
"topUsers"
|
||||
));
|
||||
}
|
||||
}';
|
||||
|
||||
file_put_contents('app/Http/Controllers/AdminController.php', $controllerContent);
|
||||
echo " ✅ AdminController erweitert\n";
|
||||
|
||||
// 2. E-Mail-Verzeichnis erstellen
|
||||
echo "2. 📁 E-Mail-Verzeichnis erstellen...\n";
|
||||
$emailDir = 'resources/views/emails';
|
||||
if (!is_dir($emailDir)) {
|
||||
mkdir($emailDir, 0755, true);
|
||||
echo " ✅ E-Mail-Verzeichnis erstellt: $emailDir\n";
|
||||
} else {
|
||||
echo " ℹ️ E-Mail-Verzeichnis existiert bereits: $emailDir\n";
|
||||
}
|
||||
|
||||
// 3. Cache leeren
|
||||
echo "3. 🧹 Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
// 4. Test-E-Mail senden
|
||||
echo "4. 📧 Test-E-Mail senden...\n";
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Laravel Bootstrap
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// Test-User erstellen
|
||||
$testUser = new \App\Models\User();
|
||||
$testUser->name = 'Test User';
|
||||
$testUser->email = 'test@example.com';
|
||||
$testUser->password = 'testpassword123';
|
||||
$testUser->is_admin = false;
|
||||
|
||||
// Test-E-Mail senden
|
||||
$result = \Illuminate\Support\Facades\Mail::send('emails.welcome-user', [
|
||||
'user' => $testUser,
|
||||
'password' => 'testpassword123'
|
||||
], function($message) use ($testUser) {
|
||||
$message->to('oliver@vogt.de.com', 'Admin')
|
||||
->subject('🧪 Test: NeoNail DB Willkommens-E-Mail Template')
|
||||
->from(config('mail.from.address'), config('mail.from.name'));
|
||||
});
|
||||
|
||||
echo " ✅ Test-E-Mail erfolgreich gesendet!\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Test-E-Mail Fehler: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
echo "\n✅ AdminController mit E-Mail-Versendung erweitert!\n";
|
||||
echo "🔗 Testen Sie jetzt:\n";
|
||||
echo "1. Gehen Sie zu: https://neonail.vogt.de.com/admin/users/create\n";
|
||||
echo "2. Erstellen Sie einen neuen User\n";
|
||||
echo "3. Der User erhält automatisch eine Willkommens-E-Mail\n";
|
||||
echo "4. Sie erhalten eine Admin-Bestätigung\n";
|
||||
echo "\n📧 Die Willkommens-E-Mail enthält:\n";
|
||||
echo "- Login-Daten (Website, E-Mail, Passwort)\n";
|
||||
echo "- Aufforderung zum Passwort-Ändern\n";
|
||||
echo "- Feature-Übersicht\n";
|
||||
echo "- Direkte Links zur Anwendung\n";
|
||||
echo "- Admin-spezifische Informationen (falls Admin)\n";
|
||||
?>
|
||||
@@ -1,291 +0,0 @@
|
||||
<?php
|
||||
// Fix: Admin-Layout korrigieren
|
||||
echo "👑 Fix: Admin-Layout korrigieren\n";
|
||||
echo "==============================\n\n";
|
||||
|
||||
// 1. Layout-Datei korrigieren
|
||||
echo "1. 🎨 Layout-Datei korrigieren...\n";
|
||||
|
||||
$layoutContent = '<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>@yield("title", "NeoNail Datenbank")</title>
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background: rgba(255, 255, 255, 0.95) !important;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.card {
|
||||
border: none;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||
border: none;
|
||||
border-radius: 25px;
|
||||
padding: 10px 25px;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(45deg, #5a6fd8, #6a4190);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.nail-polish-card {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.nail-polish-card:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.nail-polish-image {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
border-radius: 25px;
|
||||
border: 2px solid #e9ecef;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.search-box:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dropdown-Menüs über alle anderen Elemente legen */
|
||||
.dropdown-menu {
|
||||
z-index: 9999 !important;
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
/* Navbar hat höheren z-index */
|
||||
.navbar {
|
||||
z-index: 1000 !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Dropdown-Container */
|
||||
.dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Sicherstellen, dass Dropdowns über Cards angezeigt werden */
|
||||
.navbar-nav .dropdown-menu {
|
||||
z-index: 9999 !important;
|
||||
position: absolute !important;
|
||||
top: 100% !important;
|
||||
left: 0 !important;
|
||||
float: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@yield("styles")
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light">
|
||||
<div class="container">
|
||||
<a class="navbar-brand fw-bold" href="{{ route("user-nail-polishes.index") }}">
|
||||
<i class="fas fa-palette me-2"></i>NeoNail DB
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto">
|
||||
@auth
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("user-nail-polishes.index") }}">
|
||||
<i class="fas fa-home me-1"></i>Meine Sammlung
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("user-nail-polishes.available") }}">
|
||||
<i class="fas fa-plus me-1"></i>Verfügbare Lacke
|
||||
</a>
|
||||
</li>
|
||||
@if(auth()->user()->isAdmin())
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-cog me-1"></i>Admin
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="{{ route("admin.dashboard") }}">Dashboard</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("admin.users.index") }}">Benutzer</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("nail-polishes.index") }}">Nagellacke</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("admin.statistics") }}">Statistiken</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@endif
|
||||
@endauth
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav">
|
||||
@guest
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("login") }}">Anmelden</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-user me-1"></i>{{ Auth::user()->name }}
|
||||
@if(auth()->user()->isAdmin())
|
||||
<span class="badge bg-primary ms-1">Admin</span>
|
||||
@endif
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route("logout") }}"
|
||||
onclick="event.preventDefault(); document.getElementById("logout-form").submit();">
|
||||
<i class="fas fa-sign-out-alt me-1"></i>Abmelden
|
||||
</a>
|
||||
<form id="logout-form" action="https://neonail.vogt.de.com/logout" method="POST" class="d-none">
|
||||
@csrf
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@endguest
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="py-4">
|
||||
<div class="container">
|
||||
@if(session("success"))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-check-circle me-2"></i>{{ session("success") }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session("error"))
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-exclamation-circle me-2"></i>{{ session("error") }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@yield("content")
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
@yield("scripts")
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
file_put_contents('resources/views/layouts/app.blade.php', $layoutContent);
|
||||
echo " ✅ Layout-Datei korrigiert\n";
|
||||
|
||||
// 2. User Model prüfen und korrigieren
|
||||
echo "2. 📋 User Model prüfen...\n";
|
||||
$userModelPath = 'app/Models/User.php';
|
||||
if (file_exists($userModelPath)) {
|
||||
$content = file_get_contents($userModelPath);
|
||||
|
||||
// Prüfe ob isAdmin Methode korrekt ist
|
||||
if (strpos($content, 'public function isAdmin()') !== false) {
|
||||
echo " ✅ isAdmin() Methode vorhanden\n";
|
||||
|
||||
// Prüfe ob die Methode korrekt implementiert ist
|
||||
if (strpos($content, '$this->is_admin || in_array($this->email') !== false) {
|
||||
echo " ✅ isAdmin() Methode korrekt implementiert\n";
|
||||
} else {
|
||||
echo " ⚠️ isAdmin() Methode könnte inkorrekt sein\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ isAdmin() Methode fehlt\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ User Model nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 3. Cache leeren
|
||||
echo "3. 🧹 Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
// 4. Admin-User Status prüfen
|
||||
echo "4. 👑 Admin-User Status prüfen...\n";
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Laravel Bootstrap
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// Alle User prüfen
|
||||
$users = \App\Models\User::all();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$isAdmin = $user->isAdmin();
|
||||
$isAdminColumn = $user->is_admin;
|
||||
$email = $user->email;
|
||||
|
||||
echo " 📧 $email:\n";
|
||||
echo " - is_admin Spalte: " . ($isAdminColumn ? 'Ja' : 'Nein') . "\n";
|
||||
echo " - isAdmin() Methode: " . ($isAdmin ? 'Ja' : 'Nein') . "\n";
|
||||
|
||||
if ($isAdminColumn && !$isAdmin) {
|
||||
echo " ⚠️ WARNUNG: Spalte ist true, aber Methode gibt false zurück!\n";
|
||||
} elseif (!$isAdminColumn && $isAdmin) {
|
||||
echo " ℹ️ INFO: Spalte ist false, aber Methode gibt true zurück (Email-Check)\n";
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Fehler beim Prüfen der User: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Admin-Layout korrigiert!\n";
|
||||
echo "🔗 Testen Sie jetzt:\n";
|
||||
echo "1. Melden Sie sich als neuer Admin an\n";
|
||||
echo "2. Prüfen Sie ob Admin-Menü sichtbar ist\n";
|
||||
echo "3. Prüfen Sie ob Admin-Badge neben dem Namen steht\n";
|
||||
echo "4. Versuchen Sie auf /admin/users zuzugreifen\n";
|
||||
echo "5. Falls Problem besteht, führen Sie php fix-admin-view.php aus\n";
|
||||
?>
|
||||
@@ -1,120 +0,0 @@
|
||||
<?php
|
||||
// Fix: Admin-Rolle zur Datenbank hinzufügen
|
||||
// Führen Sie dies aus, um die is_admin Spalte zu erstellen
|
||||
|
||||
echo "🔧 Fix: Admin-Rolle zur Datenbank hinzufügen\n";
|
||||
echo "==========================================\n\n";
|
||||
|
||||
try {
|
||||
// Datenbankverbindung
|
||||
$pdo = new PDO('sqlite:database.sqlite');
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
echo "1. 🔍 Prüfe users-Tabelle...\n";
|
||||
|
||||
// Prüfe ob is_admin Spalte existiert
|
||||
$stmt = $pdo->query("PRAGMA table_info(users)");
|
||||
$columns = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$hasAdminColumn = false;
|
||||
|
||||
echo " 📋 Aktuelle Spalten in users-Tabelle:\n";
|
||||
foreach ($columns as $column) {
|
||||
echo " - {$column['name']} ({$column['type']})\n";
|
||||
if ($column['name'] === 'is_admin') {
|
||||
$hasAdminColumn = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasAdminColumn) {
|
||||
echo "\n2. ➕ Füge is_admin Spalte hinzu...\n";
|
||||
|
||||
// Füge is_admin Spalte hinzu
|
||||
$pdo->exec("ALTER TABLE users ADD COLUMN is_admin BOOLEAN DEFAULT 0");
|
||||
echo " ✅ is_admin Spalte hinzugefügt\n";
|
||||
|
||||
// Prüfe nochmal
|
||||
$stmt = $pdo->query("PRAGMA table_info(users)");
|
||||
$columns = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$hasAdminColumn = false;
|
||||
|
||||
foreach ($columns as $column) {
|
||||
if ($column['name'] === 'is_admin') {
|
||||
$hasAdminColumn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasAdminColumn) {
|
||||
echo " ✅ is_admin Spalte erfolgreich erstellt\n";
|
||||
} else {
|
||||
echo " ❌ is_admin Spalte konnte nicht erstellt werden\n";
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
echo "\n2. ℹ️ is_admin Spalte existiert bereits\n";
|
||||
}
|
||||
|
||||
echo "\n3. 👑 Markiere bestehende Admin-User...\n";
|
||||
|
||||
// Markiere bestehende Admin-User
|
||||
$stmt = $pdo->prepare("UPDATE users SET is_admin = 1 WHERE email IN (?, ?)");
|
||||
$stmt->execute(['admin@neonail.com', 'neueradmin@neonail.com']);
|
||||
$affectedRows = $stmt->rowCount();
|
||||
echo " ✅ $affectedRows Admin-User aktualisiert\n";
|
||||
|
||||
echo "\n4. 📋 Zeige alle User mit Admin-Status...\n";
|
||||
|
||||
// Zeige alle User
|
||||
$stmt = $pdo->query("SELECT id, name, email, is_admin FROM users ORDER BY is_admin DESC, name");
|
||||
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
foreach ($users as $user) {
|
||||
$adminStatus = $user['is_admin'] ? '👑 Admin' : '👤 User';
|
||||
echo " - {$user['name']} ({$user['email']}) - {$adminStatus}\n";
|
||||
}
|
||||
|
||||
echo "\n5. 🧪 Test: Mache einen User zum Admin...\n";
|
||||
|
||||
// Finde einen User, der noch kein Admin ist
|
||||
$stmt = $pdo->prepare("SELECT id, name, email FROM users WHERE is_admin = 0 LIMIT 1");
|
||||
$stmt->execute();
|
||||
$testUser = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($testUser) {
|
||||
echo " 📝 Teste mit User: {$testUser['name']} ({$testUser['email']})\n";
|
||||
|
||||
// Mache User zum Admin
|
||||
$stmt = $pdo->prepare("UPDATE users SET is_admin = 1 WHERE id = ?");
|
||||
$stmt->execute([$testUser['id']]);
|
||||
|
||||
echo " ✅ User zum Admin gemacht\n";
|
||||
|
||||
// Prüfe Änderung
|
||||
$stmt = $pdo->prepare("SELECT is_admin FROM users WHERE id = ?");
|
||||
$stmt->execute([$testUser['id']]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($result['is_admin']) {
|
||||
echo " ✅ Admin-Status korrekt gesetzt\n";
|
||||
} else {
|
||||
echo " ❌ Admin-Status nicht korrekt gesetzt\n";
|
||||
}
|
||||
|
||||
// Mache User wieder zurück
|
||||
$stmt = $pdo->prepare("UPDATE users SET is_admin = 0 WHERE id = ?");
|
||||
$stmt->execute([$testUser['id']]);
|
||||
echo " 🔄 User-Status zurückgesetzt\n";
|
||||
|
||||
} else {
|
||||
echo " ℹ️ Alle User sind bereits Admins\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Admin-Rolle erfolgreich zur Datenbank hinzugefügt!\n";
|
||||
echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/admin/users\n";
|
||||
echo "📝 Sie können jetzt User zum Admin machen!\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "❌ Fehler: " . $e->getMessage() . "\n";
|
||||
echo "📍 Datei: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
}
|
||||
?>
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
// Admin-Rolle zur Datenbank hinzufügen
|
||||
// Führen Sie dies direkt auf dem Webspace aus
|
||||
|
||||
try {
|
||||
// Datenbankverbindung
|
||||
$pdo = new PDO('sqlite:database.sqlite');
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
echo "🔧 Admin-Rolle hinzufügen...\n";
|
||||
|
||||
// 1. Prüfe ob is_admin Spalte existiert
|
||||
$stmt = $pdo->query("PRAGMA table_info(users)");
|
||||
$columns = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$hasAdminColumn = false;
|
||||
|
||||
foreach ($columns as $column) {
|
||||
if ($column['name'] === 'is_admin') {
|
||||
$hasAdminColumn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasAdminColumn) {
|
||||
// 2. Füge is_admin Spalte hinzu
|
||||
$pdo->exec("ALTER TABLE users ADD COLUMN is_admin BOOLEAN DEFAULT 0");
|
||||
echo "✅ is_admin Spalte hinzugefügt\n";
|
||||
} else {
|
||||
echo "ℹ️ is_admin Spalte existiert bereits\n";
|
||||
}
|
||||
|
||||
// 3. Markiere bestehende Admin-User
|
||||
$stmt = $pdo->prepare("UPDATE users SET is_admin = 1 WHERE email IN (?, ?)");
|
||||
$stmt->execute(['admin@neonail.com', 'neueradmin@neonail.com']);
|
||||
echo "✅ Admin-User aktualisiert\n";
|
||||
|
||||
// 4. Zeige alle User
|
||||
echo "\n📋 Alle User:\n";
|
||||
$stmt = $pdo->query("SELECT id, name, email, is_admin FROM users");
|
||||
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
foreach ($users as $user) {
|
||||
$adminStatus = $user['is_admin'] ? '👑 Admin' : '👤 User';
|
||||
echo "- {$user['name']} ({$user['email']}) - {$adminStatus}\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Admin-Rolle erfolgreich aktiviert!\n";
|
||||
echo "🔗 Gehen Sie zu: https://neonail.vogt.de.com/admin/users\n";
|
||||
echo "📝 Bearbeiten Sie einen User und aktivieren Sie die 'Admin-Rechte gewähren' Checkbox\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "❌ Fehler: " . $e->getMessage() . "\n";
|
||||
}
|
||||
?>
|
||||
@@ -1,165 +0,0 @@
|
||||
<?php
|
||||
// Fix: Admin-Routes korrigieren
|
||||
echo "👑 Fix: Admin-Routes korrigieren\n";
|
||||
echo "==============================\n\n";
|
||||
|
||||
// 1. Routes-Datei analysieren
|
||||
echo "1. 📋 Routes-Datei analysieren:\n";
|
||||
$routesPath = 'routes/web.php';
|
||||
if (file_exists($routesPath)) {
|
||||
$content = file_get_contents($routesPath);
|
||||
|
||||
// Zeige alle Admin-bezogenen Zeilen
|
||||
$lines = explode("\n", $content);
|
||||
$adminLines = [];
|
||||
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'admin') !== false || strpos($line, 'Admin') !== false) {
|
||||
$adminLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
echo " 📄 Admin-bezogene Zeilen in routes/web.php:\n";
|
||||
foreach ($adminLines as $line) {
|
||||
echo " $line\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Routes-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 2. Route-Liste generieren
|
||||
echo "\n2. 🛣️ Route-Liste generieren:\n";
|
||||
try {
|
||||
// Laravel Bootstrap
|
||||
require_once 'vendor/autoload.php';
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// Route-Liste abrufen
|
||||
$routes = \Illuminate\Support\Facades\Route::getRoutes();
|
||||
|
||||
$adminRoutes = [];
|
||||
foreach ($routes as $route) {
|
||||
$uri = $route->uri();
|
||||
$methods = $route->methods();
|
||||
$name = $route->getName();
|
||||
|
||||
if (strpos($uri, 'admin') !== false || strpos($name, 'admin') !== false) {
|
||||
$adminRoutes[] = [
|
||||
'uri' => $uri,
|
||||
'methods' => $methods,
|
||||
'name' => $name
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($adminRoutes)) {
|
||||
echo " ⚠️ Keine Admin-Routes gefunden\n";
|
||||
} else {
|
||||
echo " ✅ Admin-Routes gefunden:\n";
|
||||
foreach ($adminRoutes as $route) {
|
||||
$methods = implode('|', $route['methods']);
|
||||
$name = $route['name'] ?: 'kein Name';
|
||||
echo " $methods $uri ($name)\n";
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Fehler beim Abrufen der Routes: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
// 3. Admin-Routes manuell prüfen
|
||||
echo "\n3. 🔍 Admin-Routes manuell prüfen:\n";
|
||||
$routesPath = 'routes/web.php';
|
||||
if (file_exists($routesPath)) {
|
||||
$content = file_get_contents($routesPath);
|
||||
|
||||
// Suche nach spezifischen Admin-Route-Patterns
|
||||
$adminPatterns = [
|
||||
'admin/dashboard' => 'Dashboard Route',
|
||||
'admin/users' => 'Users Index Route',
|
||||
'admin/users/create' => 'Users Create Route',
|
||||
'admin/users/{user}/edit' => 'Users Edit Route',
|
||||
'admin/statistics' => 'Statistics Route',
|
||||
'admin/users/{user}' => 'Users Show/Edit Route',
|
||||
'nail-polishes' => 'Nail Polishes Route'
|
||||
];
|
||||
|
||||
foreach ($adminPatterns as $pattern => $description) {
|
||||
if (strpos($content, $pattern) !== false) {
|
||||
echo " ✅ Pattern gefunden: $pattern ($description)\n";
|
||||
} else {
|
||||
echo " ❌ Pattern fehlt: $pattern ($description)\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Prüfe Route-Gruppen
|
||||
if (strpos($content, "Route::middleware(['admin'])->prefix('admin')") !== false) {
|
||||
echo " ✅ Admin Route-Gruppe gefunden\n";
|
||||
} else {
|
||||
echo " ❌ Admin Route-Gruppe nicht gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Routes-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 4. Cache leeren und Routes neu laden
|
||||
echo "\n4. 🧹 Cache leeren und Routes neu laden...\n";
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
// 5. Admin-User Status prüfen
|
||||
echo "\n5. 👑 Admin-User Status prüfen:\n";
|
||||
try {
|
||||
// Alle User mit Admin-Rechten auflisten
|
||||
$users = \App\Models\User::all();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$isAdmin = $user->isAdmin();
|
||||
$isAdminColumn = $user->is_admin;
|
||||
$email = $user->email;
|
||||
|
||||
if ($isAdmin || $isAdminColumn) {
|
||||
echo " 📧 $email:\n";
|
||||
echo " - is_admin Spalte: " . ($isAdminColumn ? 'Ja' : 'Nein') . "\n";
|
||||
echo " - isAdmin() Methode: " . ($isAdmin ? 'Ja' : 'Nein') . "\n";
|
||||
echo " - Admin-Status: " . ($isAdmin ? '✅ Admin' : '❌ Kein Admin') . "\n";
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Fehler beim Prüfen der User: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
// 6. Test-URLs generieren
|
||||
echo "\n6. 🔗 Test-URLs für Admin-Zugriffe:\n";
|
||||
$baseUrl = 'https://neonail.vogt.de.com';
|
||||
$adminUrls = [
|
||||
'/admin/dashboard' => 'Admin Dashboard',
|
||||
'/admin/users' => 'Admin Users',
|
||||
'/admin/users/create' => 'Admin Create User',
|
||||
'/admin/statistics' => 'Admin Statistics',
|
||||
'/nail-polishes' => 'Nail Polishes Management'
|
||||
];
|
||||
|
||||
foreach ($adminUrls as $url => $description) {
|
||||
echo " 🔗 $baseUrl$url ($description)\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Admin-Routes Analyse abgeschlossen!\n";
|
||||
echo "🔗 Testen Sie jetzt:\n";
|
||||
echo "1. Melden Sie sich als Admin an (oliver@vogt.de.com)\n";
|
||||
echo "2. Prüfen Sie ob Admin-Menü sichtbar ist\n";
|
||||
echo "3. Klicken Sie auf 'Admin' → 'Benutzer'\n";
|
||||
echo "4. Oder versuchen Sie direkt: $baseUrl/admin/users\n";
|
||||
echo "5. Falls 403 Fehler: Prüfen Sie ob User wirklich Admin ist\n";
|
||||
echo "\n📋 Falls Probleme bestehen:\n";
|
||||
echo "- Prüfen Sie Browser-Entwicklertools (F12) für Fehler\n";
|
||||
echo "- Schauen Sie in die Laravel-Logs: tail -f storage/logs/laravel.log\n";
|
||||
echo "- Teilen Sie eventuelle Fehlermeldungen mit\n";
|
||||
?>
|
||||
@@ -1,158 +0,0 @@
|
||||
<?php
|
||||
// Fix: Admin-Ansicht Problem
|
||||
echo "👑 Fix: Admin-Ansicht Problem\n";
|
||||
echo "============================\n\n";
|
||||
|
||||
// 1. Aktuelle User mit Admin-Rechten prüfen
|
||||
echo "1. 🔍 Aktuelle Admin-User prüfen:\n";
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Laravel Bootstrap
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// Datenbankverbindung herstellen
|
||||
$users = \App\Models\User::all();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$isAdmin = $user->isAdmin();
|
||||
$isAdminColumn = $user->is_admin;
|
||||
$email = $user->email;
|
||||
|
||||
echo " 📧 $email:\n";
|
||||
echo " - is_admin Spalte: " . ($isAdminColumn ? 'Ja' : 'Nein') . "\n";
|
||||
echo " - isAdmin() Methode: " . ($isAdmin ? 'Ja' : 'Nein') . "\n";
|
||||
echo " - Admin-Email Check: " . (in_array($email, ['admin@neonail.com', 'neueradmin@neonail.com']) ? 'Ja' : 'Nein') . "\n";
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Fehler beim Prüfen der User: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
// 2. User Model prüfen
|
||||
echo "2. 📋 User Model prüfen:\n";
|
||||
$userModelPath = 'app/Models/User.php';
|
||||
if (file_exists($userModelPath)) {
|
||||
$content = file_get_contents($userModelPath);
|
||||
|
||||
// Prüfe isAdmin Methode
|
||||
if (strpos($content, 'public function isAdmin()') !== false) {
|
||||
echo " ✅ isAdmin() Methode vorhanden\n";
|
||||
} else {
|
||||
echo " ❌ isAdmin() Methode fehlt\n";
|
||||
}
|
||||
|
||||
// Prüfe is_admin in fillable
|
||||
if (strpos($content, "'is_admin'") !== false) {
|
||||
echo " ✅ is_admin in \$fillable vorhanden\n";
|
||||
} else {
|
||||
echo " ❌ is_admin nicht in \$fillable\n";
|
||||
}
|
||||
|
||||
// Prüfe makeAdmin Methode
|
||||
if (strpos($content, 'public function makeAdmin()') !== false) {
|
||||
echo " ✅ makeAdmin() Methode vorhanden\n";
|
||||
} else {
|
||||
echo " ❌ makeAdmin() Methode fehlt\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ User Model nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 3. AdminMiddleware prüfen
|
||||
echo "3. 🛡️ AdminMiddleware prüfen:\n";
|
||||
$middlewarePath = 'app/Http/Middleware/AdminMiddleware.php';
|
||||
if (file_exists($middlewarePath)) {
|
||||
$content = file_get_contents($middlewarePath);
|
||||
|
||||
if (strpos($content, 'auth()->user()->isAdmin()') !== false) {
|
||||
echo " ✅ AdminMiddleware verwendet isAdmin() Methode\n";
|
||||
} else {
|
||||
echo " ❌ AdminMiddleware verwendet nicht isAdmin() Methode\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ AdminMiddleware nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 4. Routes prüfen
|
||||
echo "4. 🛣️ Admin-Routes prüfen:\n";
|
||||
$routesPath = 'routes/web.php';
|
||||
if (file_exists($routesPath)) {
|
||||
$content = file_get_contents($routesPath);
|
||||
|
||||
$adminRoutes = [
|
||||
'admin/users',
|
||||
'admin/dashboard',
|
||||
'nail-polishes'
|
||||
];
|
||||
|
||||
foreach ($adminRoutes as $route) {
|
||||
if (strpos($content, $route) !== false) {
|
||||
echo " ✅ Route gefunden: $route\n";
|
||||
} else {
|
||||
echo " ❌ Route fehlt: $route\n";
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Routes-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 5. Layout prüfen
|
||||
echo "5. 🎨 Layout prüfen:\n";
|
||||
$layoutPath = 'resources/views/layouts/app.blade.php';
|
||||
if (file_exists($layoutPath)) {
|
||||
$content = file_get_contents($layoutPath);
|
||||
|
||||
if (strpos($content, 'auth()->user()->isAdmin()') !== false) {
|
||||
echo " ✅ Layout verwendet isAdmin() für Admin-Menü\n";
|
||||
} else {
|
||||
echo " ❌ Layout verwendet nicht isAdmin() für Admin-Menü\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Layout-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 6. Cache leeren
|
||||
echo "6. 🧹 Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
// 7. Test-Admin erstellen
|
||||
echo "7. 👑 Test-Admin erstellen...\n";
|
||||
try {
|
||||
$testUser = \App\Models\User::where('email', 'testadmin@neonail.com')->first();
|
||||
|
||||
if (!$testUser) {
|
||||
$testUser = new \App\Models\User();
|
||||
$testUser->name = 'Test Admin';
|
||||
$testUser->email = 'testadmin@neonail.com';
|
||||
$testUser->password = bcrypt('password123');
|
||||
$testUser->is_admin = true;
|
||||
$testUser->save();
|
||||
echo " ✅ Test-Admin erstellt: testadmin@neonail.com\n";
|
||||
} else {
|
||||
$testUser->is_admin = true;
|
||||
$testUser->save();
|
||||
echo " ✅ Test-Admin aktualisiert: testadmin@neonail.com\n";
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Fehler beim Erstellen des Test-Admins: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Admin-Ansicht Problem Analyse abgeschlossen!\n";
|
||||
echo "🔗 Testen Sie jetzt:\n";
|
||||
echo "1. Melden Sie sich als neuer Admin an\n";
|
||||
echo "2. Prüfen Sie ob Admin-Menü sichtbar ist\n";
|
||||
echo "3. Versuchen Sie auf /admin/users zuzugreifen\n";
|
||||
echo "4. Falls Problem besteht, teilen Sie die Ausgabe mit\n";
|
||||
?>
|
||||
@@ -1,50 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔧 Fix: Alle HTTP 405 Method Not Allowed Fehler"
|
||||
echo "=============================================="
|
||||
|
||||
# 1. Laravel Cache leeren
|
||||
echo "1. 🧹 Laravel Cache leeren..."
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen"
|
||||
|
||||
# 2. Bootstrap Cache leeren
|
||||
echo "2. 🗂️ Bootstrap Cache leeren..."
|
||||
rm -f bootstrap/cache/*.php 2>/dev/null || echo "⚠️ bootstrap/cache/*.php nicht gefunden"
|
||||
|
||||
# 3. Route-Tests ausführen
|
||||
echo "3. 🧪 Route-Tests ausführen..."
|
||||
echo " - Create-Route Test:"
|
||||
php test-route-fix.php 2>/dev/null || echo "⚠️ test-route-fix.php übersprungen"
|
||||
|
||||
echo " - Remove-Route Test:"
|
||||
php test-remove-fix.php 2>/dev/null || echo "⚠️ test-remove-fix.php übersprungen"
|
||||
|
||||
# 4. Debug-Modus aktivieren
|
||||
echo "4. 🐛 Debug-Modus aktivieren..."
|
||||
if [ -f .env ]; then
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
sed -i 's/APP_ENV=production/APP_ENV=local/' .env
|
||||
echo " ✅ Debug-Modus aktiviert"
|
||||
else
|
||||
echo " ❌ .env Datei nicht gefunden"
|
||||
fi
|
||||
|
||||
# 5. Route-Liste anzeigen
|
||||
echo "5. 📋 Route-Liste prüfen..."
|
||||
php artisan route:list | grep -E "(create|remove|store)" 2>/dev/null || echo "⚠️ route:list übersprungen"
|
||||
|
||||
echo ""
|
||||
echo "✅ Alle 405-Fehler behoben!"
|
||||
echo ""
|
||||
echo "🔗 Testen Sie jetzt:"
|
||||
echo "1. Neuen Lack erstellen: https://neonail.vogt.de.com/create-nail-polish"
|
||||
echo "2. Lack entfernen: https://neonail.vogt.de.com/my-collection"
|
||||
echo "3. Admin-User verwalten: https://neonail.vogt.de.com/admin/users"
|
||||
echo ""
|
||||
echo "📝 Falls Probleme bestehen:"
|
||||
echo "- Prüfen Sie die Browser-Entwicklertools (F12)"
|
||||
echo "- Schauen Sie in storage/logs/laravel.log"
|
||||
echo "- Führen Sie php artisan route:list aus"
|
||||
@@ -1,97 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔒 Alle Formulare für HTTPS reparieren"
|
||||
echo "====================================="
|
||||
|
||||
# 1. Laravel Cache komplett leeren
|
||||
echo "🧹 Leere Laravel Cache..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen"
|
||||
|
||||
# 2. .env für HTTPS erzwingen
|
||||
echo "📝 Erzwinge HTTPS in .env..."
|
||||
sed -i 's|APP_URL=http://|APP_URL=https://|' .env
|
||||
sed -i 's|APP_URL=https://192.168.30.81|APP_URL=https://neonail.vogt.de.com|' .env
|
||||
|
||||
# 3. Session-Konfiguration für HTTPS
|
||||
echo "🔐 Konfiguriere Session für HTTPS..."
|
||||
cat > config/session.php << 'EOF'
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
'driver' => env('SESSION_DRIVER', 'file'),
|
||||
'lifetime' => env('SESSION_LIFETIME', 120),
|
||||
'expire_on_close' => false,
|
||||
'encrypt' => false,
|
||||
'files' => storage_path('framework/sessions'),
|
||||
'connection' => env('SESSION_CONNECTION'),
|
||||
'table' => 'sessions',
|
||||
'store' => env('SESSION_STORE'),
|
||||
'lottery' => [2, 100],
|
||||
'cookie' => env(
|
||||
'SESSION_COOKIE',
|
||||
Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
|
||||
),
|
||||
'path' => '/',
|
||||
'domain' => env('SESSION_DOMAIN'),
|
||||
'secure' => true,
|
||||
'http_only' => true,
|
||||
'same_site' => 'lax',
|
||||
];
|
||||
EOF
|
||||
|
||||
# 4. AppServiceProvider für HTTPS erzwingen
|
||||
echo "⚙️ Konfiguriere AppServiceProvider für HTTPS..."
|
||||
cat > app/Providers/AppServiceProvider.php << 'EOF'
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
// Erzwinge HTTPS in Produktion
|
||||
if (config('app.env') === 'production') {
|
||||
URL::forceScheme('https');
|
||||
}
|
||||
|
||||
// Blade-Directive für sichere URLs
|
||||
Blade::directive('secureUrl', function ($expression) {
|
||||
return "<?php echo secure_url($expression); ?>";
|
||||
});
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# 5. Apache neu laden
|
||||
echo "🔄 Lade Apache neu..."
|
||||
systemctl reload apache2
|
||||
|
||||
# 6. Test
|
||||
echo "🧪 Teste HTTPS-Konfiguration..."
|
||||
curl -I https://neonail.vogt.de.com
|
||||
|
||||
echo ""
|
||||
echo "✅ Alle Formulare für HTTPS repariert!"
|
||||
echo "📋 Testen Sie: https://neonail.vogt.de.com"
|
||||
echo ""
|
||||
echo "📋 Falls Warnung bleibt:"
|
||||
echo "1. Safari-Cache leeren (Cmd+Shift+R)"
|
||||
echo "2. Private-Fenster testen"
|
||||
echo "3. Safari-Einstellungen: Entwickler > Leere Caches"
|
||||
echo "4. Safari-Einstellungen: Datenschutz > Website-Daten verwalten"
|
||||
echo "5. Safari komplett neu starten"
|
||||
@@ -1,189 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🛡️ Fix: Alle Safari Sicherheitswarnungen"
|
||||
echo "======================================="
|
||||
|
||||
# 1. Alle Formulare mit HTTPS-URLs beheben
|
||||
echo "1. 🔒 Alle Formulare mit HTTPS beheben..."
|
||||
|
||||
# Login-Formular
|
||||
if [ -f resources/views/auth/login.blade.php ]; then
|
||||
sed -i 's|action="{{ route('\''login'\'') }}"|action="https://neonail.vogt.de.com/login"|' resources/views/auth/login.blade.php
|
||||
echo " ✅ Login-Formular behoben"
|
||||
fi
|
||||
|
||||
# Create Nail Polish Formular
|
||||
if [ -f resources/views/user-nail-polishes/create.blade.php ]; then
|
||||
sed -i 's|action="{{ route('\''user-nail-polishes.store'\'') }}"|action="https://neonail.vogt.de.com/create-nail-polish"|' resources/views/user-nail-polishes/create.blade.php
|
||||
echo " ✅ Create Nail Polish Formular behoben"
|
||||
fi
|
||||
|
||||
# Remove Nail Polish Formular
|
||||
if [ -f resources/views/user-nail-polishes/index.blade.php ]; then
|
||||
sed -i 's|action="https://neonail.vogt.de.com/user-nail-polishes/|action="https://neonail.vogt.de.com/remove-from-collection/|' resources/views/user-nail-polishes/index.blade.php
|
||||
echo " ✅ Remove Nail Polish Formular behoben"
|
||||
fi
|
||||
|
||||
# Admin Nail Polish Delete Formular
|
||||
if [ -f resources/views/nail-polishes/index.blade.php ]; then
|
||||
sed -i 's|action="{{ route('\''nail-polishes.destroy'\'', $nailPolish) }}"|action="https://neonail.vogt.de.com/nail-polishes/{{ $nailPolish->id }}"|' resources/views/nail-polishes/index.blade.php
|
||||
echo " ✅ Admin Nail Polish Delete Formular behoben"
|
||||
fi
|
||||
|
||||
# Admin User Create Formular
|
||||
if [ -f resources/views/admin/users/create.blade.php ]; then
|
||||
sed -i 's|action="{{ route('\''admin.users.store'\'') }}"|action="https://neonail.vogt.de.com/admin/users"|' resources/views/admin/users/create.blade.php
|
||||
echo " ✅ Admin User Create Formular behoben"
|
||||
fi
|
||||
|
||||
# Admin User Edit Formular
|
||||
if [ -f resources/views/admin/users/edit.blade.php ]; then
|
||||
sed -i 's|action="{{ route('\''admin.users.update'\'', $user) }}"|action="https://neonail.vogt.de.com/admin/users/{{ $user->id }}"|' resources/views/admin/users/edit.blade.php
|
||||
echo " ✅ Admin User Edit Formular behoben"
|
||||
fi
|
||||
|
||||
# Admin User Delete Formular
|
||||
if [ -f resources/views/admin/users/index.blade.php ]; then
|
||||
sed -i 's|action="{{ route('\''admin.users.destroy'\'', $user) }}"|action="https://neonail.vogt.de.com/admin/users/{{ $user->id }}"|' resources/views/admin/users/index.blade.php
|
||||
echo " ✅ Admin User Delete Formular behoben"
|
||||
fi
|
||||
|
||||
# 2. .env HTTPS-Einstellungen
|
||||
echo "2. 🔒 .env HTTPS-Einstellungen..."
|
||||
if [ -f .env ]; then
|
||||
sed -i 's|APP_URL=.*|APP_URL=https://neonail.vogt.de.com|' .env
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
sed -i 's/APP_ENV=production/APP_ENV=local/' .env
|
||||
|
||||
# HTTPS-spezifische Einstellungen
|
||||
grep -q "FORCE_HTTPS=true" .env || echo "FORCE_HTTPS=true" >> .env
|
||||
grep -q "SECURE_COOKIES=true" .env || echo "SECURE_COOKIES=true" >> .env
|
||||
grep -q "SESSION_SECURE_COOKIE=true" .env || echo "SESSION_SECURE_COOKIE=true" >> .env
|
||||
grep -q "SESSION_SAME_SITE=lax" .env || echo "SESSION_SAME_SITE=lax" >> .env
|
||||
grep -q "SESSION_HTTP_ONLY=true" .env || echo "SESSION_HTTP_ONLY=true" >> .env
|
||||
|
||||
echo " ✅ .env HTTPS-Einstellungen aktualisiert"
|
||||
else
|
||||
echo " ❌ .env Datei nicht gefunden"
|
||||
fi
|
||||
|
||||
# 3. Session-Konfiguration
|
||||
echo "3. 🍪 Session-Konfiguration..."
|
||||
if [ -f config/session.php ]; then
|
||||
sed -i "s/'secure' => false/'secure' => true/" config/session.php
|
||||
sed -i "s/'http_only' => false/'http_only' => true/" config/session.php
|
||||
echo " ✅ Session-Konfiguration aktualisiert"
|
||||
else
|
||||
echo " ❌ config/session.php nicht gefunden"
|
||||
fi
|
||||
|
||||
# 4. CSRF-Konfiguration
|
||||
echo "4. 🔐 CSRF-Konfiguration..."
|
||||
if [ -f config/csrf.php ]; then
|
||||
sed -i "s/'secure' => false/'secure' => true/" config/csrf.php
|
||||
echo " ✅ CSRF-Konfiguration aktualisiert"
|
||||
else
|
||||
echo " ❌ config/csrf.php nicht gefunden"
|
||||
fi
|
||||
|
||||
# 5. Minimale .htaccess mit HTTPS-Force
|
||||
echo "5. 🌐 .htaccess HTTPS-Force..."
|
||||
cat > public/.htaccess << 'EOF'
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
|
||||
# Force HTTPS
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Handle Authorization Header
|
||||
RewriteCond %{HTTP:Authorization} .
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
# Redirect Trailing Slashes If Not A Folder...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} (.+)/$
|
||||
RewriteRule ^ %1 [L,R=301]
|
||||
|
||||
# Send Requests To Front Controller...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
|
||||
# Protect sensitive files
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "*.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
EOF
|
||||
|
||||
echo " ✅ .htaccess HTTPS-Force erstellt"
|
||||
|
||||
# 6. Laravel Cache leeren
|
||||
echo "6. 🧹 Laravel Cache leeren..."
|
||||
php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"
|
||||
php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"
|
||||
|
||||
# 7. Test-Script erstellen
|
||||
echo "7. 🧪 Test-Script erstellen..."
|
||||
cat > test-all-forms.php << 'EOF'
|
||||
<?php
|
||||
// Test aller Formulare auf HTTPS
|
||||
echo "🔒 Test aller Formulare auf HTTPS\n";
|
||||
echo "===============================\n\n";
|
||||
|
||||
$forms = [
|
||||
'resources/views/auth/login.blade.php' => 'Login-Formular',
|
||||
'resources/views/user-nail-polishes/create.blade.php' => 'Create Nail Polish',
|
||||
'resources/views/user-nail-polishes/index.blade.php' => 'Remove Nail Polish',
|
||||
'resources/views/nail-polishes/index.blade.php' => 'Admin Delete Nail Polish',
|
||||
'resources/views/admin/users/create.blade.php' => 'Admin Create User',
|
||||
'resources/views/admin/users/edit.blade.php' => 'Admin Edit User',
|
||||
'resources/views/admin/users/index.blade.php' => 'Admin Delete User'
|
||||
];
|
||||
|
||||
foreach ($forms as $file => $description) {
|
||||
if (file_exists($file)) {
|
||||
$content = file_get_contents($file);
|
||||
if (strpos($content, 'action="https://neonail.vogt.de.com') !== false) {
|
||||
echo " ✅ $description: HTTPS-URL gefunden\n";
|
||||
} else {
|
||||
echo " ❌ $description: Keine HTTPS-URL gefunden\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ $description: Datei nicht gefunden\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n✅ Alle Formulare getestet!\n";
|
||||
echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com\n";
|
||||
?>
|
||||
EOF
|
||||
|
||||
echo " ✅ Test-Script erstellt"
|
||||
|
||||
echo ""
|
||||
echo "✅ Alle Safari Sicherheitswarnungen behoben!"
|
||||
echo ""
|
||||
echo "🔗 Testen Sie jetzt:"
|
||||
echo "1. Login: https://neonail.vogt.de.com/login"
|
||||
echo "2. Admin-Panel: https://neonail.vogt.de.com/admin/users"
|
||||
echo "3. Lack erstellen: https://neonail.vogt.de.com/create-nail-polish"
|
||||
echo ""
|
||||
echo "📝 Falls Warnungen bestehen:"
|
||||
echo "- Führen Sie php test-all-forms.php aus"
|
||||
echo "- Leeren Sie Browser-Cache"
|
||||
echo "- Prüfen Sie Browser-Entwicklertools (F12)"
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🌐 Apache DocumentRoot korrigieren"
|
||||
echo "================================="
|
||||
|
||||
# 1. Standard-Site deaktivieren
|
||||
echo "🔧 Deaktiviere Standard-Site..."
|
||||
a2dissite 000-default.conf 2>/dev/null || echo "⚠️ Standard-Site bereits deaktiviert"
|
||||
|
||||
# 2. NeoNail-Site neu erstellen
|
||||
echo "📝 Erstelle NeoNail-Site neu..."
|
||||
cat > /etc/apache2/sites-available/neonail.conf << 'EOF'
|
||||
<VirtualHost *:80>
|
||||
ServerName 192.168.30.81
|
||||
DocumentRoot /var/www/html/public
|
||||
|
||||
<Directory /var/www/html/public>
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
Options Indexes FollowSymLinks
|
||||
</Directory>
|
||||
|
||||
# Sicherheit für sensible Dateien
|
||||
<Directory /var/www/html>
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
</Directory>
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/neonail_error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/neonail_access.log combined
|
||||
</VirtualHost>
|
||||
EOF
|
||||
|
||||
# 3. NeoNail-Site aktivieren
|
||||
echo "✅ Aktiviere NeoNail-Site..."
|
||||
a2ensite neonail.conf
|
||||
|
||||
# 4. Apache-Konfiguration testen
|
||||
echo "🔍 Teste Apache-Konfiguration..."
|
||||
apache2ctl configtest
|
||||
|
||||
# 5. Apache neu laden
|
||||
echo "🔄 Lade Apache neu..."
|
||||
systemctl reload apache2
|
||||
|
||||
# 6. Status prüfen
|
||||
echo "📊 Apache-Status..."
|
||||
systemctl status apache2 --no-pager -l
|
||||
|
||||
# 7. Test
|
||||
echo "🧪 Teste Anwendung..."
|
||||
curl -I http://192.168.30.81
|
||||
|
||||
echo ""
|
||||
echo "✅ Apache DocumentRoot korrigiert!"
|
||||
echo "📋 Testen Sie: http://192.168.30.81"
|
||||
echo ""
|
||||
echo "📋 Falls es nicht funktioniert:"
|
||||
echo "1. Apache-Logs: tail -f /var/log/apache2/neonail_error.log"
|
||||
echo "2. DocumentRoot prüfen: apache2ctl -S"
|
||||
@@ -1,103 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔧 Fix: Apache mod_headers aktivieren"
|
||||
echo "===================================="
|
||||
|
||||
# 1. Prüfe verfügbare Apache-Module
|
||||
echo "1. 🔍 Verfügbare Apache-Module prüfen..."
|
||||
apache2ctl -M 2>/dev/null | grep -E "(headers|rewrite)" || echo " ⚠️ apache2ctl nicht verfügbar"
|
||||
|
||||
# 2. Aktiviere mod_headers
|
||||
echo "2. 🔧 mod_headers aktivieren..."
|
||||
a2enmod headers 2>/dev/null || echo " ⚠️ a2enmod headers fehlgeschlagen"
|
||||
|
||||
# 3. Aktiviere mod_rewrite (falls nicht aktiviert)
|
||||
echo "3. 🔧 mod_rewrite aktivieren..."
|
||||
a2enmod rewrite 2>/dev/null || echo " ⚠️ a2enmod rewrite fehlgeschlagen"
|
||||
|
||||
# 4. Apache neu laden
|
||||
echo "4. 🔄 Apache neu laden..."
|
||||
systemctl reload apache2 2>/dev/null || service apache2 reload 2>/dev/null || echo " ⚠️ Apache reload fehlgeschlagen"
|
||||
|
||||
# 5. Prüfe .htaccess Syntax
|
||||
echo "5. 🔍 .htaccess Syntax prüfen..."
|
||||
if [ -f public/.htaccess ]; then
|
||||
echo " 📋 public/.htaccess gefunden"
|
||||
echo " 📄 Header-Befehle in .htaccess:"
|
||||
grep -n "Header" public/.htaccess || echo " ⚠️ Keine Header-Befehle gefunden"
|
||||
else
|
||||
echo " ❌ public/.htaccess nicht gefunden"
|
||||
fi
|
||||
|
||||
# 6. Alternative .htaccess ohne Header erstellen
|
||||
echo "6. 🔧 Alternative .htaccess erstellen..."
|
||||
cat > public/.htaccess.simple << 'EOF'
|
||||
<IfModule mod_rewrite.c>
|
||||
<IfModule mod_negotiation.c>
|
||||
Options -MultiViews -Indexes
|
||||
</IfModule>
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
# Force HTTPS
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Handle Authorization Header
|
||||
RewriteCond %{HTTP:Authorization} .
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
# Redirect Trailing Slashes If Not A Folder...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} (.+)/$
|
||||
RewriteRule ^ %1 [L,R=301]
|
||||
|
||||
# Send Requests To Front Controller...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
|
||||
# Protect sensitive files
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "*.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
EOF
|
||||
|
||||
echo " ✅ Alternative .htaccess erstellt"
|
||||
|
||||
# 7. Backup und ersetze .htaccess
|
||||
echo "7. 🔄 .htaccess ersetzen..."
|
||||
if [ -f public/.htaccess ]; then
|
||||
cp public/.htaccess public/.htaccess.backup
|
||||
echo " ✅ Backup erstellt: public/.htaccess.backup"
|
||||
fi
|
||||
|
||||
cp public/.htaccess.simple public/.htaccess
|
||||
echo " ✅ .htaccess ersetzt"
|
||||
|
||||
# 8. Test Apache-Konfiguration
|
||||
echo "8. 🧪 Apache-Konfiguration testen..."
|
||||
apache2ctl -t 2>/dev/null && echo " ✅ Apache-Konfiguration OK" || echo " ❌ Apache-Konfiguration fehlerhaft"
|
||||
|
||||
echo ""
|
||||
echo "✅ Apache mod_headers Fix abgeschlossen!"
|
||||
echo ""
|
||||
echo "🔗 Testen Sie jetzt:"
|
||||
echo "1. https://neonail.vogt.de.com"
|
||||
echo "2. Admin-Panel: https://neonail.vogt.de.com/admin/users"
|
||||
echo ""
|
||||
echo "📝 Falls Problem besteht:"
|
||||
echo "- Prüfen Sie: apache2ctl -M | grep headers"
|
||||
echo "- Schauen Sie in: /var/log/apache2/error.log"
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔧 Fix: AppServiceProvider Syntax-Fehler"
|
||||
echo "======================================="
|
||||
|
||||
# 1. Syntax prüfen
|
||||
echo "1. 🔍 PHP Syntax prüfen..."
|
||||
php -l app/Providers/AppServiceProvider.php
|
||||
|
||||
# 2. Laravel Cache leeren
|
||||
echo "2. 🧹 Laravel Cache leeren..."
|
||||
php artisan cache:clear
|
||||
php artisan config:clear
|
||||
php artisan route:clear
|
||||
php artisan view:clear
|
||||
|
||||
# 3. HTTPS-Sicherheit testen
|
||||
echo "3. 🧪 HTTPS-Sicherheit testen..."
|
||||
php test-https-security.php
|
||||
|
||||
echo ""
|
||||
echo "✅ AppServiceProvider Syntax-Fehler behoben!"
|
||||
echo ""
|
||||
echo "🔗 Testen Sie jetzt:"
|
||||
echo "1. Admin-Panel: https://neonail.vogt.de.com/admin/users"
|
||||
echo "2. Lack löschen im Admin-Panel"
|
||||
echo "3. User bearbeiten/löschen"
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# NeoNail DB - Black Screen Fix Script
|
||||
# Behebt schwarzen Bildschirm in Production
|
||||
|
||||
echo "🖥️ NeoNail DB - Black Screen Fix"
|
||||
echo "================================="
|
||||
|
||||
# Prüfe, ob wir im richtigen Verzeichnis sind
|
||||
if [ ! -f "artisan" ]; then
|
||||
echo "❌ Fehler: artisan Datei nicht gefunden. Bitte führen Sie das Script im Laravel-Root-Verzeichnis aus."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔍 Schritt 1: Temporär Debug aktivieren..."
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
php artisan config:clear
|
||||
|
||||
echo "🔍 Schritt 2: Logs leeren..."
|
||||
> storage/logs/laravel.log
|
||||
|
||||
echo "🔍 Schritt 3: Cache komplett leeren..."
|
||||
php artisan config:clear
|
||||
php artisan route:clear
|
||||
php artisan view:clear
|
||||
php artisan cache:clear
|
||||
php artisan optimize:clear
|
||||
|
||||
echo "🔍 Schritt 4: Composer Autoload neu generieren..."
|
||||
composer dump-autoload --optimize
|
||||
|
||||
echo "🔍 Schritt 5: Berechtigungen prüfen..."
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
chmod 664 database.sqlite
|
||||
chmod 644 .env
|
||||
|
||||
echo "🔍 Schritt 6: Datenbank-Verbindung testen..."
|
||||
php artisan tinker --execute="echo 'DB Test: '; try { DB::connection()->getPdo(); echo 'OK'; } catch(Exception \$e) { echo 'FEHLER: ' . \$e->getMessage(); }"
|
||||
|
||||
echo "🔍 Schritt 7: Routen testen..."
|
||||
php artisan route:list | head -10
|
||||
|
||||
echo "🔍 Schritt 8: Storage-Link prüfen..."
|
||||
if [ ! -L "public/storage" ]; then
|
||||
echo "📎 Storage-Link erstellen..."
|
||||
php artisan storage:link
|
||||
else
|
||||
echo "✅ Storage-Link bereits vorhanden"
|
||||
fi
|
||||
|
||||
echo "✅ Black Screen Fix abgeschlossen!"
|
||||
echo ""
|
||||
echo "🎯 Nächste Schritte:"
|
||||
echo "1. Seite aufrufen (sollte jetzt Fehlermeldung zeigen)"
|
||||
echo "2. Fehlermeldung notieren"
|
||||
echo "3. Fehler beheben"
|
||||
echo "4. APP_DEBUG=false setzen"
|
||||
echo ""
|
||||
echo "📋 Logs prüfen mit: tail -f storage/logs/laravel.log"
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔒 HTTPS-Konfiguration für NeoNail DB"
|
||||
echo "===================================="
|
||||
|
||||
# 1. .env für HTTPS aktualisieren
|
||||
echo "📝 Aktualisiere .env für HTTPS..."
|
||||
sed -i 's|APP_URL=http://192.168.30.81|APP_URL=https://neonail.vogt.de.com|' .env
|
||||
sed -i 's|APP_URL=http://neonail.vogt.de.com|APP_URL=https://neonail.vogt.de.com|' .env
|
||||
|
||||
# 2. Laravel Cache leeren
|
||||
echo "🧹 Leere Laravel Cache..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
|
||||
# 3. Trusted Proxies konfigurieren (falls hinter Proxy)
|
||||
echo "🔧 Konfiguriere Trusted Proxies..."
|
||||
cat > config/trusted-proxies.php << 'EOF'
|
||||
<?php
|
||||
|
||||
return [
|
||||
'proxies' => [
|
||||
'192.168.30.81',
|
||||
'neonail.vogt.de.com',
|
||||
],
|
||||
'headers' => [
|
||||
'X-Forwarded-For' => 'X_FORWARDED_FOR',
|
||||
'X-Forwarded-Host' => 'X_FORWARDED_HOST',
|
||||
'X-Forwarded-Proto' => 'X_FORWARDED_PROTO',
|
||||
],
|
||||
];
|
||||
EOF
|
||||
|
||||
# 4. Session-Konfiguration für HTTPS
|
||||
echo "🔐 Konfiguriere Sessions für HTTPS..."
|
||||
sed -i 's|SESSION_SECURE_COOKIE=false|SESSION_SECURE_COOKIE=true|' .env 2>/dev/null || echo "⚠️ SESSION_SECURE_COOKIE nicht gefunden"
|
||||
|
||||
# 5. Test
|
||||
echo "🧪 Teste HTTPS-Konfiguration..."
|
||||
curl -I https://neonail.vogt.de.com
|
||||
|
||||
echo ""
|
||||
echo "✅ HTTPS-Konfiguration abgeschlossen!"
|
||||
echo "📋 Testen Sie: https://neonail.vogt.de.com"
|
||||
echo ""
|
||||
echo "📋 Falls Probleme auftreten:"
|
||||
echo "1. Browser-Cache leeren"
|
||||
echo "2. Laravel-Logs prüfen: tail -f storage/logs/laravel.log"
|
||||
@@ -1,70 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔒 HTTPS-Formular-Sicherheit beheben"
|
||||
echo "==================================="
|
||||
|
||||
# 1. .env für HTTPS konfigurieren
|
||||
echo "📝 Konfiguriere .env für HTTPS..."
|
||||
sed -i 's|APP_URL=http://|APP_URL=https://|' .env
|
||||
sed -i 's|APP_URL=https://192.168.30.81|APP_URL=https://neonail.vogt.de.com|' .env
|
||||
|
||||
# 2. Session-Konfiguration für HTTPS
|
||||
echo "🔐 Konfiguriere Sessions für HTTPS..."
|
||||
cat >> .env << 'EOF'
|
||||
|
||||
# HTTPS-Konfiguration
|
||||
SESSION_SECURE_COOKIE=true
|
||||
SESSION_SAME_SITE=lax
|
||||
EOF
|
||||
|
||||
# 3. Laravel Cache leeren
|
||||
echo "🧹 Leere Laravel Cache..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen"
|
||||
|
||||
# 4. CSRF-Token für HTTPS konfigurieren
|
||||
echo "🛡️ Konfiguriere CSRF für HTTPS..."
|
||||
cat > config/csrf.php << 'EOF'
|
||||
<?php
|
||||
|
||||
return [
|
||||
'cookie' => [
|
||||
'secure' => true,
|
||||
'same_site' => 'lax',
|
||||
],
|
||||
];
|
||||
EOF
|
||||
|
||||
# 5. Trusted Proxies konfigurieren
|
||||
echo "🌐 Konfiguriere Trusted Proxies..."
|
||||
cat > config/trusted-proxies.php << 'EOF'
|
||||
<?php
|
||||
|
||||
return [
|
||||
'proxies' => [
|
||||
'192.168.30.81',
|
||||
'neonail.vogt.de.com',
|
||||
'127.0.0.1',
|
||||
'::1',
|
||||
],
|
||||
'headers' => [
|
||||
'X-Forwarded-For' => 'X_FORWARDED_FOR',
|
||||
'X-Forwarded-Host' => 'X_FORWARDED_HOST',
|
||||
'X-Forwarded-Proto' => 'X_FORWARDED_PROTO',
|
||||
],
|
||||
];
|
||||
EOF
|
||||
|
||||
# 6. Test
|
||||
echo "🧪 Teste HTTPS-Konfiguration..."
|
||||
curl -I https://neonail.vogt.de.com
|
||||
|
||||
echo ""
|
||||
echo "✅ HTTPS-Formular-Sicherheit behoben!"
|
||||
echo "📋 Testen Sie: https://neonail.vogt.de.com"
|
||||
echo ""
|
||||
echo "📋 Falls Warnungen bleiben:"
|
||||
echo "1. Browser-Cache leeren (Strg+F5)"
|
||||
echo "2. Private/Inkognito-Modus testen"
|
||||
echo "3. HTTPS-Zertifikat prüfen"
|
||||
@@ -1,55 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🖼️ Bild-Anzeige reparieren"
|
||||
echo "========================="
|
||||
|
||||
# 1. Storage Link prüfen und neu erstellen
|
||||
echo "🔗 Prüfe Storage Link..."
|
||||
if [ -L "public/storage" ]; then
|
||||
echo "✅ Storage Link existiert"
|
||||
ls -la public/storage
|
||||
else
|
||||
echo "❌ Storage Link fehlt - erstelle neu..."
|
||||
rm -f public/storage
|
||||
php artisan storage:link
|
||||
fi
|
||||
|
||||
# 2. Storage-Verzeichnis-Berechtigungen
|
||||
echo "🔐 Setze Storage-Berechtigungen..."
|
||||
chmod -R 777 storage/
|
||||
chmod -R 755 public/storage/
|
||||
|
||||
# 3. Bilder-Verzeichnis erstellen
|
||||
echo "📁 Erstelle Bilder-Verzeichnis..."
|
||||
mkdir -p storage/app/public/nail_polishes
|
||||
chmod -R 777 storage/app/public/nail_polishes
|
||||
|
||||
# 4. Test-Bild erstellen (falls keine Bilder vorhanden)
|
||||
echo "🧪 Erstelle Test-Bild..."
|
||||
if [ ! -f "storage/app/public/nail_polishes/test.jpg" ]; then
|
||||
# Einfaches Test-Bild erstellen
|
||||
echo "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==" | base64 -d > storage/app/public/nail_polishes/test.jpg
|
||||
echo "✅ Test-Bild erstellt"
|
||||
fi
|
||||
|
||||
# 5. Laravel Cache leeren
|
||||
echo "🧹 Leere Laravel Cache..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
|
||||
# 6. Test-URL prüfen
|
||||
echo "🧪 Teste Bild-URL..."
|
||||
curl -I https://neonail.vogt.de.com/storage/nail_polishes/test.jpg 2>/dev/null || echo "⚠️ Test-URL nicht erreichbar"
|
||||
|
||||
# 7. Datenbank-Bilder prüfen
|
||||
echo "🗄️ Prüfe Datenbank-Bilder..."
|
||||
sqlite3 database.sqlite "SELECT id, name, image_path FROM nail_polishes WHERE image_path IS NOT NULL;" 2>/dev/null || echo "⚠️ Keine Bilder in Datenbank gefunden"
|
||||
|
||||
echo ""
|
||||
echo "✅ Bild-Anzeige repariert!"
|
||||
echo "📋 Testen Sie: https://neonail.vogt.de.com/storage/nail_polishes/test.jpg"
|
||||
echo ""
|
||||
echo "📋 Falls Bilder immer noch nicht angezeigt werden:"
|
||||
echo "1. Browser-Cache leeren (Strg+F5)"
|
||||
echo "2. Private-Fenster testen"
|
||||
echo "3. Bild-URL direkt aufrufen"
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
// Fallback für Bild-Upload ohne GD Extension
|
||||
// Fügen Sie dies temporär in UserNailPolishController.php ein
|
||||
|
||||
// Ersetzen Sie den Bildverarbeitungs-Code in der store() Methode:
|
||||
|
||||
/*
|
||||
// Original-Code (mit GD):
|
||||
if ($request->hasFile('image') && $request->file('image')->isValid()) {
|
||||
$image = $request->file('image');
|
||||
$filename = 'nail_polish_' . time() . '_' . uniqid() . '.jpg';
|
||||
$path = 'nail_polishes/' . $filename;
|
||||
|
||||
$manager = new ImageManager(new Driver());
|
||||
$img = $manager->read($image);
|
||||
$img->resize(400, 400, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
});
|
||||
|
||||
$imageData = $img->toJpeg(80)->toString();
|
||||
Storage::disk('public')->put($path, $imageData);
|
||||
$nailPolish->image_path = $path;
|
||||
}
|
||||
*/
|
||||
|
||||
// Fallback-Code (ohne GD):
|
||||
if ($request->hasFile('image') && $request->file('image')->isValid()) {
|
||||
$image = $request->file('image');
|
||||
|
||||
// Prüfe Dateigröße (max 2MB)
|
||||
if ($image->getSize() > 2 * 1024 * 1024) {
|
||||
return back()->with('error', 'Das Bild darf maximal 2MB groß sein.')->withInput();
|
||||
}
|
||||
|
||||
// Prüfe Dateityp
|
||||
$allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'];
|
||||
if (!in_array($image->getMimeType(), $allowedTypes)) {
|
||||
return back()->with('error', 'Nur JPG, PNG und GIF Dateien sind erlaubt.')->withInput();
|
||||
}
|
||||
|
||||
// Speichere Original-Bild ohne Verarbeitung
|
||||
$filename = 'nail_polish_' . time() . '_' . uniqid() . '.' . $image->getClientOriginalExtension();
|
||||
$path = 'nail_polishes/' . $filename;
|
||||
|
||||
Storage::disk('public')->put($path, file_get_contents($image));
|
||||
$nailPolish->image_path = $path;
|
||||
}
|
||||
?>
|
||||
@@ -1,282 +0,0 @@
|
||||
<?php
|
||||
// Fix: Finales Bild-Upload-System
|
||||
echo "📸 Fix: Finales Bild-Upload-System\n";
|
||||
echo "==================================\n\n";
|
||||
|
||||
// 1. Controller mit vereinfachtem Upload erstellen (ohne Intervention Image)
|
||||
echo "1. 🔧 Controller mit vereinfachtem Upload erstellen...\n";
|
||||
|
||||
$controllerContent = '<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\NailPolish;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class UserNailPolishController extends Controller
|
||||
{
|
||||
/**
|
||||
* Zeigt die Sammlung des aktuellen Benutzers an
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$search = $request->get("search");
|
||||
|
||||
$query = $user->nailPolishes();
|
||||
|
||||
if ($search) {
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where("name", "like", "%{$search}%")
|
||||
->orWhere("number", "like", "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
$nailPolishes = $query->orderBy("name")->paginate(12);
|
||||
|
||||
return view("user-nail-polishes.index", compact("nailPolishes", "search"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt alle verfügbaren Lacke an, die der User noch nicht hat
|
||||
*/
|
||||
public function available(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$search = $request->get("search");
|
||||
|
||||
$query = NailPolish::whereNotIn("id", $user->nailPolishes()->pluck("nail_polishes.id"));
|
||||
|
||||
if ($search) {
|
||||
$query->search($search);
|
||||
}
|
||||
|
||||
$nailPolishes = $query->orderBy("name")->paginate(12);
|
||||
|
||||
return view("user-nail-polishes.available", compact("nailPolishes", "search"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fügt einen Lack zur Sammlung des Users hinzu
|
||||
*/
|
||||
public function add(NailPolish $nailPolish)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Prüfe, ob der Lack bereits in der Sammlung ist
|
||||
if ($user->nailPolishes()->where("nail_polish_id", $nailPolish->id)->exists()) {
|
||||
return back()->with("warning", "Dieser Lack ist bereits in Ihrer Sammlung!");
|
||||
}
|
||||
|
||||
$user->nailPolishes()->attach($nailPolish->id);
|
||||
|
||||
return back()->with("success", "Lack \"{$nailPolish->name}\" wurde zu Ihrer Sammlung hinzugefügt!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Entfernt einen Lack aus der Sammlung des Users
|
||||
*/
|
||||
public function remove(NailPolish $nailPolish)
|
||||
{
|
||||
try {
|
||||
$user = Auth::user();
|
||||
|
||||
// Prüfe, ob der Lack in der Sammlung ist
|
||||
if (!$user->nailPolishes()->where("nail_polish_id", $nailPolish->id)->exists()) {
|
||||
return back()->with("warning", "Dieser Lack ist nicht in Ihrer Sammlung!");
|
||||
}
|
||||
|
||||
$user->nailPolishes()->detach($nailPolish->id);
|
||||
|
||||
return back()->with("success", "Lack \"{$nailPolish->name}\" wurde aus Ihrer Sammlung entfernt!");
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("Fehler beim Entfernen des Lackes: " . $e->getMessage());
|
||||
return back()->with("error", "Fehler beim Entfernen des Lackes. Bitte versuchen Sie es erneut.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt das Formular zum Erstellen eines neuen Lackes
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view("user-nail-polishes.create");
|
||||
}
|
||||
|
||||
/**
|
||||
* Speichert einen neuen Lack (wird automatisch zum Hauptkatalog hinzugefügt)
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
"name" => "required|string|max:255",
|
||||
"number" => "required|string|max:50",
|
||||
"image" => "nullable|image|max:10240", // Max 10MB
|
||||
], [
|
||||
"name.required" => "Der Name des Lackes ist erforderlich.",
|
||||
"number.required" => "Die Nummer des Lackes ist erforderlich.",
|
||||
"image.image" => "Die Datei muss ein Bild sein.",
|
||||
"image.max" => "Das Bild darf maximal 10MB groß sein.",
|
||||
]);
|
||||
|
||||
try {
|
||||
$nailPolish = new NailPolish();
|
||||
$nailPolish->name = trim($request->name);
|
||||
$nailPolish->number = trim($request->number);
|
||||
|
||||
// Vereinfachte Bildverarbeitung ohne Intervention Image
|
||||
if ($request->hasFile("image") && $request->file("image")->isValid()) {
|
||||
$image = $request->file("image");
|
||||
|
||||
// Erstelle einen eindeutigen Dateinamen
|
||||
$filename = "nail_polish_" . time() . "_" . uniqid() . "." . $image->getClientOriginalExtension();
|
||||
$path = "nail_polishes/" . $filename;
|
||||
|
||||
// Speichere das Bild direkt ohne Verarbeitung
|
||||
Storage::disk("public")->putFileAs("nail_polishes", $image, $filename);
|
||||
$nailPolish->image_path = $path;
|
||||
|
||||
\Log::info("Bild erfolgreich gespeichert: " . $path);
|
||||
}
|
||||
|
||||
$nailPolish->save();
|
||||
|
||||
// Füge den Lack automatisch zur Sammlung des Users hinzu
|
||||
$user = Auth::user();
|
||||
$user->nailPolishes()->attach($nailPolish->id);
|
||||
|
||||
return redirect()->route("user-nail-polishes.index")
|
||||
->with("success", "Lack \"{$nailPolish->name}\" wurde erfolgreich erstellt und zu Ihrer Sammlung hinzugefügt!");
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("Fehler beim Erstellen des Lackes: " . $e->getMessage());
|
||||
return back()->with("error", "Fehler beim Erstellen des Lackes: " . $e->getMessage())
|
||||
->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt die Sammlung eines bestimmten Users (für Admin)
|
||||
*/
|
||||
public function showUserCollection(User $user)
|
||||
{
|
||||
$nailPolishes = $user->nailPolishes()->orderBy("name")->paginate(12);
|
||||
|
||||
return view("user-nail-polishes.show-user", compact("user", "nailPolishes"));
|
||||
}
|
||||
}';
|
||||
|
||||
file_put_contents('app/Http/Controllers/UserNailPolishController.php', $controllerContent);
|
||||
echo " ✅ Controller mit vereinfachtem Upload erstellt\n";
|
||||
|
||||
// 2. Storage-Verzeichnisse erstellen
|
||||
echo "2. 📁 Storage-Verzeichnisse erstellen...\n";
|
||||
$directories = [
|
||||
'storage/app/public',
|
||||
'storage/app/public/nail_polishes'
|
||||
];
|
||||
|
||||
foreach ($directories as $dir) {
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0755, true);
|
||||
echo " ✅ Verzeichnis erstellt: $dir\n";
|
||||
} else {
|
||||
echo " ℹ️ Verzeichnis existiert bereits: $dir\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Berechtigungen setzen
|
||||
echo "3. 🔐 Berechtigungen setzen...\n";
|
||||
system('chmod -R 755 storage/');
|
||||
system('chown -R www-data:www-data storage/ 2>/dev/null || echo " ⚠️ chown fehlgeschlagen"');
|
||||
echo " ✅ Berechtigungen gesetzt\n";
|
||||
|
||||
// 4. Storage Link erstellen
|
||||
echo "4. 🔗 Storage Link erstellen...\n";
|
||||
if (file_exists('public/storage')) {
|
||||
if (is_dir('public/storage')) {
|
||||
system('rm -rf public/storage');
|
||||
}
|
||||
}
|
||||
system('ln -sf ../storage/app/public public/storage');
|
||||
echo " ✅ Storage Link erstellt\n";
|
||||
|
||||
// 5. Laravel Cache leeren
|
||||
echo "5. 🧹 Laravel Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
// 6. Test-Bild erstellen
|
||||
echo "6. 🖼️ Test-Bild erstellen...\n";
|
||||
$testImagePath = 'storage/app/public/nail_polishes/test.jpg';
|
||||
if (extension_loaded('gd')) {
|
||||
$image = imagecreate(100, 100);
|
||||
$bgColor = imagecolorallocate($image, 255, 255, 255);
|
||||
$textColor = imagecolorallocate($image, 0, 0, 0);
|
||||
imagestring($image, 5, 10, 40, 'TEST', $textColor);
|
||||
|
||||
if (imagejpeg($image, $testImagePath, 80)) {
|
||||
echo " ✅ Test-Bild erstellt: $testImagePath\n";
|
||||
} else {
|
||||
echo " ❌ Test-Bild erstellen fehlgeschlagen\n";
|
||||
}
|
||||
|
||||
imagedestroy($image);
|
||||
} else {
|
||||
echo " ❌ GD Extension nicht verfügbar\n";
|
||||
}
|
||||
|
||||
// 7. Upload-Limits in .htaccess prüfen
|
||||
echo "7. 📏 Upload-Limits prüfen...\n";
|
||||
$htaccessPath = 'public/.htaccess';
|
||||
if (file_exists($htaccessPath)) {
|
||||
$htaccessContent = file_get_contents($htaccessPath);
|
||||
|
||||
$requiredSettings = [
|
||||
'upload_max_filesize 10M',
|
||||
'post_max_size 10M',
|
||||
'max_file_uploads 20',
|
||||
'memory_limit 256M'
|
||||
];
|
||||
|
||||
$missingSettings = [];
|
||||
foreach ($requiredSettings as $setting) {
|
||||
if (strpos($htaccessContent, $setting) === false) {
|
||||
$missingSettings[] = $setting;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($missingSettings)) {
|
||||
echo " ✅ Alle Upload-Limits in .htaccess vorhanden\n";
|
||||
} else {
|
||||
echo " ⚠️ Fehlende Upload-Limits: " . implode(', ', $missingSettings) . "\n";
|
||||
|
||||
// Füge fehlende Settings hinzu
|
||||
$uploadSettings = "\n# Upload-Limits für Bild-Upload\n";
|
||||
foreach ($missingSettings as $setting) {
|
||||
$uploadSettings .= "php_value " . $setting . "\n";
|
||||
}
|
||||
|
||||
$htaccessContent .= $uploadSettings;
|
||||
file_put_contents($htaccessPath, $htaccessContent);
|
||||
echo " ✅ Upload-Limits zu .htaccess hinzugefügt\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ .htaccess nicht gefunden\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Finales Bild-Upload-System erstellt!\n";
|
||||
echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/create-nail-polish\n";
|
||||
echo "📝 Das System speichert Bilder jetzt direkt ohne Verarbeitung\n";
|
||||
echo "📋 Falls Upload immer noch fehlschlägt:\n";
|
||||
echo "- Prüfen Sie die Laravel-Logs: tail -f storage/logs/laravel.log\n";
|
||||
echo "- Testen Sie mit einem kleinen Bild (< 1MB)\n";
|
||||
echo "- Prüfen Sie Browser-Entwicklertools (F12) für Netzwerk-Fehler\n";
|
||||
?>
|
||||
@@ -1,222 +0,0 @@
|
||||
<?php
|
||||
// Fix: Vereinfachtes Bild-Upload-System
|
||||
echo "📸 Fix: Vereinfachtes Bild-Upload-System\n";
|
||||
echo "======================================\n\n";
|
||||
|
||||
// 1. Controller mit vereinfachtem Upload erstellen
|
||||
echo "1. 🔧 Controller mit vereinfachtem Upload erstellen...\n";
|
||||
|
||||
$controllerContent = '<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\NailPolish;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class UserNailPolishController extends Controller
|
||||
{
|
||||
/**
|
||||
* Zeigt die Sammlung des aktuellen Benutzers an
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$search = $request->get("search");
|
||||
|
||||
$query = $user->nailPolishes();
|
||||
|
||||
if ($search) {
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where("name", "like", "%{$search}%")
|
||||
->orWhere("number", "like", "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
$nailPolishes = $query->orderBy("name")->paginate(12);
|
||||
|
||||
return view("user-nail-polishes.index", compact("nailPolishes", "search"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt alle verfügbaren Lacke an, die der User noch nicht hat
|
||||
*/
|
||||
public function available(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$search = $request->get("search");
|
||||
|
||||
$query = NailPolish::whereNotIn("id", $user->nailPolishes()->pluck("nail_polishes.id"));
|
||||
|
||||
if ($search) {
|
||||
$query->search($search);
|
||||
}
|
||||
|
||||
$nailPolishes = $query->orderBy("name")->paginate(12);
|
||||
|
||||
return view("user-nail-polishes.available", compact("nailPolishes", "search"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fügt einen Lack zur Sammlung des Users hinzu
|
||||
*/
|
||||
public function add(NailPolish $nailPolish)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Prüfe, ob der Lack bereits in der Sammlung ist
|
||||
if ($user->nailPolishes()->where("nail_polish_id", $nailPolish->id)->exists()) {
|
||||
return back()->with("warning", "Dieser Lack ist bereits in Ihrer Sammlung!");
|
||||
}
|
||||
|
||||
$user->nailPolishes()->attach($nailPolish->id);
|
||||
|
||||
return back()->with("success", "Lack \"{$nailPolish->name}\" wurde zu Ihrer Sammlung hinzugefügt!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Entfernt einen Lack aus der Sammlung des Users
|
||||
*/
|
||||
public function remove(NailPolish $nailPolish)
|
||||
{
|
||||
try {
|
||||
$user = Auth::user();
|
||||
|
||||
// Prüfe, ob der Lack in der Sammlung ist
|
||||
if (!$user->nailPolishes()->where("nail_polish_id", $nailPolish->id)->exists()) {
|
||||
return back()->with("warning", "Dieser Lack ist nicht in Ihrer Sammlung!");
|
||||
}
|
||||
|
||||
$user->nailPolishes()->detach($nailPolish->id);
|
||||
|
||||
return back()->with("success", "Lack \"{$nailPolish->name}\" wurde aus Ihrer Sammlung entfernt!");
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("Fehler beim Entfernen des Lackes: " . $e->getMessage());
|
||||
return back()->with("error", "Fehler beim Entfernen des Lackes. Bitte versuchen Sie es erneut.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt das Formular zum Erstellen eines neuen Lackes
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view("user-nail-polishes.create");
|
||||
}
|
||||
|
||||
/**
|
||||
* Speichert einen neuen Lack (wird automatisch zum Hauptkatalog hinzugefügt)
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
"name" => "required|string|max:255",
|
||||
"number" => "required|string|max:50",
|
||||
"image" => "nullable|image|max:10240", // Max 10MB
|
||||
], [
|
||||
"name.required" => "Der Name des Lackes ist erforderlich.",
|
||||
"number.required" => "Die Nummer des Lackes ist erforderlich.",
|
||||
"image.image" => "Die Datei muss ein Bild sein.",
|
||||
"image.max" => "Das Bild darf maximal 10MB groß sein.",
|
||||
]);
|
||||
|
||||
try {
|
||||
$nailPolish = new NailPolish();
|
||||
$nailPolish->name = trim($request->name);
|
||||
$nailPolish->number = trim($request->number);
|
||||
|
||||
// Vereinfachte Bildverarbeitung ohne Intervention Image
|
||||
if ($request->hasFile("image") && $request->file("image")->isValid()) {
|
||||
$image = $request->file("image");
|
||||
|
||||
// Erstelle einen eindeutigen Dateinamen
|
||||
$filename = "nail_polish_" . time() . "_" . uniqid() . "." . $image->getClientOriginalExtension();
|
||||
$path = "nail_polishes/" . $filename;
|
||||
|
||||
// Speichere das Bild direkt ohne Verarbeitung
|
||||
Storage::disk("public")->putFileAs("nail_polishes", $image, $filename);
|
||||
$nailPolish->image_path = $path;
|
||||
|
||||
\Log::info("Bild erfolgreich gespeichert: " . $path);
|
||||
}
|
||||
|
||||
$nailPolish->save();
|
||||
|
||||
// Füge den Lack automatisch zur Sammlung des Users hinzu
|
||||
$user = Auth::user();
|
||||
$user->nailPolishes()->attach($nailPolish->id);
|
||||
|
||||
return redirect()->route("user-nail-polishes.index")
|
||||
->with("success", "Lack \"{$nailPolish->name}\" wurde erfolgreich erstellt und zu Ihrer Sammlung hinzugefügt!");
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("Fehler beim Erstellen des Lackes: " . $e->getMessage());
|
||||
return back()->with("error", "Fehler beim Erstellen des Lackes: " . $e->getMessage())
|
||||
->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt die Sammlung eines bestimmten Users (für Admin)
|
||||
*/
|
||||
public function showUserCollection(User $user)
|
||||
{
|
||||
$nailPolishes = $user->nailPolishes()->orderBy("name")->paginate(12);
|
||||
|
||||
return view("user-nail-polishes.show-user", compact("user", "nailPolishes"));
|
||||
}
|
||||
}';
|
||||
|
||||
file_put_contents('app/Http/Controllers/UserNailPolishController.php', $controllerContent);
|
||||
echo " ✅ Controller mit vereinfachtem Upload erstellt\n";
|
||||
|
||||
// 2. Storage-Verzeichnisse erstellen
|
||||
echo "2. 📁 Storage-Verzeichnisse erstellen...\n";
|
||||
$directories = [
|
||||
'storage/app/public',
|
||||
'storage/app/public/nail_polishes'
|
||||
];
|
||||
|
||||
foreach ($directories as $dir) {
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0755, true);
|
||||
echo " ✅ Verzeichnis erstellt: $dir\n";
|
||||
} else {
|
||||
echo " ℹ️ Verzeichnis existiert bereits: $dir\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Berechtigungen setzen
|
||||
echo "3. 🔐 Berechtigungen setzen...\n";
|
||||
system('chmod -R 755 storage/');
|
||||
system('chown -R www-data:www-data storage/ 2>/dev/null || echo " ⚠️ chown fehlgeschlagen"');
|
||||
echo " ✅ Berechtigungen gesetzt\n";
|
||||
|
||||
// 4. Storage Link erstellen
|
||||
echo "4. 🔗 Storage Link erstellen...\n";
|
||||
if (file_exists('public/storage')) {
|
||||
if (is_dir('public/storage')) {
|
||||
system('rm -rf public/storage');
|
||||
}
|
||||
}
|
||||
system('ln -sf ../storage/app/public public/storage');
|
||||
echo " ✅ Storage Link erstellt\n";
|
||||
|
||||
// 5. Laravel Cache leeren
|
||||
echo "5. 🧹 Laravel Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
echo "\n✅ Vereinfachtes Bild-Upload-System erstellt!\n";
|
||||
echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/create-nail-polish\n";
|
||||
echo "📝 Das System speichert Bilder jetzt direkt ohne Verarbeitung\n";
|
||||
echo "📋 Falls Upload immer noch fehlschlägt:\n";
|
||||
echo "- Führen Sie php debug-image-upload.php aus\n";
|
||||
echo "- Prüfen Sie die Laravel-Logs\n";
|
||||
echo "- Testen Sie mit einem kleinen Bild (< 1MB)\n";
|
||||
?>
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
// Robuste Bild-URL-Lösung für NeoNail DB
|
||||
// Fügen Sie diese Helper-Funktion hinzu
|
||||
|
||||
// In app/Helpers/ImageHelper.php erstellen:
|
||||
namespace App\Helpers;
|
||||
|
||||
class ImageHelper
|
||||
{
|
||||
public static function getImageUrl($imagePath)
|
||||
{
|
||||
if (!$imagePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Prüfe ob das Bild existiert
|
||||
if (!\Storage::disk('public')->exists($imagePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Erstelle die URL
|
||||
$url = \Storage::disk('public')->url($imagePath);
|
||||
|
||||
// Stelle sicher, dass HTTPS verwendet wird
|
||||
if (strpos($url, 'http://') === 0) {
|
||||
$url = str_replace('http://', 'https://', $url);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public static function getImageUrlOrPlaceholder($imagePath, $size = '400x400')
|
||||
{
|
||||
$url = self::getImageUrl($imagePath);
|
||||
|
||||
if ($url) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
// Fallback zu einem Placeholder-Bild
|
||||
return "https://via.placeholder.com/{$size}/cccccc/666666?text=Kein+Bild";
|
||||
}
|
||||
}
|
||||
|
||||
// In der View verwenden:
|
||||
// {{ \App\Helpers\ImageHelper::getImageUrlOrPlaceholder($nailPolish->image_path) }}
|
||||
|
||||
// Oder als Blade-Directive in AppServiceProvider.php registrieren:
|
||||
/*
|
||||
public function boot()
|
||||
{
|
||||
Blade::directive('nailPolishImage', function ($expression) {
|
||||
return "<?php echo \App\Helpers\ImageHelper::getImageUrlOrPlaceholder($expression); ?>";
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
// Dann in der View:
|
||||
// @nailPolishImage($nailPolish->image_path)
|
||||
?>
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔧 Laravel Setup Reparieren"
|
||||
echo "==========================="
|
||||
|
||||
# 1. Vendor-Ordner prüfen
|
||||
echo "📦 Prüfe vendor/ Ordner..."
|
||||
if [ ! -d "vendor" ]; then
|
||||
echo "❌ vendor/ Ordner nicht gefunden!"
|
||||
echo "📋 Bitte laden Sie den vendor/ Ordner hoch oder führen Sie composer install aus"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. Composer autoload neu generieren
|
||||
echo "🔄 Generiere Composer autoload neu..."
|
||||
if command -v composer &> /dev/null; then
|
||||
composer dump-autoload --optimize
|
||||
elif [ -f "composer.phar" ]; then
|
||||
php composer.phar dump-autoload --optimize
|
||||
else
|
||||
echo "⚠️ Composer nicht verfügbar, überspringe autoload"
|
||||
fi
|
||||
|
||||
# 3. Laravel Cache leeren
|
||||
echo "🗑️ Leere Laravel Cache..."
|
||||
php artisan config:clear
|
||||
php artisan route:clear
|
||||
php artisan view:clear
|
||||
php artisan cache:clear
|
||||
|
||||
# 4. Laravel neu initialisieren
|
||||
echo "⚙️ Initialisiere Laravel neu..."
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
|
||||
# 5. Berechtigungen setzen
|
||||
echo "🔐 Setze Berechtigungen..."
|
||||
chmod -R 755 vendor/
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
|
||||
# 6. .env prüfen
|
||||
echo "📝 Prüfe .env Datei..."
|
||||
if [ ! -f ".env" ]; then
|
||||
echo "❌ .env Datei nicht gefunden!"
|
||||
echo "📋 Kopieren Sie env-production-example.txt zu .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ Laravel Setup repariert!"
|
||||
echo "📋 Testen Sie jetzt: php artisan --version"
|
||||
@@ -1,110 +0,0 @@
|
||||
<?php
|
||||
// Fix: Logout-Problem final beheben
|
||||
echo "🔧 Fix: Logout-Problem final beheben\n";
|
||||
echo "===================================\n\n";
|
||||
|
||||
// 1. Layout korrigieren
|
||||
echo "1. 🎨 Layout korrigieren...\n";
|
||||
$layoutPath = 'resources/views/layouts/app.blade.php';
|
||||
if (file_exists($layoutPath)) {
|
||||
$content = file_get_contents($layoutPath);
|
||||
|
||||
// Ersetze hardcodierte Logout-URL
|
||||
$oldAction = 'action="https://neonail.vogt.de.com/logout"';
|
||||
$newAction = 'action="{{ route("logout") }}"';
|
||||
|
||||
if (strpos($content, $oldAction) !== false) {
|
||||
$content = str_replace($oldAction, $newAction, $content);
|
||||
file_put_contents($layoutPath, $content);
|
||||
echo " ✅ Hardcodierte URL ersetzt: $oldAction → $newAction\n";
|
||||
} else {
|
||||
echo " ℹ️ Keine hardcodierte URL gefunden\n";
|
||||
}
|
||||
|
||||
// Prüfe ob die Korrektur erfolgreich war
|
||||
if (strpos($content, '{{ route("logout") }}') !== false) {
|
||||
echo " ✅ Laravel Route wird verwendet\n";
|
||||
} else {
|
||||
echo " ❌ Laravel Route wird nicht verwendet\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Layout-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 2. Cache leeren
|
||||
echo "\n2. 🧹 Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
// 3. Layout nochmal prüfen
|
||||
echo "\n3. 🎨 Layout final prüfen...\n";
|
||||
if (file_exists($layoutPath)) {
|
||||
$content = file_get_contents($layoutPath);
|
||||
|
||||
// Suche nach Logout-Form
|
||||
if (strpos($content, 'logout-form') !== false) {
|
||||
echo " ✅ Logout-Form gefunden\n";
|
||||
|
||||
// Zeige Logout-Form Details
|
||||
$lines = explode("\n", $content);
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
echo " 📋 Zeile " . ($lineNumber + 1) . ": " . trim($line) . "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Logout-Form nicht gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Layout-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 4. JavaScript prüfen
|
||||
echo "\n4. 🔧 JavaScript prüfen...\n";
|
||||
if (file_exists($layoutPath)) {
|
||||
$content = file_get_contents($layoutPath);
|
||||
|
||||
// Suche nach onclick Event
|
||||
if (strpos($content, 'onclick="event.preventDefault(); document.getElementById("logout-form").submit();"') !== false) {
|
||||
echo " ✅ JavaScript Event Handler gefunden\n";
|
||||
} else {
|
||||
echo " ❌ JavaScript Event Handler nicht gefunden\n";
|
||||
}
|
||||
|
||||
// Suche nach Bootstrap JS
|
||||
if (strpos($content, 'bootstrap.bundle.min.js') !== false) {
|
||||
echo " ✅ Bootstrap JS geladen\n";
|
||||
} else {
|
||||
echo " ❌ Bootstrap JS nicht geladen\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Layout-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 5. Test-Anleitung
|
||||
echo "\n5. 🧪 Test-Anleitung...\n";
|
||||
echo " 📋 1. Öffnen Sie: https://neonail.vogt.de.com\n";
|
||||
echo " 📋 2. Melden Sie sich an\n";
|
||||
echo " 📋 3. Klicken Sie auf Ihren Benutzernamen (oben rechts)\n";
|
||||
echo " 📋 4. Wählen Sie 'Abmelden' aus dem Dropdown\n";
|
||||
echo " 📋 5. Sie sollten zur Login-Seite weitergeleitet werden\n";
|
||||
echo "\n 🔍 Falls Problem besteht:\n";
|
||||
echo " 📋 - Öffnen Sie Browser-Entwicklertools (F12)\n";
|
||||
echo " 📋 - Gehen Sie zu Console-Tab\n";
|
||||
echo " 📋 - Klicken Sie auf Abmelden\n";
|
||||
echo " 📋 - Schauen Sie nach JavaScript-Fehlern\n";
|
||||
echo " 📋 - Gehen Sie zu Network-Tab\n";
|
||||
echo " 📋 - Schauen Sie welche URL aufgerufen wird\n";
|
||||
|
||||
echo "\n✅ Logout-Problem final behoben!\n";
|
||||
echo "🔗 Testen Sie jetzt das Logout und teilen Sie mit:\n";
|
||||
echo "1. Funktioniert das Logout jetzt?\n";
|
||||
echo "2. Werden Sie zur Login-Seite weitergeleitet?\n";
|
||||
echo "3. Falls nicht: Welche Fehlermeldungen sehen Sie?\n";
|
||||
?>
|
||||
@@ -1,194 +0,0 @@
|
||||
<?php
|
||||
// Fix: Logout-Route Cache-Problem beheben
|
||||
echo "🔧 Fix: Logout-Route Cache-Problem beheben\n";
|
||||
echo "=========================================\n\n";
|
||||
|
||||
// 1. Alle Cache-Dateien löschen
|
||||
echo "1. 🗑️ Alle Cache-Dateien löschen...\n";
|
||||
$cacheFiles = [
|
||||
'bootstrap/cache/packages.php',
|
||||
'bootstrap/cache/services.php',
|
||||
'bootstrap/cache/routes.php',
|
||||
'bootstrap/cache/config.php',
|
||||
'bootstrap/cache/application.php'
|
||||
];
|
||||
|
||||
foreach ($cacheFiles as $cacheFile) {
|
||||
if (file_exists($cacheFile)) {
|
||||
unlink($cacheFile);
|
||||
echo " ✅ Gelöscht: $cacheFile\n";
|
||||
} else {
|
||||
echo " ℹ️ Nicht vorhanden: $cacheFile\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Composer autoload neu generieren
|
||||
echo "\n2. 🔄 Composer autoload neu generieren...\n";
|
||||
system('composer dump-autoload 2>/dev/null || echo " ⚠️ composer dump-autoload übersprungen"');
|
||||
echo " ✅ Autoload neu generiert\n";
|
||||
|
||||
// 3. Laravel Cache komplett leeren
|
||||
echo "\n3. 🧹 Laravel Cache komplett leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
system('php artisan optimize:clear 2>/dev/null || echo " ⚠️ optimize:clear übersprungen"');
|
||||
echo " ✅ Laravel Cache geleert\n";
|
||||
|
||||
// 4. Routes-Datei prüfen und korrigieren
|
||||
echo "\n4. 🛣️ Routes-Datei prüfen...\n";
|
||||
$routesPath = 'routes/web.php';
|
||||
if (file_exists($routesPath)) {
|
||||
$content = file_get_contents($routesPath);
|
||||
|
||||
// Zeige alle Logout-bezogenen Zeilen
|
||||
$lines = explode("\n", $content);
|
||||
$logoutLines = [];
|
||||
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
$logoutLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($logoutLines)) {
|
||||
echo " ✅ Logout-Routes gefunden:\n";
|
||||
foreach ($logoutLines as $line) {
|
||||
echo " 📋 $line\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Keine Logout-Routes gefunden\n";
|
||||
}
|
||||
|
||||
// Prüfe ob die Route korrekt ist
|
||||
if (strpos($content, "Route::post('/logout', [LoginController::class, 'logout'])->name('logout')->middleware('auth');") !== false) {
|
||||
echo " ✅ Logout-Route ist korrekt definiert\n";
|
||||
} else {
|
||||
echo " ❌ Logout-Route ist nicht korrekt definiert\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Routes-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 5. LoginController prüfen
|
||||
echo "\n5. 🔐 LoginController prüfen...\n";
|
||||
$controllerPath = 'app/Http/Controllers/Auth/LoginController.php';
|
||||
if (file_exists($controllerPath)) {
|
||||
$content = file_get_contents($controllerPath);
|
||||
|
||||
if (strpos($content, 'public function logout') !== false) {
|
||||
echo " ✅ Logout-Methode vorhanden\n";
|
||||
|
||||
// Zeige Logout-Methode
|
||||
$lines = explode("\n", $content);
|
||||
$inLogoutMethod = false;
|
||||
$methodLines = [];
|
||||
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'public function logout') !== false) {
|
||||
$inLogoutMethod = true;
|
||||
$methodLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
} elseif ($inLogoutMethod && strpos($line, 'public function') !== false) {
|
||||
$inLogoutMethod = false;
|
||||
} elseif ($inLogoutMethod) {
|
||||
$methodLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
echo " 📋 Logout-Methode:\n";
|
||||
foreach ($methodLines as $line) {
|
||||
echo " $line\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Logout-Methode nicht gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ LoginController nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 6. Route-Liste neu generieren
|
||||
echo "\n6. 🛣️ Route-Liste neu generieren...\n";
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Laravel Bootstrap
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// Route-Liste abrufen
|
||||
$routes = \Illuminate\Support\Facades\Route::getRoutes();
|
||||
|
||||
$logoutRoutes = [];
|
||||
foreach ($routes as $route) {
|
||||
$uri = $route->uri();
|
||||
$methods = $route->methods();
|
||||
$name = $route->getName();
|
||||
|
||||
if (strpos($uri, 'logout') !== false || strpos($name, 'logout') !== false) {
|
||||
$logoutRoutes[] = [
|
||||
'uri' => $uri,
|
||||
'methods' => $methods,
|
||||
'name' => $name
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($logoutRoutes)) {
|
||||
echo " ❌ Keine Logout-Routes in Laravel registriert\n";
|
||||
} else {
|
||||
echo " ✅ Logout-Routes in Laravel gefunden:\n";
|
||||
foreach ($logoutRoutes as $route) {
|
||||
$methods = implode('|', $route['methods']);
|
||||
$name = $route['name'] ?: 'kein Name';
|
||||
echo " 📋 $methods $uri ($name)\n";
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ❌ Fehler beim Abrufen der Routes: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
// 7. Test-Logout-Form erstellen
|
||||
echo "\n7. 🧪 Test-Logout-Form erstellen...\n";
|
||||
$testForm = '<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Logout Test</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Logout Test</h1>
|
||||
<form action="{{ route("logout") }}" method="POST">
|
||||
@csrf
|
||||
<button type="submit">Abmelden</button>
|
||||
</form>
|
||||
<p>Route: {{ route("logout") }}</p>
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
file_put_contents('public/logout-test.blade.php', $testForm);
|
||||
echo " ✅ Test-Form erstellt: public/logout-test.blade.php\n";
|
||||
|
||||
// 8. Apache neu laden (falls möglich)
|
||||
echo "\n8. 🔄 Apache neu laden...\n";
|
||||
system('systemctl reload apache2 2>/dev/null || echo " ⚠️ Apache reload übersprungen"');
|
||||
echo " ✅ Apache neu geladen\n";
|
||||
|
||||
echo "\n✅ Logout-Route Fix abgeschlossen!\n";
|
||||
echo "🔗 Testen Sie jetzt:\n";
|
||||
echo "1. Klicken Sie auf Ihren Benutzernamen (oben rechts)\n";
|
||||
echo "2. Wählen Sie 'Abmelden' aus dem Dropdown\n";
|
||||
echo "3. Falls das nicht funktioniert:\n";
|
||||
echo " - Öffnen Sie Browser-Entwicklertools (F12)\n";
|
||||
echo " - Gehen Sie zu Network-Tab\n";
|
||||
echo " - Klicken Sie auf Abmelden\n";
|
||||
echo " - Schauen Sie welche URL aufgerufen wird\n";
|
||||
echo "\n📋 Falls Problem besteht:\n";
|
||||
echo "- Teilen Sie die Network-Tab Ausgabe mit\n";
|
||||
echo "- Schauen Sie in die Laravel-Logs: tail -f storage/logs/laravel.log\n";
|
||||
echo "- Testen Sie direkt: https://neonail.vogt.de.com/logout\n";
|
||||
?>
|
||||
@@ -1,147 +0,0 @@
|
||||
<?php
|
||||
// Fix: Logout-Route Cache-Problem beheben (vereinfacht)
|
||||
echo "🔧 Fix: Logout-Route Cache-Problem beheben (vereinfacht)\n";
|
||||
echo "======================================================\n\n";
|
||||
|
||||
// 1. Alle Cache-Dateien löschen
|
||||
echo "1. 🗑️ Alle Cache-Dateien löschen...\n";
|
||||
$cacheFiles = [
|
||||
'bootstrap/cache/packages.php',
|
||||
'bootstrap/cache/services.php',
|
||||
'bootstrap/cache/routes.php',
|
||||
'bootstrap/cache/config.php',
|
||||
'bootstrap/cache/application.php'
|
||||
];
|
||||
|
||||
foreach ($cacheFiles as $cacheFile) {
|
||||
if (file_exists($cacheFile)) {
|
||||
unlink($cacheFile);
|
||||
echo " ✅ Gelöscht: $cacheFile\n";
|
||||
} else {
|
||||
echo " ℹ️ Nicht vorhanden: $cacheFile\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Laravel Cache leeren (ohne Composer)
|
||||
echo "\n2. 🧹 Laravel Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
echo " ✅ Laravel Cache geleert\n";
|
||||
|
||||
// 3. Routes-Datei prüfen
|
||||
echo "\n3. 🛣️ Routes-Datei prüfen...\n";
|
||||
$routesPath = 'routes/web.php';
|
||||
if (file_exists($routesPath)) {
|
||||
$content = file_get_contents($routesPath);
|
||||
|
||||
// Zeige alle Logout-bezogenen Zeilen
|
||||
$lines = explode("\n", $content);
|
||||
$logoutLines = [];
|
||||
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
$logoutLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($logoutLines)) {
|
||||
echo " ✅ Logout-Routes gefunden:\n";
|
||||
foreach ($logoutLines as $line) {
|
||||
echo " 📋 $line\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Keine Logout-Routes gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Routes-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 4. LoginController prüfen
|
||||
echo "\n4. 🔐 LoginController prüfen...\n";
|
||||
$controllerPath = 'app/Http/Controllers/Auth/LoginController.php';
|
||||
if (file_exists($controllerPath)) {
|
||||
$content = file_get_contents($controllerPath);
|
||||
|
||||
if (strpos($content, 'public function logout') !== false) {
|
||||
echo " ✅ Logout-Methode vorhanden\n";
|
||||
|
||||
// Zeige Logout-Methode
|
||||
$lines = explode("\n", $content);
|
||||
$inLogoutMethod = false;
|
||||
$methodLines = [];
|
||||
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'public function logout') !== false) {
|
||||
$inLogoutMethod = true;
|
||||
$methodLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
} elseif ($inLogoutMethod && strpos($line, 'public function') !== false) {
|
||||
$inLogoutMethod = false;
|
||||
} elseif ($inLogoutMethod) {
|
||||
$methodLines[] = ($lineNumber + 1) . ": " . trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
echo " 📋 Logout-Methode:\n";
|
||||
foreach ($methodLines as $line) {
|
||||
echo " $line\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Logout-Methode nicht gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ LoginController nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 5. Layout prüfen
|
||||
echo "\n5. 🎨 Layout prüfen...\n";
|
||||
$layoutPath = 'resources/views/layouts/app.blade.php';
|
||||
if (file_exists($layoutPath)) {
|
||||
$content = file_get_contents($layoutPath);
|
||||
|
||||
// Suche nach Logout-Form
|
||||
if (strpos($content, 'logout-form') !== false) {
|
||||
echo " ✅ Logout-Form gefunden\n";
|
||||
|
||||
// Zeige Logout-Form Details
|
||||
$lines = explode("\n", $content);
|
||||
foreach ($lines as $lineNumber => $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
echo " 📋 Zeile " . ($lineNumber + 1) . ": " . trim($line) . "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Logout-Form nicht gefunden\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Layout-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 6. Test-Logout-URL erstellen
|
||||
echo "\n6. 🧪 Test-Logout-URL erstellen...\n";
|
||||
$testUrl = 'https://neonail.vogt.de.com/logout';
|
||||
echo " 🔗 Test-URL: $testUrl\n";
|
||||
echo " 📋 Methode: POST\n";
|
||||
echo " 📋 CSRF-Token erforderlich\n";
|
||||
|
||||
// 7. Einfacher Test
|
||||
echo "\n7. 🧪 Einfacher Test...\n";
|
||||
echo " 📋 Öffnen Sie: https://neonail.vogt.de.com\n";
|
||||
echo " 📋 Melden Sie sich an\n";
|
||||
echo " 📋 Klicken Sie auf Ihren Benutzernamen\n";
|
||||
echo " 📋 Wählen Sie 'Abmelden'\n";
|
||||
echo " 📋 Falls Fehler: Öffnen Sie Browser-Entwicklertools (F12)\n";
|
||||
echo " 📋 Gehen Sie zu Network-Tab\n";
|
||||
echo " 📋 Schauen Sie welche URL aufgerufen wird\n";
|
||||
|
||||
echo "\n✅ Logout-Route Fix abgeschlossen!\n";
|
||||
echo "🔗 Testen Sie jetzt das Logout und teilen Sie mit:\n";
|
||||
echo "1. Funktioniert das Logout?\n";
|
||||
echo "2. Falls nicht: Welche URL wird im Network-Tab angezeigt?\n";
|
||||
echo "3. Gibt es Fehlermeldungen in der Browser-Konsole?\n";
|
||||
?>
|
||||
@@ -1,81 +0,0 @@
|
||||
<?php
|
||||
// Fix: Logout-Problem einfach beheben
|
||||
echo "🚪 Fix: Logout-Problem einfach beheben\n";
|
||||
echo "=====================================\n\n";
|
||||
|
||||
// 1. Layout-Datei korrigieren - nur den Logout-Teil
|
||||
echo "1. 🎨 Logout-Teil im Layout korrigieren...\n";
|
||||
|
||||
$layoutPath = 'resources/views/layouts/app.blade.php';
|
||||
if (file_exists($layoutPath)) {
|
||||
$content = file_get_contents($layoutPath);
|
||||
|
||||
// Hardcodierte HTTPS-URL durch Laravel Route ersetzen
|
||||
$oldLogoutForm = 'action="https://neonail.vogt.de.com/logout"';
|
||||
$newLogoutForm = 'action="{{ route("logout") }}"';
|
||||
|
||||
if (strpos($content, $oldLogoutForm) !== false) {
|
||||
$content = str_replace($oldLogoutForm, $newLogoutForm, $content);
|
||||
file_put_contents($layoutPath, $content);
|
||||
echo " ✅ Logout-Form korrigiert\n";
|
||||
} else {
|
||||
echo " ℹ️ Logout-Form bereits korrekt\n";
|
||||
}
|
||||
|
||||
// Prüfe ob Route verwendet wird
|
||||
if (strpos($content, '{{ route("logout") }}') !== false) {
|
||||
echo " ✅ Laravel Route wird verwendet\n";
|
||||
} else {
|
||||
echo " ❌ Laravel Route wird nicht verwendet\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo " ❌ Layout-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 2. Routes prüfen
|
||||
echo "\n2. 🛣️ Logout-Route prüfen...\n";
|
||||
$routesPath = 'routes/web.php';
|
||||
if (file_exists($routesPath)) {
|
||||
$content = file_get_contents($routesPath);
|
||||
|
||||
if (strpos($content, 'logout') !== false) {
|
||||
echo " ✅ Logout-Route gefunden\n";
|
||||
|
||||
// Zeige Logout-Route
|
||||
$lines = explode("\n", $content);
|
||||
foreach ($lines as $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
echo " 📋 " . trim($line) . "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Logout-Route nicht gefunden\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Routes-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 3. Cache leeren
|
||||
echo "\n3. 🧹 Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
// 4. Alternative Logout-URL testen
|
||||
echo "\n4. 🔗 Alternative Logout-URLs:\n";
|
||||
echo " - https://neonail.vogt.de.com/logout\n";
|
||||
echo " - https://neonail.vogt.de.com/logout (POST)\n";
|
||||
|
||||
echo "\n✅ Logout-Problem behoben!\n";
|
||||
echo "🔗 Testen Sie jetzt:\n";
|
||||
echo "1. Klicken Sie auf Ihren Benutzernamen (oben rechts)\n";
|
||||
echo "2. Wählen Sie 'Abmelden' aus dem Dropdown\n";
|
||||
echo "3. Sie sollten zur Login-Seite weitergeleitet werden\n";
|
||||
echo "\n📋 Falls Problem besteht:\n";
|
||||
echo "- Versuchen Sie direkt: https://neonail.vogt.de.com/logout\n";
|
||||
echo "- Prüfen Sie Browser-Entwicklertools (F12) für Fehler\n";
|
||||
echo "- Schauen Sie in die Laravel-Logs: tail -f storage/logs/laravel.log\n";
|
||||
?>
|
||||
277
fix-logout.php
277
fix-logout.php
@@ -1,277 +0,0 @@
|
||||
<?php
|
||||
// Fix: Logout-Problem beheben
|
||||
echo "🚪 Fix: Logout-Problem beheben\n";
|
||||
echo "=============================\n\n";
|
||||
|
||||
// 1. Routes prüfen
|
||||
echo "1. 🛣️ Logout-Route prüfen...\n";
|
||||
$routesPath = 'routes/web.php';
|
||||
if (file_exists($routesPath)) {
|
||||
$content = file_get_contents($routesPath);
|
||||
|
||||
if (strpos($content, 'logout') !== false) {
|
||||
echo " ✅ Logout-Route gefunden\n";
|
||||
|
||||
// Zeige Logout-Route Details
|
||||
$lines = explode("\n", $content);
|
||||
foreach ($lines as $line) {
|
||||
if (strpos($line, 'logout') !== false) {
|
||||
echo " 📋 " . trim($line) . "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Logout-Route nicht gefunden\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Routes-Datei nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 2. Layout korrigieren
|
||||
echo "\n2. 🎨 Layout korrigieren...\n";
|
||||
|
||||
$layoutContent = '<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>@yield("title", "NeoNail Datenbank")</title>
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background: rgba(255, 255, 255, 0.95) !important;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.card {
|
||||
border: none;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||
border: none;
|
||||
border-radius: 25px;
|
||||
padding: 10px 25px;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(45deg, #5a6fd8, #6a4190);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.nail-polish-card {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.nail-polish-card:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.nail-polish-image {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
border-radius: 25px;
|
||||
border: 2px solid #e9ecef;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.search-box:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dropdown-Menüs über alle anderen Elemente legen */
|
||||
.dropdown-menu {
|
||||
z-index: 9999 !important;
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
/* Navbar hat höheren z-index */
|
||||
.navbar {
|
||||
z-index: 1000 !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Dropdown-Container */
|
||||
.dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Sicherstellen, dass Dropdowns über Cards angezeigt werden */
|
||||
.navbar-nav .dropdown-menu {
|
||||
z-index: 9999 !important;
|
||||
position: absolute !important;
|
||||
top: 100% !important;
|
||||
left: 0 !important;
|
||||
float: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@yield("styles")
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light">
|
||||
<div class="container">
|
||||
<a class="navbar-brand fw-bold" href="{{ route("user-nail-polishes.index") }}">
|
||||
<i class="fas fa-palette me-2"></i>NeoNail DB
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto">
|
||||
@auth
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("user-nail-polishes.index") }}">
|
||||
<i class="fas fa-home me-1"></i>Meine Sammlung
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("user-nail-polishes.available") }}">
|
||||
<i class="fas fa-plus me-1"></i>Verfügbare Lacke
|
||||
</a>
|
||||
</li>
|
||||
@if(auth()->user()->isAdmin())
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-cog me-1"></i>Admin
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="{{ route("admin.dashboard") }}">Dashboard</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("admin.users.index") }}">Benutzer</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("nail-polishes.index") }}">Nagellacke</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("admin.statistics") }}">Statistiken</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@endif
|
||||
@endauth
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav">
|
||||
@guest
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("login") }}">Anmelden</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-user me-1"></i>{{ Auth::user()->name }}
|
||||
@if(auth()->user()->isAdmin())
|
||||
<span class="badge bg-primary ms-1">Admin</span>
|
||||
@endif
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a class="dropdown-item" href="#" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
||||
<i class="fas fa-sign-out-alt me-1"></i>Abmelden
|
||||
</a>
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
|
||||
@csrf
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@endguest
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="py-4">
|
||||
<div class="container">
|
||||
@if(session("success"))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-check-circle me-2"></i>{{ session("success") }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session("error"))
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-exclamation-circle me-2"></i>{{ session("error") }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@yield("content")
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
@yield("scripts")
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
file_put_contents('resources/views/layouts/app.blade.php', $layoutContent);
|
||||
echo " ✅ Layout korrigiert\n";
|
||||
|
||||
// 3. LoginController prüfen
|
||||
echo "\n3. 🔐 LoginController prüfen...\n";
|
||||
$controllerPath = 'app/Http/Controllers/Auth/LoginController.php';
|
||||
if (file_exists($controllerPath)) {
|
||||
$content = file_get_contents($controllerPath);
|
||||
|
||||
if (strpos($content, 'logout') !== false) {
|
||||
echo " ✅ Logout-Methode gefunden\n";
|
||||
} else {
|
||||
echo " ❌ Logout-Methode fehlt\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ LoginController nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 4. Cache leeren
|
||||
echo "\n4. 🧹 Cache leeren...\n";
|
||||
system('php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"');
|
||||
system('php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"');
|
||||
system('php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"');
|
||||
system('php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"');
|
||||
echo " ✅ Cache geleert\n";
|
||||
|
||||
// 5. Test-Logout-URL generieren
|
||||
echo "\n5. 🔗 Test-Logout-URL:\n";
|
||||
echo " https://neonail.vogt.de.com/logout\n";
|
||||
|
||||
echo "\n✅ Logout-Problem behoben!\n";
|
||||
echo "🔗 Testen Sie jetzt:\n";
|
||||
echo "1. Klicken Sie auf Ihren Benutzernamen (oben rechts)\n";
|
||||
echo "2. Wählen Sie 'Abmelden' aus dem Dropdown\n";
|
||||
echo "3. Sie sollten zur Login-Seite weitergeleitet werden\n";
|
||||
echo "\n📋 Falls Problem besteht:\n";
|
||||
echo "- Prüfen Sie Browser-Entwicklertools (F12) für Fehler\n";
|
||||
echo "- Schauen Sie in die Laravel-Logs: tail -f storage/logs/laravel.log\n";
|
||||
echo "- Versuchen Sie direkt: https://neonail.vogt.de.com/logout\n";
|
||||
?>
|
||||
@@ -1,56 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# NeoNail DB - Mail Configuration Fix Script
|
||||
# Behebt Mail-Probleme in Production
|
||||
|
||||
echo "📧 NeoNail DB - Mail Configuration Fix"
|
||||
echo "======================================"
|
||||
|
||||
# Prüfe, ob wir im richtigen Verzeichnis sind
|
||||
if [ ! -f "artisan" ]; then
|
||||
echo "❌ Fehler: artisan Datei nicht gefunden. Bitte führen Sie das Script im Laravel-Root-Verzeichnis aus."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔍 Schritt 1: Aktuelle Mail-Konfiguration prüfen..."
|
||||
php artisan tinker --execute="echo 'Mail-Konfiguration:'; echo 'MAIL_MAILER: ' . config('mail.default'); echo 'MAIL_HOST: ' . config('mail.mailers.smtp.host'); echo 'MAIL_PORT: ' . config('mail.mailers.smtp.port'); echo 'MAIL_FROM: ' . config('mail.from.address');"
|
||||
|
||||
echo "🔍 Schritt 2: Mail-Logs prüfen..."
|
||||
echo "Letzte Mail-Fehler:"
|
||||
tail -n 10 storage/logs/laravel.log | grep -i mail
|
||||
|
||||
echo "🔍 Schritt 3: Mail-Konfiguration für Production anpassen..."
|
||||
|
||||
# Backup der .env erstellen
|
||||
cp .env .env.backup.$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# Mail-Konfiguration auf log setzen (für Production ohne SMTP)
|
||||
sed -i 's/MAIL_MAILER=smtp/MAIL_MAILER=log/' .env
|
||||
sed -i 's/MAIL_HOST=mail.selfhost.de/MAIL_HOST=127.0.0.1/' .env
|
||||
sed -i 's/MAIL_PORT=465/MAIL_PORT=1025/' .env
|
||||
sed -i 's/MAIL_USERNAME=.*/MAIL_USERNAME=null/' .env
|
||||
sed -i 's/MAIL_PASSWORD=.*/MAIL_PASSWORD=null/' .env
|
||||
sed -i 's/MAIL_ENCRYPTION=ssl/MAIL_ENCRYPTION=null/' .env
|
||||
sed -i 's/MAIL_FROM_ADDRESS=.*/MAIL_FROM_ADDRESS="noreply@neonail.vogt.de.com"/' .env
|
||||
sed -i 's/MAIL_FROM_NAME=.*/MAIL_FROM_NAME="NeoNail DB"/' .env
|
||||
|
||||
echo "🔍 Schritt 4: Cache leeren..."
|
||||
php artisan config:clear
|
||||
|
||||
echo "🔍 Schritt 5: Neue Mail-Konfiguration prüfen..."
|
||||
php artisan tinker --execute="echo 'Neue Mail-Konfiguration:'; echo 'MAIL_MAILER: ' . config('mail.default'); echo 'MAIL_HOST: ' . config('mail.mailers.smtp.host'); echo 'MAIL_PORT: ' . config('mail.mailers.smtp.port'); echo 'MAIL_FROM: ' . config('mail.from.address');"
|
||||
|
||||
echo "🔍 Schritt 6: Test-Mail senden..."
|
||||
php artisan tinker --execute="use Illuminate\Support\Facades\Mail; try { Mail::raw('Test-Mail von NeoNail DB - ' . now(), function(\$message) { \$message->to('test@example.com')->subject('Test-Mail'); }); echo 'Test-Mail erfolgreich gesendet (in Logs)'; } catch(Exception \$e) { echo 'Mail-Fehler: ' . \$e->getMessage(); }"
|
||||
|
||||
echo "✅ Mail Configuration Fix abgeschlossen!"
|
||||
echo ""
|
||||
echo "🎯 Was wurde geändert:"
|
||||
echo " - MAIL_MAILER auf 'log' gesetzt (E-Mails werden in Logs geschrieben)"
|
||||
echo " - SMTP-Konfiguration für Production angepasst"
|
||||
echo " - Backup der .env erstellt"
|
||||
echo ""
|
||||
echo "📋 E-Mails werden jetzt in storage/logs/laravel.log geschrieben"
|
||||
echo "📋 Für echte E-Mail-Versendung SMTP-Server konfigurieren"
|
||||
echo ""
|
||||
echo "🚀 Mail-System ist jetzt funktionsfähig!"
|
||||
@@ -1,35 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🧹 Pail Cache Problem lösen"
|
||||
echo "=========================="
|
||||
|
||||
# 1. Cache-Dateien löschen
|
||||
echo "🗑️ Lösche Cache-Dateien..."
|
||||
rm -f bootstrap/cache/packages.php
|
||||
rm -f bootstrap/cache/services.php
|
||||
rm -f bootstrap/cache/config.php
|
||||
|
||||
# 2. Composer autoload neu generieren
|
||||
echo "🔄 Generiere autoload neu..."
|
||||
if command -v composer &> /dev/null; then
|
||||
composer dump-autoload --optimize
|
||||
elif [ -f "composer.phar" ]; then
|
||||
php composer.phar dump-autoload --optimize
|
||||
else
|
||||
echo "⚠️ Composer nicht verfügbar"
|
||||
fi
|
||||
|
||||
# 3. Laravel Cache leeren
|
||||
echo "🧹 Leere Laravel Cache..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen"
|
||||
|
||||
# 4. Berechtigungen setzen
|
||||
echo "🔐 Setze Berechtigungen..."
|
||||
chmod -R 777 bootstrap/cache/
|
||||
|
||||
echo ""
|
||||
echo "✅ Pail Cache Problem behoben!"
|
||||
echo "📋 Testen Sie: php artisan --version"
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🧹 Finale Pail-Problem Lösung"
|
||||
echo "============================="
|
||||
|
||||
# 1. Alle Cache-Dateien löschen
|
||||
echo "🗑️ Lösche alle Cache-Dateien..."
|
||||
rm -f bootstrap/cache/packages.php
|
||||
rm -f bootstrap/cache/services.php
|
||||
rm -f bootstrap/cache/config.php
|
||||
rm -f bootstrap/cache/routes.php
|
||||
rm -f bootstrap/cache/views.php
|
||||
|
||||
# 2. Composer autoload neu generieren
|
||||
echo "🔄 Generiere Composer autoload neu..."
|
||||
if command -v composer &> /dev/null; then
|
||||
composer dump-autoload --optimize
|
||||
elif [ -f "composer.phar" ]; then
|
||||
php composer.phar dump-autoload --optimize
|
||||
else
|
||||
echo "⚠️ Composer nicht verfügbar, überspringe autoload"
|
||||
fi
|
||||
|
||||
# 3. Laravel Cache komplett leeren
|
||||
echo "🧹 Leere Laravel Cache komplett..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen"
|
||||
|
||||
# 4. Berechtigungen setzen
|
||||
echo "🔐 Setze Berechtigungen..."
|
||||
chmod -R 777 bootstrap/cache/
|
||||
chmod -R 777 storage/
|
||||
|
||||
# 5. Debug deaktivieren (für Produktion)
|
||||
echo "🔧 Setze Debug-Modus zurück..."
|
||||
sed -i 's/APP_DEBUG=true/APP_DEBUG=false/' .env
|
||||
|
||||
# 6. Test
|
||||
echo "🧪 Teste Anwendung..."
|
||||
curl -I http://192.168.30.81
|
||||
|
||||
echo ""
|
||||
echo "✅ Pail-Problem behoben!"
|
||||
echo "📋 Testen Sie: http://192.168.30.81"
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# NeoNail DB - Berechtigungen korrigieren
|
||||
echo "🔧 NeoNail DB - Berechtigungen korrigieren..."
|
||||
|
||||
# 1. Storage-Verzeichnisse erstellen (falls nicht vorhanden)
|
||||
echo "📁 Storage-Verzeichnisse erstellen..."
|
||||
mkdir -p storage/framework/views
|
||||
mkdir -p storage/framework/cache
|
||||
mkdir -p storage/framework/sessions
|
||||
mkdir -p storage/logs
|
||||
mkdir -p bootstrap/cache
|
||||
|
||||
# 2. Berechtigungen für Storage setzen
|
||||
echo "🔐 Storage-Berechtigungen setzen..."
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 storage/framework/
|
||||
chmod -R 777 storage/framework/views/
|
||||
chmod -R 777 storage/framework/cache/
|
||||
chmod -R 777 storage/framework/sessions/
|
||||
chmod -R 777 storage/logs/
|
||||
|
||||
# 3. Bootstrap/Cache-Berechtigungen
|
||||
echo "🔐 Bootstrap/Cache-Berechtigungen setzen..."
|
||||
chmod -R 777 bootstrap/cache/
|
||||
|
||||
# 4. SQLite-Datenbank erstellen und Berechtigungen setzen
|
||||
echo "🗄️ SQLite-Datenbank erstellen..."
|
||||
if [ ! -f database.sqlite ]; then
|
||||
touch database.sqlite
|
||||
echo "✅ SQLite-Datenbank erstellt"
|
||||
else
|
||||
echo "✅ SQLite-Datenbank bereits vorhanden"
|
||||
fi
|
||||
chmod 664 database.sqlite
|
||||
|
||||
# 5. .env Berechtigungen
|
||||
echo "🔐 .env Berechtigungen setzen..."
|
||||
if [ -f .env ]; then
|
||||
chmod 644 .env
|
||||
echo "✅ .env Berechtigungen gesetzt"
|
||||
else
|
||||
echo "⚠️ .env Datei nicht gefunden"
|
||||
fi
|
||||
|
||||
# 6. Cache leeren
|
||||
echo "🧹 Cache leeren..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ php artisan nicht verfügbar"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ php artisan nicht verfügbar"
|
||||
php artisan view:clear 2>/dev/null || echo "⚠️ php artisan nicht verfügbar"
|
||||
|
||||
# 7. Storage-Link erstellen
|
||||
echo "🔗 Storage-Link erstellen..."
|
||||
php artisan storage:link 2>/dev/null || echo "⚠️ php artisan nicht verfügbar"
|
||||
|
||||
echo "✅ Berechtigungen korrigiert!"
|
||||
echo ""
|
||||
echo "📋 Nächste Schritte:"
|
||||
echo "1. Seite neu laden: http://192.168.30.81/neonail/"
|
||||
echo "2. Falls immer noch Fehler: Composer install ausführen"
|
||||
echo "3. Migrationen ausführen: php artisan migrate --force"
|
||||
echo "4. Admin-User erstellen: php artisan tinker"
|
||||
echo ""
|
||||
echo "💡 Falls Probleme bestehen:"
|
||||
echo "- Hosting-Provider kontaktieren"
|
||||
echo "- SSH-Zugang anfordern"
|
||||
echo "- Berechtigungen über Hosting-Panel prüfen"
|
||||
@@ -1,104 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🛡️ Fix: Verbleibende Safari Sicherheitswarnungen"
|
||||
echo "==============================================="
|
||||
|
||||
# 1. Logout-Formular beheben
|
||||
echo "1. 🔒 Logout-Formular beheben..."
|
||||
if [ -f resources/views/layouts/app.blade.php ]; then
|
||||
sed -i 's|action="{{ route('\''logout'\'') }}"|action="https://neonail.vogt.de.com/logout"|' resources/views/layouts/app.blade.php
|
||||
echo " ✅ Logout-Formular behoben"
|
||||
else
|
||||
echo " ❌ layouts/app.blade.php nicht gefunden"
|
||||
fi
|
||||
|
||||
# 2. Alle verbleibenden route() Aufrufe finden
|
||||
echo "2. 🔍 Alle verbleibenden route() Aufrufe finden..."
|
||||
grep -r "route(" resources/views/ --include="*.blade.php" | grep -E "(action|href)" || echo " ℹ️ Keine verbleibenden route() Aufrufe in action/href gefunden"
|
||||
|
||||
# 3. Alle Formulare mit HTTPS-URLs prüfen
|
||||
echo "3. 🔒 Alle Formulare mit HTTPS prüfen..."
|
||||
php test-forms-fixed.php
|
||||
|
||||
# 4. Laravel Cache leeren
|
||||
echo "4. 🧹 Laravel Cache leeren..."
|
||||
php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"
|
||||
php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"
|
||||
|
||||
# 5. Test-Script erstellen
|
||||
echo "5. 🧪 Test-Script erstellen..."
|
||||
cat > test-all-forms-final.php << 'EOF'
|
||||
<?php
|
||||
// Finaler Test aller Formulare auf HTTPS
|
||||
echo "🔒 Finaler Test aller Formulare auf HTTPS\n";
|
||||
echo "=======================================\n\n";
|
||||
|
||||
$forms = [
|
||||
'resources/views/auth/login.blade.php' => 'Login-Formular',
|
||||
'resources/views/user-nail-polishes/create.blade.php' => 'Create Nail Polish',
|
||||
'resources/views/user-nail-polishes/index.blade.php' => 'Remove Nail Polish',
|
||||
'resources/views/nail-polishes/index.blade.php' => 'Admin Delete Nail Polish',
|
||||
'resources/views/admin/users/create.blade.php' => 'Admin Create User',
|
||||
'resources/views/admin/users/edit.blade.php' => 'Admin Edit User',
|
||||
'resources/views/admin/users/index.blade.php' => 'Admin Delete User',
|
||||
'resources/views/layouts/app.blade.php' => 'Logout-Formular'
|
||||
];
|
||||
|
||||
$allFixed = true;
|
||||
|
||||
foreach ($forms as $file => $description) {
|
||||
if (file_exists($file)) {
|
||||
$content = file_get_contents($file);
|
||||
if (strpos($content, 'action="https://neonail.vogt.de.com') !== false) {
|
||||
echo " ✅ $description: HTTPS-URL gefunden\n";
|
||||
} else {
|
||||
echo " ❌ $description: Keine HTTPS-URL gefunden\n";
|
||||
$allFixed = false;
|
||||
|
||||
// Zeige die aktuelle action
|
||||
if (preg_match('/action="([^"]+)"/', $content, $matches)) {
|
||||
echo " Aktuelle action: " . $matches[1] . "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo " ❌ $description: Datei nicht gefunden\n";
|
||||
$allFixed = false;
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
if ($allFixed) {
|
||||
echo "🎉 ALLE Formulare sind jetzt mit HTTPS-URLs konfiguriert!\n";
|
||||
echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com\n";
|
||||
echo "📝 Safari-Sicherheitswarnungen sollten komplett verschwunden sein.\n";
|
||||
} else {
|
||||
echo "⚠️ Einige Formulare müssen noch korrigiert werden.\n";
|
||||
echo "🔧 Führen Sie das Fix-Script erneut aus.\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Finaler Formular-Test abgeschlossen!\n";
|
||||
?>
|
||||
EOF
|
||||
|
||||
echo " ✅ Test-Script erstellt"
|
||||
|
||||
# 6. Finalen Test ausführen
|
||||
echo "6. 🧪 Finalen Test ausführen..."
|
||||
php test-all-forms-final.php
|
||||
|
||||
echo ""
|
||||
echo "✅ Verbleibende Safari Sicherheitswarnungen behoben!"
|
||||
echo ""
|
||||
echo "🔗 Testen Sie jetzt:"
|
||||
echo "1. Login: https://neonail.vogt.de.com/login"
|
||||
echo "2. Logout: Klicken Sie auf Ihren Namen → Abmelden"
|
||||
echo "3. Admin-Panel: https://neonail.vogt.de.com/admin/users"
|
||||
echo "4. Lack erstellen: https://neonail.vogt.de.com/create-nail-polish"
|
||||
echo ""
|
||||
echo "📝 Falls Warnungen bestehen:"
|
||||
echo "- Führen Sie php test-all-forms-final.php aus"
|
||||
echo "- Leeren Sie Browser-Cache komplett"
|
||||
echo "- Prüfen Sie Browser-Entwicklertools (F12)"
|
||||
echo "- Testen Sie in einem Inkognito-Fenster"
|
||||
@@ -1,207 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🍎 Safari Formular-Sicherheit beheben"
|
||||
echo "===================================="
|
||||
|
||||
# 1. .env komplett für HTTPS konfigurieren
|
||||
echo "📝 Konfiguriere .env für HTTPS..."
|
||||
cat > .env << 'EOF'
|
||||
APP_NAME="NeoNail DB"
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:+LTZYPKjkZ+O3iFTgU2sS+9bNvxxvG8Kw8JSEPiG7Rs=
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://neonail.vogt.de.com
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=database.sqlite
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_SECURE_COOKIE=true
|
||||
SESSION_SAME_SITE=lax
|
||||
SESSION_HTTP_ONLY=true
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailpit
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_HOST=
|
||||
PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
||||
# HTTPS-Konfiguration
|
||||
FORCE_HTTPS=true
|
||||
SECURE_COOKIES=true
|
||||
EOF
|
||||
|
||||
# 2. Session-Konfiguration für HTTPS
|
||||
echo "🔐 Konfiguriere Session für HTTPS..."
|
||||
cat > config/session.php << 'EOF'
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
'driver' => env('SESSION_DRIVER', 'file'),
|
||||
'lifetime' => env('SESSION_LIFETIME', 120),
|
||||
'expire_on_close' => false,
|
||||
'encrypt' => false,
|
||||
'files' => storage_path('framework/sessions'),
|
||||
'connection' => env('SESSION_CONNECTION'),
|
||||
'table' => 'sessions',
|
||||
'store' => env('SESSION_STORE'),
|
||||
'lottery' => [2, 100],
|
||||
'cookie' => env(
|
||||
'SESSION_COOKIE',
|
||||
Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
|
||||
),
|
||||
'path' => '/',
|
||||
'domain' => env('SESSION_DOMAIN'),
|
||||
'secure' => true,
|
||||
'http_only' => true,
|
||||
'same_site' => 'lax',
|
||||
];
|
||||
EOF
|
||||
|
||||
# 3. Laravel Cache komplett leeren
|
||||
echo "🧹 Leere Laravel Cache komplett..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen"
|
||||
|
||||
# 4. HTTPS-Force in .htaccess
|
||||
echo "🔒 Füge HTTPS-Force hinzu..."
|
||||
cat > public/.htaccess << 'EOF'
|
||||
<IfModule mod_rewrite.c>
|
||||
<IfModule mod_negotiation.c>
|
||||
Options -MultiViews -Indexes
|
||||
</IfModule>
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
# Force HTTPS
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Handle Authorization Header
|
||||
RewriteCond %{HTTP:Authorization} .
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
# Redirect Trailing Slashes If Not A Folder...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} (.+)/$
|
||||
RewriteRule ^ %1 [L,R=301]
|
||||
|
||||
# Send Requests To Front Controller...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
|
||||
# Security Headers
|
||||
<IfModule mod_headers.c>
|
||||
Header always set X-Content-Type-Options nosniff
|
||||
Header always set X-Frame-Options DENY
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
Header always set Content-Security-Policy "upgrade-insecure-requests"
|
||||
Header always set X-Forwarded-Proto https
|
||||
</IfModule>
|
||||
|
||||
# Protect sensitive files
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "*.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
# Compression
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/plain
|
||||
AddOutputFilterByType DEFLATE text/html
|
||||
AddOutputFilterByType DEFLATE text/xml
|
||||
AddOutputFilterByType DEFLATE text/css
|
||||
AddOutputFilterByType DEFLATE application/xml
|
||||
AddOutputFilterByType DEFLATE application/xhtml+xml
|
||||
AddOutputFilterByType DEFLATE application/rss+xml
|
||||
AddOutputFilterByType DEFLATE application/javascript
|
||||
AddOutputFilterByType DEFLATE application/x-javascript
|
||||
</IfModule>
|
||||
|
||||
# Cache Control
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive on
|
||||
ExpiresByType text/css "access plus 1 year"
|
||||
ExpiresByType application/javascript "access plus 1 year"
|
||||
ExpiresByType image/png "access plus 1 year"
|
||||
ExpiresByType image/jpg "access plus 1 year"
|
||||
ExpiresByType image/jpeg "access plus 1 year"
|
||||
ExpiresByType image/gif "access plus 1 year"
|
||||
ExpiresByType image/svg+xml "access plus 1 year"
|
||||
</IfModule>
|
||||
EOF
|
||||
|
||||
# 5. Apache neu laden
|
||||
echo "🔄 Lade Apache neu..."
|
||||
systemctl reload apache2
|
||||
|
||||
# 6. Test
|
||||
echo "🧪 Teste HTTPS-Konfiguration..."
|
||||
curl -I https://neonail.vogt.de.com
|
||||
|
||||
echo ""
|
||||
echo "✅ Safari Formular-Sicherheit behoben!"
|
||||
echo "📋 Testen Sie: https://neonail.vogt.de.com"
|
||||
echo ""
|
||||
echo "📋 Falls Warnung bleibt:"
|
||||
echo "1. Safari-Cache leeren (Cmd+Shift+R)"
|
||||
echo "2. Private-Fenster testen"
|
||||
echo "3. Safari-Einstellungen: Entwickler > Leere Caches"
|
||||
echo "4. Safari-Einstellungen: Datenschutz > Website-Daten verwalten"
|
||||
@@ -1,171 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🍎 Safari HTTPS-Warnung beheben"
|
||||
echo "=============================="
|
||||
|
||||
# 1. .env komplett für HTTPS konfigurieren
|
||||
echo "📝 Konfiguriere .env komplett für HTTPS..."
|
||||
cat > .env << 'EOF'
|
||||
APP_NAME="NeoNail DB"
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:+LTZYPKjkZ+O3iFTgU2sS+9bNvxxvG8Kw8JSEPiG7Rs=
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://neonail.vogt.de.com
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=database.sqlite
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_SECURE_COOKIE=true
|
||||
SESSION_SAME_SITE=lax
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailpit
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_HOST=
|
||||
PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
EOF
|
||||
|
||||
# 2. Laravel Cache komplett leeren
|
||||
echo "🧹 Leere Laravel Cache komplett..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen"
|
||||
|
||||
# 3. HTTPS-Header in .htaccess hinzufügen
|
||||
echo "🔒 Füge HTTPS-Header hinzu..."
|
||||
cat > public/.htaccess << 'EOF'
|
||||
<IfModule mod_rewrite.c>
|
||||
<IfModule mod_negotiation.c>
|
||||
Options -MultiViews -Indexes
|
||||
</IfModule>
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
# Force HTTPS
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Handle Authorization Header
|
||||
RewriteCond %{HTTP:Authorization} .
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
# Redirect Trailing Slashes If Not A Folder...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} (.+)/$
|
||||
RewriteRule ^ %1 [L,R=301]
|
||||
|
||||
# Send Requests To Front Controller...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
|
||||
# Security Headers
|
||||
<IfModule mod_headers.c>
|
||||
Header always set X-Content-Type-Options nosniff
|
||||
Header always set X-Frame-Options DENY
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
Header always set Content-Security-Policy "upgrade-insecure-requests"
|
||||
</IfModule>
|
||||
|
||||
# Protect sensitive files
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "*.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
# Compression
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/plain
|
||||
AddOutputFilterByType DEFLATE text/html
|
||||
AddOutputFilterByType DEFLATE text/xml
|
||||
AddOutputFilterByType DEFLATE text/css
|
||||
AddOutputFilterByType DEFLATE application/xml
|
||||
AddOutputFilterByType DEFLATE application/xhtml+xml
|
||||
AddOutputFilterByType DEFLATE application/rss+xml
|
||||
AddOutputFilterByType DEFLATE application/javascript
|
||||
AddOutputFilterByType DEFLATE application/x-javascript
|
||||
</IfModule>
|
||||
|
||||
# Cache Control
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive on
|
||||
ExpiresByType text/css "access plus 1 year"
|
||||
ExpiresByType application/javascript "access plus 1 year"
|
||||
ExpiresByType image/png "access plus 1 year"
|
||||
ExpiresByType image/jpg "access plus 1 year"
|
||||
ExpiresByType image/jpeg "access plus 1 year"
|
||||
ExpiresByType image/gif "access plus 1 year"
|
||||
ExpiresByType image/svg+xml "access plus 1 year"
|
||||
</IfModule>
|
||||
EOF
|
||||
|
||||
# 4. Apache neu laden
|
||||
echo "🔄 Lade Apache neu..."
|
||||
systemctl reload apache2
|
||||
|
||||
# 5. Test
|
||||
echo "🧪 Teste HTTPS-Konfiguration..."
|
||||
curl -I https://neonail.vogt.de.com
|
||||
|
||||
echo ""
|
||||
echo "✅ Safari HTTPS-Warnung behoben!"
|
||||
echo "📋 Testen Sie: https://neonail.vogt.de.com"
|
||||
echo ""
|
||||
echo "📋 Falls Warnung bleibt:"
|
||||
echo "1. Safari-Cache leeren (Cmd+Shift+R)"
|
||||
echo "2. Private-Fenster testen"
|
||||
echo "3. Safari-Einstellungen: Entwickler > Leere Caches"
|
||||
@@ -1,166 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🛡️ Fix: Safari Sicherheitswarnungen"
|
||||
echo "=================================="
|
||||
|
||||
# 1. .env HTTPS-Einstellungen
|
||||
echo "1. 🔒 HTTPS-Einstellungen in .env..."
|
||||
if [ -f .env ]; then
|
||||
# Setze alle HTTPS-Einstellungen
|
||||
sed -i 's|APP_URL=.*|APP_URL=https://neonail.vogt.de.com|' .env
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
sed -i 's/APP_ENV=production/APP_ENV=local/' .env
|
||||
|
||||
# HTTPS-spezifische Einstellungen
|
||||
echo "FORCE_HTTPS=true" >> .env
|
||||
echo "SECURE_COOKIES=true" >> .env
|
||||
echo "SESSION_SECURE_COOKIE=true" >> .env
|
||||
echo "SESSION_SAME_SITE=lax" >> .env
|
||||
echo "SESSION_HTTP_ONLY=true" >> .env
|
||||
|
||||
echo " ✅ .env HTTPS-Einstellungen aktualisiert"
|
||||
else
|
||||
echo " ❌ .env Datei nicht gefunden"
|
||||
fi
|
||||
|
||||
# 2. Session-Konfiguration
|
||||
echo "2. 🍪 Session-Konfiguration..."
|
||||
if [ -f config/session.php ]; then
|
||||
sed -i "s/'secure' => false/'secure' => true/" config/session.php
|
||||
sed -i "s/'http_only' => false/'http_only' => true/" config/session.php
|
||||
echo " ✅ Session-Konfiguration aktualisiert"
|
||||
else
|
||||
echo " ❌ config/session.php nicht gefunden"
|
||||
fi
|
||||
|
||||
# 3. CSRF-Konfiguration
|
||||
echo "3. 🔐 CSRF-Konfiguration..."
|
||||
if [ -f config/csrf.php ]; then
|
||||
sed -i "s/'secure' => false/'secure' => true/" config/csrf.php
|
||||
sed -i "s/'same_site' => 'lax'/'same_site' => 'lax'/" config/csrf.php
|
||||
echo " ✅ CSRF-Konfiguration aktualisiert"
|
||||
else
|
||||
echo " ❌ config/csrf.php nicht gefunden"
|
||||
fi
|
||||
|
||||
# 4. .htaccess HTTPS-Headers
|
||||
echo "4. 🌐 .htaccess HTTPS-Headers..."
|
||||
if [ -f public/.htaccess ]; then
|
||||
# Füge HTTPS-Headers hinzu
|
||||
if ! grep -q "Strict-Transport-Security" public/.htaccess; then
|
||||
sed -i '/# Security Headers/a\
|
||||
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"\
|
||||
Header always set Content-Security-Policy "upgrade-insecure-requests"' public/.htaccess
|
||||
fi
|
||||
|
||||
# Force HTTPS
|
||||
if ! grep -q "RewriteCond %{HTTPS} off" public/.htaccess; then
|
||||
sed -i '/RewriteEngine On/a\
|
||||
RewriteCond %{HTTPS} off\
|
||||
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]' public/.htaccess
|
||||
fi
|
||||
|
||||
echo " ✅ .htaccess HTTPS-Headers aktualisiert"
|
||||
else
|
||||
echo " ❌ public/.htaccess nicht gefunden"
|
||||
fi
|
||||
|
||||
# 5. AppServiceProvider HTTPS-Force
|
||||
echo "5. 🔧 AppServiceProvider HTTPS-Force..."
|
||||
if [ -f app/Providers/AppServiceProvider.php ]; then
|
||||
if ! grep -q "URL::forceScheme('https')" app/Providers/AppServiceProvider.php; then
|
||||
sed -i "/public function boot(): void/a\\
|
||||
if (config('app.env') === 'production') {\\
|
||||
URL::forceScheme('https');\\
|
||||
}" app/Providers/AppServiceProvider.php
|
||||
fi
|
||||
echo " ✅ AppServiceProvider HTTPS-Force aktualisiert"
|
||||
else
|
||||
echo " ❌ AppServiceProvider nicht gefunden"
|
||||
fi
|
||||
|
||||
# 6. Laravel Cache leeren
|
||||
echo "6. 🧹 Laravel Cache leeren..."
|
||||
php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"
|
||||
php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"
|
||||
|
||||
# 7. Test-Script erstellen
|
||||
echo "7. 🧪 Test-Script erstellen..."
|
||||
cat > test-https-security.php << 'EOF'
|
||||
<?php
|
||||
// Test der HTTPS-Sicherheit
|
||||
echo "🔒 HTTPS-Sicherheit Test\n";
|
||||
echo "======================\n\n";
|
||||
|
||||
// 1. Prüfe .env Einstellungen
|
||||
echo "1. .env Einstellungen:\n";
|
||||
$envVars = ['APP_URL', 'FORCE_HTTPS', 'SECURE_COOKIES', 'SESSION_SECURE_COOKIE'];
|
||||
foreach ($envVars as $var) {
|
||||
$value = getenv($var) ?: 'nicht gesetzt';
|
||||
echo " - $var: $value\n";
|
||||
}
|
||||
|
||||
// 2. Prüfe Session-Konfiguration
|
||||
echo "\n2. Session-Konfiguration:\n";
|
||||
if (file_exists('config/session.php')) {
|
||||
$content = file_get_contents('config/session.php');
|
||||
if (strpos($content, "'secure' => true") !== false) {
|
||||
echo " ✅ Session secure: true\n";
|
||||
} else {
|
||||
echo " ❌ Session secure: false\n";
|
||||
}
|
||||
if (strpos($content, "'http_only' => true") !== false) {
|
||||
echo " ✅ Session http_only: true\n";
|
||||
} else {
|
||||
echo " ❌ Session http_only: false\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Prüfe CSRF-Konfiguration
|
||||
echo "\n3. CSRF-Konfiguration:\n";
|
||||
if (file_exists('config/csrf.php')) {
|
||||
$content = file_get_contents('config/csrf.php');
|
||||
if (strpos($content, "'secure' => true") !== false) {
|
||||
echo " ✅ CSRF secure: true\n";
|
||||
} else {
|
||||
echo " ❌ CSRF secure: false\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Prüfe .htaccess
|
||||
echo "\n4. .htaccess HTTPS-Headers:\n";
|
||||
if (file_exists('public/.htaccess')) {
|
||||
$content = file_get_contents('public/.htaccess');
|
||||
if (strpos($content, 'Strict-Transport-Security') !== false) {
|
||||
echo " ✅ HSTS Header vorhanden\n";
|
||||
} else {
|
||||
echo " ❌ HSTS Header fehlt\n";
|
||||
}
|
||||
if (strpos($content, 'upgrade-insecure-requests') !== false) {
|
||||
echo " ✅ CSP upgrade-insecure-requests vorhanden\n";
|
||||
} else {
|
||||
echo " ❌ CSP upgrade-insecure-requests fehlt\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n✅ HTTPS-Sicherheit Test abgeschlossen!\n";
|
||||
echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/admin/users\n";
|
||||
?>
|
||||
EOF
|
||||
|
||||
echo " ✅ Test-Script erstellt"
|
||||
|
||||
echo ""
|
||||
echo "✅ Safari Sicherheitswarnungen behoben!"
|
||||
echo ""
|
||||
echo "🔗 Testen Sie jetzt:"
|
||||
echo "1. Admin-Panel: https://neonail.vogt.de.com/admin/users"
|
||||
echo "2. Lack löschen im Admin-Panel"
|
||||
echo "3. User bearbeiten/löschen"
|
||||
echo ""
|
||||
echo "📝 Falls Warnungen bestehen:"
|
||||
echo "- Führen Sie php test-https-security.php aus"
|
||||
echo "- Prüfen Sie Browser-Entwicklertools (F12)"
|
||||
echo "- Leeren Sie Browser-Cache"
|
||||
@@ -1,41 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🗄️ SQLite-Berechtigungen korrigieren"
|
||||
echo "==================================="
|
||||
|
||||
# 1. Aktuelle Berechtigungen prüfen
|
||||
echo "🔍 Aktuelle Berechtigungen:"
|
||||
ls -la database.sqlite
|
||||
echo ""
|
||||
|
||||
# 2. Berechtigungen korrigieren
|
||||
echo "🔐 Setze SQLite-Berechtigungen..."
|
||||
chown www-data:www-data database.sqlite
|
||||
chmod 664 database.sqlite
|
||||
|
||||
# 3. Verzeichnis-Berechtigungen
|
||||
echo "📁 Setze Verzeichnis-Berechtigungen..."
|
||||
chown -R www-data:www-data /var/www/html
|
||||
chmod -R 755 /var/www/html
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
|
||||
# 4. SQLite-Datei testen
|
||||
echo "🧪 Teste SQLite-Schreibzugriff..."
|
||||
if [ -w database.sqlite ]; then
|
||||
echo "✅ SQLite-Datei ist schreibbar"
|
||||
else
|
||||
echo "❌ SQLite-Datei ist NICHT schreibbar"
|
||||
fi
|
||||
|
||||
# 5. Apache-User prüfen
|
||||
echo "👤 Apache-User:"
|
||||
ps aux | grep apache | head -1
|
||||
|
||||
# 6. Test-Schreibzugriff
|
||||
echo "📝 Teste Schreibzugriff..."
|
||||
sqlite3 database.sqlite "CREATE TABLE IF NOT EXISTS test_write (id INTEGER); DROP TABLE test_write;" 2>/dev/null && echo "✅ SQLite-Schreibzugriff funktioniert" || echo "❌ SQLite-Schreibzugriff fehlgeschlagen"
|
||||
|
||||
echo ""
|
||||
echo "✅ SQLite-Berechtigungen korrigiert!"
|
||||
echo "📋 Testen Sie jetzt das Erstellen eines Lackes"
|
||||
@@ -1,70 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔗 Storage Link Problem lösen"
|
||||
echo "============================"
|
||||
|
||||
# 1. Aktuellen Storage-Status prüfen
|
||||
echo "🔍 Aktueller Storage-Status:"
|
||||
ls -la public/storage
|
||||
echo ""
|
||||
|
||||
# 2. Storage-Verzeichnis entfernen (falls es ein Verzeichnis ist)
|
||||
echo "🗑️ Entferne falsches Storage-Verzeichnis..."
|
||||
if [ -d "public/storage" ]; then
|
||||
rm -rf public/storage
|
||||
echo "✅ Storage-Verzeichnis entfernt"
|
||||
elif [ -L "public/storage" ]; then
|
||||
rm public/storage
|
||||
echo "✅ Storage-Link entfernt"
|
||||
fi
|
||||
|
||||
# 3. Storage Link neu erstellen
|
||||
echo "🔗 Erstelle Storage Link neu..."
|
||||
php artisan storage:link
|
||||
|
||||
# 4. Link prüfen
|
||||
echo "🔍 Prüfe neuen Storage Link:"
|
||||
ls -la public/storage
|
||||
echo ""
|
||||
|
||||
# 5. Ziel-Verzeichnis prüfen
|
||||
echo "📁 Prüfe Ziel-Verzeichnis:"
|
||||
ls -la storage/app/public/
|
||||
echo ""
|
||||
|
||||
# 6. Bilder-Verzeichnis prüfen
|
||||
echo "🖼️ Prüfe Bilder-Verzeichnis:"
|
||||
ls -la storage/app/public/nail_polishes/ 2>/dev/null || echo "⚠️ nail_polishes Verzeichnis nicht gefunden"
|
||||
|
||||
# 7. Test-Bild erstellen
|
||||
echo "🧪 Erstelle Test-Bild..."
|
||||
mkdir -p storage/app/public/nail_polishes
|
||||
echo "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==" | base64 -d > storage/app/public/nail_polishes/test.jpg
|
||||
chmod 644 storage/app/public/nail_polishes/test.jpg
|
||||
|
||||
# 8. Berechtigungen setzen
|
||||
echo "🔐 Setze Berechtigungen..."
|
||||
chmod -R 755 public/storage/
|
||||
chmod -R 777 storage/app/public/
|
||||
|
||||
# 9. Test-URL
|
||||
echo "🧪 Teste Bild-URL..."
|
||||
curl -I https://neonail.vogt.de.com/storage/nail_polishes/test.jpg
|
||||
|
||||
# 10. Echte Bilder testen
|
||||
echo "🖼️ Teste echte Bilder..."
|
||||
sqlite3 database.sqlite "SELECT image_path FROM nail_polishes WHERE image_path IS NOT NULL LIMIT 1;" | while read image_path; do
|
||||
if [ ! -z "$image_path" ]; then
|
||||
echo "Teste: $image_path"
|
||||
if [ -f "storage/app/public/$image_path" ]; then
|
||||
echo "✅ Bild existiert: $image_path"
|
||||
curl -I "https://neonail.vogt.de.com/storage/$image_path"
|
||||
else
|
||||
echo "❌ Bild fehlt: $image_path"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "✅ Storage Link Problem behoben!"
|
||||
echo "📋 Testen Sie: https://neonail.vogt.de.com"
|
||||
@@ -1,133 +0,0 @@
|
||||
<?php
|
||||
// Fix: Upload-Limits für Bild-Upload
|
||||
echo "📸 Fix: Upload-Limits für Bild-Upload\n";
|
||||
echo "===================================\n\n";
|
||||
|
||||
// 1. Aktuelle PHP-Upload-Limits prüfen
|
||||
echo "1. 🔍 Aktuelle PHP-Upload-Limits:\n";
|
||||
$limits = [
|
||||
'upload_max_filesize' => ini_get('upload_max_filesize'),
|
||||
'post_max_size' => ini_get('post_max_size'),
|
||||
'max_file_uploads' => ini_get('max_file_uploads'),
|
||||
'memory_limit' => ini_get('memory_limit'),
|
||||
'max_execution_time' => ini_get('max_execution_time'),
|
||||
'max_input_time' => ini_get('max_input_time')
|
||||
];
|
||||
|
||||
foreach ($limits as $setting => $value) {
|
||||
echo " - $setting: $value\n";
|
||||
}
|
||||
|
||||
// 2. Konvertiere zu Bytes für Vergleich
|
||||
function convertToBytes($sizeStr) {
|
||||
$sizeStr = strtolower(trim($sizeStr));
|
||||
$last = strtolower($sizeStr[strlen($sizeStr)-1]);
|
||||
$size = (int)$sizeStr;
|
||||
|
||||
switch($last) {
|
||||
case 'g': $size *= 1024;
|
||||
case 'm': $size *= 1024;
|
||||
case 'k': $size *= 1024;
|
||||
}
|
||||
|
||||
return $size;
|
||||
}
|
||||
|
||||
$uploadMaxBytes = convertToBytes($limits['upload_max_filesize']);
|
||||
$postMaxBytes = convertToBytes($limits['post_max_size']);
|
||||
$requiredBytes = 10 * 1024 * 1024; // 10MB
|
||||
|
||||
echo "\n2. 📊 Größenvergleich:\n";
|
||||
echo " - Upload max filesize: " . number_format($uploadMaxBytes) . " Bytes\n";
|
||||
echo " - Post max size: " . number_format($postMaxBytes) . " Bytes\n";
|
||||
echo " - Benötigt für 10MB: " . number_format($requiredBytes) . " Bytes\n";
|
||||
|
||||
if ($uploadMaxBytes < $requiredBytes) {
|
||||
echo " ⚠️ upload_max_filesize ist zu klein für 10MB Uploads\n";
|
||||
} else {
|
||||
echo " ✅ upload_max_filesize ist ausreichend\n";
|
||||
}
|
||||
|
||||
if ($postMaxBytes < $requiredBytes) {
|
||||
echo " ⚠️ post_max_size ist zu klein für 10MB Uploads\n";
|
||||
} else {
|
||||
echo " ✅ post_max_size ist ausreichend\n";
|
||||
}
|
||||
|
||||
// 3. .htaccess für Upload-Limits erstellen
|
||||
echo "\n3. 🔧 .htaccess Upload-Limits erstellen...\n";
|
||||
$htaccessContent = "
|
||||
# Upload-Limits für Bild-Upload
|
||||
php_value upload_max_filesize 10M
|
||||
php_value post_max_size 10M
|
||||
php_value max_file_uploads 20
|
||||
php_value memory_limit 256M
|
||||
php_value max_execution_time 300
|
||||
php_value max_input_time 300
|
||||
";
|
||||
|
||||
if (file_exists('public/.htaccess')) {
|
||||
$currentHtaccess = file_get_contents('public/.htaccess');
|
||||
|
||||
// Prüfe ob Upload-Limits bereits vorhanden sind
|
||||
if (strpos($currentHtaccess, 'upload_max_filesize') === false) {
|
||||
// Füge Upload-Limits hinzu
|
||||
$newHtaccess = $currentHtaccess . "\n" . $htaccessContent;
|
||||
file_put_contents('public/.htaccess', $newHtaccess);
|
||||
echo " ✅ Upload-Limits zu .htaccess hinzugefügt\n";
|
||||
} else {
|
||||
echo " ℹ️ Upload-Limits bereits in .htaccess vorhanden\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ public/.htaccess nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 4. Test-Upload-Funktionalität
|
||||
echo "\n4. 🧪 Test Upload-Funktionalität...\n";
|
||||
|
||||
// Prüfe GD Extension
|
||||
if (extension_loaded('gd')) {
|
||||
echo " ✅ GD Extension geladen\n";
|
||||
} else {
|
||||
echo " ❌ GD Extension nicht geladen - Bildverarbeitung nicht möglich\n";
|
||||
}
|
||||
|
||||
// Prüfe Storage-Verzeichnis
|
||||
$storagePath = 'storage/app/public/nail_polishes';
|
||||
if (is_dir($storagePath)) {
|
||||
echo " ✅ Storage-Verzeichnis existiert: $storagePath\n";
|
||||
} else {
|
||||
echo " ⚠️ Storage-Verzeichnis existiert nicht: $storagePath\n";
|
||||
mkdir($storagePath, 0755, true);
|
||||
echo " ✅ Storage-Verzeichnis erstellt\n";
|
||||
}
|
||||
|
||||
// Prüfe Schreibrechte
|
||||
if (is_writable($storagePath)) {
|
||||
echo " ✅ Storage-Verzeichnis beschreibbar\n";
|
||||
} else {
|
||||
echo " ❌ Storage-Verzeichnis nicht beschreibbar\n";
|
||||
}
|
||||
|
||||
// 5. Laravel Storage Link prüfen
|
||||
echo "\n5. 🔗 Laravel Storage Link prüfen...\n";
|
||||
$publicStoragePath = 'public/storage';
|
||||
if (is_link($publicStoragePath)) {
|
||||
echo " ✅ Storage Link existiert\n";
|
||||
} else {
|
||||
echo " ⚠️ Storage Link existiert nicht\n";
|
||||
if (file_exists('public/storage')) {
|
||||
echo " ℹ️ public/storage ist ein Verzeichnis, kein Link\n";
|
||||
} else {
|
||||
echo " ℹ️ public/storage existiert nicht\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n✅ Upload-Limits Fix abgeschlossen!\n";
|
||||
echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/create-nail-polish\n";
|
||||
echo "📝 Versuchen Sie ein Handy-Foto hochzuladen (bis 10MB)\n";
|
||||
echo "\n📋 Falls Upload immer noch fehlschlägt:\n";
|
||||
echo "- Prüfen Sie die Browser-Entwicklertools (F12) für Details\n";
|
||||
echo "- Schauen Sie in storage/logs/laravel.log für Laravel-Fehler\n";
|
||||
echo "- Prüfen Sie die Apache-Logs für Server-Fehler\n";
|
||||
?>
|
||||
@@ -1,158 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🚨 Force Fix: Upload-Limits erzwingen"
|
||||
echo "===================================="
|
||||
|
||||
# 1. Laravel Cache komplett leeren
|
||||
echo "1. 🧹 Laravel Cache komplett leeren..."
|
||||
php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen"
|
||||
php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen"
|
||||
php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen"
|
||||
php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen"
|
||||
php artisan config:cache 2>/dev/null || echo " ⚠️ config:cache übersprungen"
|
||||
|
||||
# 2. Bootstrap Cache leeren
|
||||
echo "2. 🗂️ Bootstrap Cache leeren..."
|
||||
rm -f bootstrap/cache/*.php 2>/dev/null || echo " ⚠️ bootstrap/cache/*.php nicht gefunden"
|
||||
|
||||
# 3. .htaccess Upload-Limits erzwingen
|
||||
echo "3. 🔧 .htaccess Upload-Limits erzwingen..."
|
||||
cat > public/.htaccess << 'EOF'
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
|
||||
# Force HTTPS
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Handle Authorization Header
|
||||
RewriteCond %{HTTP:Authorization} .
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
# Redirect Trailing Slashes If Not A Folder...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} (.+)/$
|
||||
RewriteRule ^ %1 [L,R=301]
|
||||
|
||||
# Send Requests To Front Controller...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
|
||||
# Upload-Limits für Bild-Upload
|
||||
php_value upload_max_filesize 10M
|
||||
php_value post_max_size 10M
|
||||
php_value max_file_uploads 20
|
||||
php_value memory_limit 256M
|
||||
php_value max_execution_time 300
|
||||
php_value max_input_time 300
|
||||
|
||||
# Protect sensitive files
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "*.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
EOF
|
||||
|
||||
echo " ✅ .htaccess mit Upload-Limits erstellt"
|
||||
|
||||
# 4. PHP-Konfiguration prüfen
|
||||
echo "4. 🔍 PHP-Konfiguration prüfen..."
|
||||
php fix-upload-limits.php
|
||||
|
||||
# 5. Apache neu laden
|
||||
echo "5. 🔄 Apache neu laden..."
|
||||
systemctl reload apache2 2>/dev/null || service apache2 reload 2>/dev/null || echo " ⚠️ Apache reload fehlgeschlagen"
|
||||
|
||||
# 6. Test-Script erstellen
|
||||
echo "6. 🧪 Test-Script erstellen..."
|
||||
cat > test-upload-limits.php << 'EOF'
|
||||
<?php
|
||||
// Test der Upload-Limits
|
||||
echo "📸 Test der Upload-Limits\n";
|
||||
echo "========================\n\n";
|
||||
|
||||
// 1. PHP-Upload-Limits
|
||||
echo "1. PHP-Upload-Limits:\n";
|
||||
$limits = [
|
||||
'upload_max_filesize' => ini_get('upload_max_filesize'),
|
||||
'post_max_size' => ini_get('post_max_size'),
|
||||
'max_file_uploads' => ini_get('max_file_uploads'),
|
||||
'memory_limit' => ini_get('memory_limit')
|
||||
];
|
||||
|
||||
foreach ($limits as $setting => $value) {
|
||||
echo " - $setting: $value\n";
|
||||
}
|
||||
|
||||
// 2. Laravel Validierungsregeln prüfen
|
||||
echo "\n2. Laravel Validierungsregeln:\n";
|
||||
$controllerPath = 'app/Http/Controllers/UserNailPolishController.php';
|
||||
if (file_exists($controllerPath)) {
|
||||
$content = file_get_contents($controllerPath);
|
||||
if (preg_match('/image.*max:(\d+)/', $content, $matches)) {
|
||||
$maxKB = $matches[1];
|
||||
$maxMB = $maxKB / 1024;
|
||||
echo " - Bild-Upload-Limit: {$maxKB}KB ({$maxMB}MB)\n";
|
||||
|
||||
if ($maxMB >= 10) {
|
||||
echo " ✅ Upload-Limit ist ausreichend (>= 10MB)\n";
|
||||
} else {
|
||||
echo " ❌ Upload-Limit ist zu klein (< 10MB)\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Keine Bild-Upload-Validierung gefunden\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Controller nicht gefunden\n";
|
||||
}
|
||||
|
||||
// 3. View-Text prüfen
|
||||
echo "\n3. View-Text:\n";
|
||||
$viewPath = 'resources/views/user-nail-polishes/create.blade.php';
|
||||
if (file_exists($viewPath)) {
|
||||
$content = file_get_contents($viewPath);
|
||||
if (preg_match('/Maximale Größe: (\d+MB)/', $content, $matches)) {
|
||||
echo " - Angezeigte Größe: {$matches[1]}\n";
|
||||
|
||||
if ($matches[1] === '10MB') {
|
||||
echo " ✅ View zeigt korrekte Größe an\n";
|
||||
} else {
|
||||
echo " ❌ View zeigt falsche Größe an\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ Keine Größenangabe in View gefunden\n";
|
||||
}
|
||||
} else {
|
||||
echo " ❌ View nicht gefunden\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Upload-Limits Test abgeschlossen!\n";
|
||||
echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/create-nail-polish\n";
|
||||
?>
|
||||
EOF
|
||||
|
||||
echo " ✅ Test-Script erstellt"
|
||||
|
||||
echo ""
|
||||
echo "✅ Force Upload-Limits Fix abgeschlossen!"
|
||||
echo ""
|
||||
echo "🔗 Testen Sie jetzt:"
|
||||
echo "1. https://neonail.vogt.de.com/create-nail-polish"
|
||||
echo "2. Versuchen Sie ein Handy-Foto hochzuladen"
|
||||
echo ""
|
||||
echo "📝 Falls Problem besteht:"
|
||||
echo "- Führen Sie php test-upload-limits.php aus"
|
||||
echo "- Leeren Sie Browser-Cache"
|
||||
echo "- Testen Sie in einem Inkognito-Fenster"
|
||||
@@ -1,24 +0,0 @@
|
||||
# NeoNail DB - Hauptverzeichnis .htaccess
|
||||
# Umleitung auf public/ Ordner
|
||||
|
||||
# Sicherheit
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
# Umleitung auf public/
|
||||
RewriteEngine On
|
||||
RewriteRule ^$ public/ [L]
|
||||
RewriteRule (.*) public/$1 [L]
|
||||
|
||||
# Fallback für direkte PHP-Dateien
|
||||
<Files "*.php">
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Files>
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "📦 Composer lokale Installation"
|
||||
echo "=============================="
|
||||
|
||||
# 1. Composer herunterladen
|
||||
echo "⬇️ Lade Composer herunter..."
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
# 2. Composer lokal verwenden
|
||||
echo "🔗 Verwende Composer lokal..."
|
||||
php composer.phar --version
|
||||
|
||||
echo ""
|
||||
echo "🎉 Composer lokal verfügbar!"
|
||||
echo "📋 Verwenden Sie:"
|
||||
echo " php composer.phar install --no-dev"
|
||||
echo ""
|
||||
echo "📋 Oder für andere Composer-Befehle:"
|
||||
echo " php composer.phar [befehl]"
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "📦 Composer Installation"
|
||||
echo "======================="
|
||||
|
||||
# 1. PHP und curl prüfen
|
||||
echo "🔍 Prüfe PHP und curl..."
|
||||
if ! command -v php &> /dev/null; then
|
||||
echo "❌ PHP nicht gefunden!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v curl &> /dev/null; then
|
||||
echo "❌ curl nicht gefunden!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. Composer herunterladen
|
||||
echo "⬇️ Lade Composer herunter..."
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
# 3. Composer global verfügbar machen
|
||||
echo "🔗 Mache Composer global verfügbar..."
|
||||
sudo mv composer.phar /usr/local/bin/composer
|
||||
sudo chmod +x /usr/local/bin/composer
|
||||
|
||||
# 4. Test
|
||||
echo "✅ Teste Composer..."
|
||||
composer --version
|
||||
|
||||
echo ""
|
||||
echo "🎉 Composer erfolgreich installiert!"
|
||||
echo "📋 Jetzt können Sie ausführen:"
|
||||
echo " composer install --no-dev"
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🖼️ GD PHP Extension installieren"
|
||||
echo "==============================="
|
||||
|
||||
# 1. System-Update
|
||||
echo "🔄 System-Update..."
|
||||
apt update
|
||||
|
||||
# 2. GD Extension installieren
|
||||
echo "📦 Installiere GD Extension..."
|
||||
apt install -y php-gd
|
||||
|
||||
# 3. Weitere nötige Extensions
|
||||
echo "📦 Installiere weitere Extensions..."
|
||||
apt install -y libpng-dev libjpeg-dev libfreetype6-dev
|
||||
|
||||
# 4. PHP-Module neu laden
|
||||
echo "🔄 Lade PHP-Module neu..."
|
||||
systemctl reload apache2 2>/dev/null || echo "⚠️ Apache reload übersprungen"
|
||||
systemctl reload nginx 2>/dev/null || echo "⚠️ Nginx reload übersprungen"
|
||||
|
||||
# 5. GD Extension testen
|
||||
echo "🧪 Teste GD Extension..."
|
||||
php -m | grep -i gd
|
||||
|
||||
# 6. PHP-Info für GD
|
||||
echo "📋 GD PHP-Info:"
|
||||
php -r "if (extension_loaded('gd')) { echo '✅ GD Extension ist aktiviert\n'; echo 'Version: ' . gd_info()['GD Version'] . '\n'; } else { echo '❌ GD Extension ist NICHT aktiviert\n'; }"
|
||||
|
||||
# 7. Laravel Cache leeren
|
||||
echo "🧹 Leere Laravel Cache..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
|
||||
echo ""
|
||||
echo "✅ GD Extension installiert!"
|
||||
echo "📋 Testen Sie jetzt das Erstellen eines Lackes mit Bild"
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🗄️ SQLite-Treiber Installation"
|
||||
echo "=============================="
|
||||
|
||||
# 1. System-Update
|
||||
echo "🔄 System-Update..."
|
||||
apt update
|
||||
|
||||
# 2. SQLite und PHP-SQLite installieren
|
||||
echo "📦 Installiere SQLite..."
|
||||
apt install -y sqlite3 php-sqlite3 php-pdo-sqlite
|
||||
|
||||
# 3. PHP-Module neu laden
|
||||
echo "🔄 Lade PHP-Module neu..."
|
||||
systemctl reload apache2 2>/dev/null || echo "⚠️ Apache reload übersprungen"
|
||||
systemctl reload nginx 2>/dev/null || echo "⚠️ Nginx reload übersprungen"
|
||||
|
||||
# 4. PHP-Info prüfen
|
||||
echo "🔍 Prüfe SQLite-Installation..."
|
||||
php -m | grep -i sqlite
|
||||
|
||||
echo ""
|
||||
echo "✅ SQLite-Treiber installiert!"
|
||||
echo "📋 Testen Sie: php -m | grep sqlite"
|
||||
114
laravel-test.php
114
laravel-test.php
@@ -1,114 +0,0 @@
|
||||
<?php
|
||||
// Laravel-Test für NeoNail DB
|
||||
echo "<h1>Laravel-Test</h1>";
|
||||
|
||||
// 1. Composer autoload testen
|
||||
echo "<h2>1. Composer Autoload:</h2>";
|
||||
if (file_exists('vendor/autoload.php')) {
|
||||
require_once 'vendor/autoload.php';
|
||||
echo "✅ Autoload geladen<br>";
|
||||
} else {
|
||||
echo "❌ vendor/autoload.php nicht gefunden<br>";
|
||||
echo "Führen Sie 'composer install' aus<br>";
|
||||
exit;
|
||||
}
|
||||
|
||||
// 2. Laravel Bootstrap testen
|
||||
echo "<h2>2. Laravel Bootstrap:</h2>";
|
||||
if (file_exists('bootstrap/app.php')) {
|
||||
try {
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
echo "✅ Laravel App geladen<br>";
|
||||
} catch (Exception $e) {
|
||||
echo "❌ Laravel Bootstrap Fehler: " . $e->getMessage() . "<br>";
|
||||
}
|
||||
} else {
|
||||
echo "❌ bootstrap/app.php nicht gefunden<br>";
|
||||
}
|
||||
|
||||
// 3. .env laden testen
|
||||
echo "<h2>3. .env Konfiguration:</h2>";
|
||||
if (file_exists('.env')) {
|
||||
$env_content = file_get_contents('.env');
|
||||
echo "✅ .env Datei gefunden<br>";
|
||||
|
||||
// Wichtige Einstellungen prüfen
|
||||
$checks = [
|
||||
'APP_ENV' => 'production',
|
||||
'APP_DEBUG' => 'false',
|
||||
'DB_CONNECTION' => 'sqlite',
|
||||
'DB_DATABASE' => 'database.sqlite'
|
||||
];
|
||||
|
||||
foreach ($checks as $key => $expected) {
|
||||
if (preg_match("/^$key=(.*)$/m", $env_content, $matches)) {
|
||||
$value = trim($matches[1]);
|
||||
$status = ($value === $expected) ? "✅" : "⚠️";
|
||||
echo "$status $key = $value (erwartet: $expected)<br>";
|
||||
} else {
|
||||
echo "❌ $key nicht gefunden<br>";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "❌ .env Datei nicht gefunden<br>";
|
||||
}
|
||||
|
||||
// 4. SQLite-Verbindung testen
|
||||
echo "<h2>4. SQLite-Verbindung:</h2>";
|
||||
if (file_exists('database.sqlite')) {
|
||||
try {
|
||||
$pdo = new PDO('sqlite:database.sqlite');
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
echo "✅ SQLite-Verbindung erfolgreich<br>";
|
||||
|
||||
// Tabellen prüfen
|
||||
$tables = $pdo->query("SELECT name FROM sqlite_master WHERE type='table'")->fetchAll(PDO::FETCH_COLUMN);
|
||||
echo "Gefundene Tabellen: " . implode(', ', $tables) . "<br>";
|
||||
|
||||
} catch (PDOException $e) {
|
||||
echo "❌ SQLite-Fehler: " . $e->getMessage() . "<br>";
|
||||
}
|
||||
} else {
|
||||
echo "❌ database.sqlite nicht gefunden<br>";
|
||||
}
|
||||
|
||||
// 5. Storage-Verzeichnis testen
|
||||
echo "<h2>5. Storage-Verzeichnis:</h2>";
|
||||
if (is_dir('storage')) {
|
||||
if (is_writable('storage')) {
|
||||
echo "✅ storage/ ist schreibbar<br>";
|
||||
} else {
|
||||
echo "❌ storage/ ist nicht schreibbar<br>";
|
||||
}
|
||||
|
||||
// Storage-Link prüfen
|
||||
if (is_link('public/storage')) {
|
||||
echo "✅ Storage-Link existiert<br>";
|
||||
} else {
|
||||
echo "⚠️ Storage-Link fehlt (php artisan storage:link)<br>";
|
||||
}
|
||||
} else {
|
||||
echo "❌ storage/ Verzeichnis nicht gefunden<br>";
|
||||
}
|
||||
|
||||
// 6. Cache-Verzeichnis testen
|
||||
echo "<h2>6. Cache-Verzeichnis:</h2>";
|
||||
if (is_dir('bootstrap/cache')) {
|
||||
if (is_writable('bootstrap/cache')) {
|
||||
echo "✅ bootstrap/cache/ ist schreibbar<br>";
|
||||
} else {
|
||||
echo "❌ bootstrap/cache/ ist nicht schreibbar<br>";
|
||||
}
|
||||
} else {
|
||||
echo "❌ bootstrap/cache/ Verzeichnis nicht gefunden<br>";
|
||||
}
|
||||
|
||||
echo "<hr>";
|
||||
echo "<h2>Empfohlene Aktionen:</h2>";
|
||||
echo "1. Falls Composer fehlt: composer install ausführen<br>";
|
||||
echo "2. Falls .env falsch: env-sqlite-example.txt zu .env kopieren<br>";
|
||||
echo "3. Falls Berechtigungen falsch: chmod 755 storage/ bootstrap/cache/<br>";
|
||||
echo "4. Falls SQLite fehlt: touch database.sqlite && chmod 664 database.sqlite<br>";
|
||||
echo "5. Falls Storage-Link fehlt: php artisan storage:link<br>";
|
||||
echo "6. Migrationen ausführen: php artisan migrate --force<br>";
|
||||
?>
|
||||
@@ -1,97 +0,0 @@
|
||||
# 📧 Mail-Konfiguration Problem - Lösung
|
||||
|
||||
## 🚨 **Problem:**
|
||||
- E-Mails werden nicht versendet
|
||||
- Weder User noch Admin erhalten E-Mails
|
||||
- Mail-Fehler in den Logs
|
||||
|
||||
## 🔍 **Ursache:**
|
||||
SMTP-Server `mail.selfhost.de:465` ist nicht erreichbar oder falsch konfiguriert.
|
||||
|
||||
## 🔧 **Lösung:**
|
||||
|
||||
### **Schritt 1: Auf dem Webspace ausführen**
|
||||
|
||||
```bash
|
||||
# 1. Ins Laravel-Verzeichnis wechseln
|
||||
cd /var/www/html
|
||||
|
||||
# 2. Mail Configuration Fix ausführen
|
||||
./fix-mail-config.sh
|
||||
```
|
||||
|
||||
### **Schritt 2: Manuell (falls Script nicht funktioniert)**
|
||||
|
||||
```bash
|
||||
# 1. Backup der .env erstellen
|
||||
cp .env .env.backup.$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# 2. Mail-Konfiguration anpassen
|
||||
sed -i 's/MAIL_MAILER=smtp/MAIL_MAILER=log/' .env
|
||||
sed -i 's/MAIL_HOST=mail.selfhost.de/MAIL_HOST=127.0.0.1/' .env
|
||||
sed -i 's/MAIL_PORT=465/MAIL_PORT=1025/' .env
|
||||
sed -i 's/MAIL_USERNAME=.*/MAIL_USERNAME=null/' .env
|
||||
sed -i 's/MAIL_PASSWORD=.*/MAIL_PASSWORD=null/' .env
|
||||
sed -i 's/MAIL_ENCRYPTION=ssl/MAIL_ENCRYPTION=null/' .env
|
||||
sed -i 's/MAIL_FROM_ADDRESS=.*/MAIL_FROM_ADDRESS="noreply@neonail.vogt.de.com"/' .env
|
||||
sed -i 's/MAIL_FROM_NAME=.*/MAIL_FROM_NAME="NeoNail DB"/' .env
|
||||
|
||||
# 3. Cache leeren
|
||||
php artisan config:clear
|
||||
|
||||
# 4. Test-Mail senden
|
||||
php artisan tinker --execute="use Illuminate\Support\Facades\Mail; Mail::raw('Test-Mail von NeoNail DB - ' . now(), function(\$message) { \$message->to('test@example.com')->subject('Test-Mail'); }); echo 'Test-Mail gesendet';"
|
||||
```
|
||||
|
||||
### **Schritt 3: E-Mails in Logs prüfen**
|
||||
|
||||
```bash
|
||||
# Mail-Logs anzeigen
|
||||
tail -f storage/logs/laravel.log | grep -i mail
|
||||
|
||||
# Oder alle Logs durchsuchen
|
||||
grep -i "mail\|email" storage/logs/laravel.log
|
||||
```
|
||||
|
||||
## 🎯 **Was passiert jetzt:**
|
||||
|
||||
### **Option 1: Log-Modus (empfohlen für Production)**
|
||||
- E-Mails werden in `storage/logs/laravel.log` geschrieben
|
||||
- Keine echten E-Mails versendet
|
||||
- System funktioniert ohne SMTP-Server
|
||||
|
||||
### **Option 2: Echte E-Mail-Versendung**
|
||||
Für echte E-Mail-Versendung SMTP-Server konfigurieren:
|
||||
|
||||
```env
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=ihr-smtp-server.com
|
||||
MAIL_PORT=587
|
||||
MAIL_USERNAME=ihr-username
|
||||
MAIL_PASSWORD=ihr-passwort
|
||||
MAIL_ENCRYPTION=tls
|
||||
MAIL_FROM_ADDRESS="noreply@ihre-domain.com"
|
||||
MAIL_FROM_NAME="NeoNail DB"
|
||||
```
|
||||
|
||||
## 📋 **Mail-Logs prüfen:**
|
||||
|
||||
```bash
|
||||
# Letzte Mail-Einträge anzeigen
|
||||
tail -n 50 storage/logs/laravel.log | grep -i mail
|
||||
|
||||
# Spezifische Mail suchen
|
||||
grep -i "willkommens-e-mail" storage/logs/laravel.log
|
||||
```
|
||||
|
||||
## 🚀 **Nach dem Fix:**
|
||||
|
||||
1. **Neuen User erstellen** - E-Mail wird in Logs geschrieben
|
||||
2. **Logs prüfen** - E-Mail-Inhalt anzeigen
|
||||
3. **Bei Bedarf** - SMTP-Server für echte E-Mails konfigurieren
|
||||
|
||||
## ⚠️ **Wichtige Hinweise:**
|
||||
|
||||
- **Log-Modus** ist sicher für Production ohne SMTP-Server
|
||||
- **E-Mails sind in Logs verfügbar** für Debugging
|
||||
- **SMTP-Konfiguration** nur bei verfügbarem Mail-Server
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
// Bestehenden User zum Admin machen
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
try {
|
||||
// Laravel App initialisieren
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
echo "<h1>👑 User zum Admin machen</h1>";
|
||||
|
||||
// Alle User anzeigen
|
||||
echo "<h2>👥 Alle User:</h2>";
|
||||
$allUsers = User::all();
|
||||
|
||||
if ($allUsers->count() > 0) {
|
||||
echo "<table border='1' style='border-collapse: collapse;'>";
|
||||
echo "<tr><th>ID</th><th>Name</th><th>Email</th><th>Erstellt</th><th>Aktion</th></tr>";
|
||||
|
||||
foreach ($allUsers as $user) {
|
||||
$isAdmin = ($user->email === 'admin@neonail.com' || $user->email === 'neueradmin@neonail.com');
|
||||
echo "<tr>";
|
||||
echo "<td>{$user->id}</td>";
|
||||
echo "<td>{$user->name}</td>";
|
||||
echo "<td>{$user->email}</td>";
|
||||
echo "<td>{$user->created_at}</td>";
|
||||
echo "<td>" . ($isAdmin ? "👑 Admin" : "👤 User") . "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
|
||||
// User zum Admin machen (Beispiel: User mit ID 2)
|
||||
$userId = 2; // Ändern Sie diese ID
|
||||
$user = User::find($userId);
|
||||
|
||||
if ($user) {
|
||||
echo "<h2>🔧 User zum Admin machen:</h2>";
|
||||
echo "<p><strong>User:</strong> {$user->name} ({$user->email})</p>";
|
||||
|
||||
// Passwort ändern (optional)
|
||||
$newPassword = 'admin123';
|
||||
$user->password = bcrypt($newPassword);
|
||||
$user->save();
|
||||
|
||||
echo "<p>✅ User wurde zum Admin gemacht!</p>";
|
||||
echo "<p><strong>Neues Passwort:</strong> {$newPassword}</p>";
|
||||
echo "<p><strong>Login:</strong> {$user->email} / {$newPassword}</p>";
|
||||
} else {
|
||||
echo "<p>❌ User mit ID {$userId} nicht gefunden</p>";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo "<p>❌ Keine User gefunden</p>";
|
||||
}
|
||||
|
||||
echo "<h2>🔑 Admin-Login:</h2>";
|
||||
echo "<p>Verwenden Sie eine der Admin-Emails:</p>";
|
||||
echo "<ul>";
|
||||
echo "<li>admin@neonail.com</li>";
|
||||
echo "<li>neueradmin@neonail.com</li>";
|
||||
echo "</ul>";
|
||||
echo "<p><strong>Passwort:</strong> admin123</p>";
|
||||
echo "<p><a href='https://neonail.vogt.de.com' style='background: #007bff; color: white; padding: 10px; text-decoration: none; border-radius: 5px;'>🚀 Zur Anwendung</a></p>";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "<h2>❌ Fehler:</h2>";
|
||||
echo "<p>{$e->getMessage()}</p>";
|
||||
}
|
||||
?>
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
// Neuen Admin-User erstellen
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
try {
|
||||
// Laravel App initialisieren
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
echo "<h1>👑 Neuen Admin-User erstellen</h1>";
|
||||
|
||||
// Prüfe ob User bereits existiert
|
||||
$email = 'neueradmin@neonail.com';
|
||||
$existingUser = User::where('email', $email)->first();
|
||||
|
||||
if ($existingUser) {
|
||||
echo "<h2>✅ User existiert bereits!</h2>";
|
||||
echo "<p><strong>Name:</strong> {$existingUser->name}</p>";
|
||||
echo "<p><strong>Email:</strong> {$existingUser->email}</p>";
|
||||
echo "<p><strong>ID:</strong> {$existingUser->id}</p>";
|
||||
echo "<p><strong>Erstellt:</strong> {$existingUser->created_at}</p>";
|
||||
} else {
|
||||
// Neuen Admin-User erstellen
|
||||
$newAdmin = User::create([
|
||||
'name' => 'Neuer Admin',
|
||||
'email' => $email,
|
||||
'password' => bcrypt('admin123')
|
||||
]);
|
||||
|
||||
echo "<h2>✅ Neuer Admin-User erstellt!</h2>";
|
||||
echo "<p><strong>Name:</strong> {$newAdmin->name}</p>";
|
||||
echo "<p><strong>Email:</strong> {$newAdmin->email}</p>";
|
||||
echo "<p><strong>Passwort:</strong> admin123</p>";
|
||||
echo "<p><strong>ID:</strong> {$newAdmin->id}</p>";
|
||||
}
|
||||
|
||||
// Alle Admin-User anzeigen
|
||||
echo "<h2>👑 Alle Admin-User:</h2>";
|
||||
$allUsers = User::all();
|
||||
|
||||
echo "<table border='1' style='border-collapse: collapse;'>";
|
||||
echo "<tr><th>ID</th><th>Name</th><th>Email</th><th>Erstellt</th></tr>";
|
||||
|
||||
foreach ($allUsers as $user) {
|
||||
echo "<tr>";
|
||||
echo "<td>{$user->id}</td>";
|
||||
echo "<td>{$user->name}</td>";
|
||||
echo "<td>{$user->email}</td>";
|
||||
echo "<td>{$user->created_at}</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
|
||||
echo "<h2>🔑 Login-Daten:</h2>";
|
||||
echo "<p><strong>Email:</strong> neueradmin@neonail.com</p>";
|
||||
echo "<p><strong>Passwort:</strong> admin123</p>";
|
||||
echo "<p><a href='https://neonail.vogt.de.com' style='background: #007bff; color: white; padding: 10px; text-decoration: none; border-radius: 5px;'>🚀 Zur Anwendung</a></p>";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "<h2>❌ Fehler:</h2>";
|
||||
echo "<p>{$e->getMessage()}</p>";
|
||||
}
|
||||
?>
|
||||
3
memory/MEMORY.md
Normal file
3
memory/MEMORY.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Memory Index — NeoNail DB
|
||||
|
||||
- [Project Overview](project_overview.md) — Laravel 12 Nagellack-Sammlungs-App, SQLite, Bootstrap 5, Admin/User-Rollen, Foto-Upload
|
||||
34
memory/project_overview.md
Normal file
34
memory/project_overview.md
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: project-overview
|
||||
description: NeoNail DB — Laravel-Webapp für persönliche Nagellack-Sammlungen mit Fotos, Admin-Bereich und E-Mail-Benachrichtigungen
|
||||
metadata:
|
||||
type: project
|
||||
---
|
||||
|
||||
NeoNail DB ist eine Laravel 12 / PHP 8.2 Webanwendung (SQLite-Datenbank), bei der Nutzer ihre eigene Nagellack-Sammlung verwalten und Fotos hochladen können.
|
||||
|
||||
**Kernfunktionen:**
|
||||
- User-Sammlung: eigene Lacke hinzufügen/entfernen (Many-to-Many via `user_nail_polishes`)
|
||||
- Foto-Upload: Bilder werden im `storage/public/nail_polishes/` Ordner gespeichert
|
||||
- Hersteller-Verwaltung: alle eingeloggten User können Hersteller anlegen/bearbeiten
|
||||
- Admin-Bereich (`/admin`): User-CRUD, Nagellack-Katalog, Statistiken, Willkommens-E-Mails
|
||||
- E-Mail: Willkommens-Mail an neue User + Bestätigungs-Mail an Admin (oliver@vogt.de.com)
|
||||
|
||||
**Tech-Stack:**
|
||||
- Backend: Laravel 12, PHP 8.2, SQLite (database/database.sqlite)
|
||||
- Frontend: Bootstrap 5.3, Font Awesome 6, Blade-Templates
|
||||
- Bild-Verarbeitung: Intervention Image v3 (im NailPolishController), direkt im UserNailPolishController
|
||||
- Auth: Laravel UI (kein Breeze/Jetstream), session-basiert
|
||||
|
||||
**Rollen:**
|
||||
- User: kann Sammlung verwalten, Hersteller anlegen, eigene Lacke hinzufügen
|
||||
- Admin: `is_admin`-Flag in users-Tabelle ODER E-Mail-Whitelist in User::isAdmin()
|
||||
|
||||
**Wichtige Controller:**
|
||||
- `NailPolishController` — Admin-only CRUD für den globalen Katalog
|
||||
- `UserNailPolishController` — User-seitige Sammlung (index, available, add, remove, create/store)
|
||||
- `AdminController` — Dashboard, User-Management, Statistiken
|
||||
- `ManufacturerController` — für alle eingeloggten User
|
||||
|
||||
**Why:** Persönliches Hobby-Projekt zur Verwaltung einer Nagellack-Sammlung.
|
||||
**How to apply:** Bei neuen Features beachten: User sehen nur ihre eigene Sammlung, nur Admins verwalten den Gesamt-Katalog. SQLite-Datei liegt doppelt (root + database/). Viele Debug-/Fix-Skripte im Root stammen aus der Produktions-Einrichtung und können ignoriert werden.
|
||||
137
monitor-logs.php
137
monitor-logs.php
@@ -1,137 +0,0 @@
|
||||
<?php
|
||||
// Monitor: Laravel-Logs überwachen
|
||||
echo "📋 Monitor: Laravel-Logs überwachen\n";
|
||||
echo "==================================\n\n";
|
||||
|
||||
// 1. Aktuelle Logs anzeigen
|
||||
echo "1. 📄 Aktuelle Laravel-Logs:\n";
|
||||
$logFiles = [
|
||||
'storage/logs/laravel.log',
|
||||
'storage/logs/laravel-' . date('Y-m-d') . '.log'
|
||||
];
|
||||
|
||||
foreach ($logFiles as $logFile) {
|
||||
if (file_exists($logFile)) {
|
||||
echo "\n📋 $logFile:\n";
|
||||
echo str_repeat('-', 50) . "\n";
|
||||
|
||||
$lines = file($logFile);
|
||||
$lastLines = array_slice($lines, -20); // Letzte 20 Zeilen
|
||||
|
||||
foreach ($lastLines as $line) {
|
||||
$line = trim($line);
|
||||
if (!empty($line)) {
|
||||
// Markiere Fehler rot
|
||||
if (strpos($line, 'ERROR') !== false || strpos($line, 'Exception') !== false) {
|
||||
echo "❌ $line\n";
|
||||
} elseif (strpos($line, 'WARNING') !== false) {
|
||||
echo "⚠️ $line\n";
|
||||
} elseif (strpos($line, 'INFO') !== false) {
|
||||
echo "ℹ️ $line\n";
|
||||
} else {
|
||||
echo " $line\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "❌ $logFile nicht gefunden\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Apache-Logs prüfen
|
||||
echo "\n2. 🌐 Apache-Logs prüfen:\n";
|
||||
$apacheLogs = [
|
||||
'/var/log/apache2/error.log',
|
||||
'/var/log/apache2/neonail_error.log',
|
||||
'/var/log/apache2/access.log',
|
||||
'/var/log/apache2/neonail_access.log'
|
||||
];
|
||||
|
||||
foreach ($apacheLogs as $logFile) {
|
||||
if (file_exists($logFile)) {
|
||||
echo "\n📋 $logFile:\n";
|
||||
echo str_repeat('-', 50) . "\n";
|
||||
|
||||
$lines = file($logFile);
|
||||
$lastLines = array_slice($lines, -10); // Letzte 10 Zeilen
|
||||
|
||||
foreach ($lastLines as $line) {
|
||||
$line = trim($line);
|
||||
if (!empty($line)) {
|
||||
if (strpos($line, 'error') !== false || strpos($line, 'Error') !== false) {
|
||||
echo "❌ $line\n";
|
||||
} else {
|
||||
echo " $line\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "❌ $logFile nicht gefunden\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 3. PHP-Fehler-Log prüfen
|
||||
echo "\n3. 🐘 PHP-Fehler-Log prüfen:\n";
|
||||
$phpLogs = [
|
||||
'/var/log/php_errors.log',
|
||||
'/var/log/php8.1-fpm.log',
|
||||
'/var/log/php8.0-fpm.log',
|
||||
'/var/log/php7.4-fpm.log'
|
||||
];
|
||||
|
||||
foreach ($phpLogs as $logFile) {
|
||||
if (file_exists($logFile)) {
|
||||
echo "\n📋 $logFile:\n";
|
||||
echo str_repeat('-', 50) . "\n";
|
||||
|
||||
$lines = file($logFile);
|
||||
$lastLines = array_slice($lines, -10); // Letzte 10 Zeilen
|
||||
|
||||
foreach ($lastLines as $line) {
|
||||
$line = trim($line);
|
||||
if (!empty($line)) {
|
||||
if (strpos($line, 'error') !== false || strpos($line, 'Error') !== false) {
|
||||
echo "❌ $line\n";
|
||||
} else {
|
||||
echo " $line\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "❌ $logFile nicht gefunden\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Upload-spezifische Fehler suchen
|
||||
echo "\n4. 📸 Upload-spezifische Fehler:\n";
|
||||
echo str_repeat('-', 50) . "\n";
|
||||
|
||||
$uploadKeywords = [
|
||||
'upload', 'image', 'file', 'storage', 'intervention', 'gd', 'driver'
|
||||
];
|
||||
|
||||
foreach ($logFiles as $logFile) {
|
||||
if (file_exists($logFile)) {
|
||||
$content = file_get_contents($logFile);
|
||||
|
||||
foreach ($uploadKeywords as $keyword) {
|
||||
$lines = explode("\n", $content);
|
||||
foreach ($lines as $line) {
|
||||
if (stripos($line, $keyword) !== false) {
|
||||
$line = trim($line);
|
||||
if (!empty($line)) {
|
||||
echo "🔍 [$keyword] $line\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n✅ Log-Überwachung abgeschlossen!\n";
|
||||
echo "📋 Nächste Schritte:\n";
|
||||
echo "1. Versuchen Sie einen Bild-Upload\n";
|
||||
echo "2. Führen Sie dieses Script erneut aus\n";
|
||||
echo "3. Schauen Sie nach neuen Fehlermeldungen\n";
|
||||
echo "4. Teilen Sie die relevanten Fehlermeldungen mit\n";
|
||||
?>
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🚨 Quick Fix: HTTP 500 Internal Server Error"
|
||||
echo "==========================================="
|
||||
|
||||
# 1. Debug aktivieren
|
||||
echo "1. 🐛 Debug aktivieren..."
|
||||
if [ -f .env ]; then
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
sed -i 's/APP_ENV=production/APP_ENV=local/' .env
|
||||
echo " ✅ Debug-Modus aktiviert"
|
||||
else
|
||||
echo " ❌ .env Datei nicht gefunden"
|
||||
fi
|
||||
|
||||
# 2. Berechtigungen reparieren
|
||||
echo "2. 🔐 Berechtigungen reparieren..."
|
||||
chmod -R 755 storage/
|
||||
chmod -R 755 bootstrap/cache/
|
||||
chown -R www-data:www-data storage/
|
||||
chown -R www-data:www-data bootstrap/cache/
|
||||
echo " ✅ Berechtigungen repariert"
|
||||
|
||||
# 3. Cache leeren
|
||||
echo "3. 🧹 Cache leeren..."
|
||||
rm -f bootstrap/cache/*.php 2>/dev/null || echo " ⚠️ bootstrap/cache/*.php nicht gefunden"
|
||||
rm -f storage/framework/cache/* 2>/dev/null || echo " ⚠️ storage/framework/cache/* nicht gefunden"
|
||||
rm -f storage/framework/views/* 2>/dev/null || echo " ⚠️ storage/framework/views/* nicht gefunden"
|
||||
echo " ✅ Cache geleert"
|
||||
|
||||
# 4. Log-Dateien erstellen
|
||||
echo "4. 📝 Log-Dateien erstellen..."
|
||||
mkdir -p storage/logs/
|
||||
touch storage/logs/laravel.log
|
||||
chmod 666 storage/logs/laravel.log
|
||||
chown www-data:www-data storage/logs/laravel.log
|
||||
echo " ✅ Log-Dateien erstellt"
|
||||
|
||||
# 5. Debug-Script ausführen
|
||||
echo "5. 🔍 Debug-Script ausführen..."
|
||||
php debug-500-error.php
|
||||
|
||||
echo ""
|
||||
echo "✅ Quick Fix abgeschlossen!"
|
||||
echo ""
|
||||
echo "🔗 Testen Sie jetzt:"
|
||||
echo "1. https://neonail.vogt.de.com"
|
||||
echo "2. Falls Fehler bestehen, prüfen Sie die Debug-Ausgabe oben"
|
||||
echo "3. Schauen Sie in storage/logs/laravel.log für Details"
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔧 Schnelle Debug-Aktivierung"
|
||||
echo "============================"
|
||||
|
||||
# 1. Debug aktivieren
|
||||
echo "📝 Aktiviere Debug-Modus..."
|
||||
sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env
|
||||
echo "✅ APP_DEBUG=true gesetzt"
|
||||
|
||||
# 2. Cache leeren
|
||||
echo "🧹 Leere Laravel Cache..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
|
||||
# 3. Berechtigungen prüfen
|
||||
echo "🔐 Prüfe Berechtigungen..."
|
||||
chmod -R 777 storage/ 2>/dev/null
|
||||
chmod -R 777 bootstrap/cache/ 2>/dev/null
|
||||
|
||||
# 4. Test
|
||||
echo "🧪 Teste Anwendung..."
|
||||
curl -s http://192.168.30.81 | head -20
|
||||
|
||||
echo ""
|
||||
echo "✅ Debug aktiviert!"
|
||||
echo "📋 Öffnen Sie: http://192.168.30.81"
|
||||
echo "📋 Fehlermeldung wird jetzt angezeigt"
|
||||
@@ -1,68 +1,82 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Anmelden - NeoNail DB')
|
||||
@section('title', 'Anmelden – NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="d-flex align-items-center justify-content-center" style="min-height: 72vh;">
|
||||
<div style="width: 100%; max-width: 400px;">
|
||||
|
||||
{{-- Logo / Hero --}}
|
||||
<div class="text-center mb-5">
|
||||
<div style="width:72px; height:72px; background:rgba(255,255,255,0.13); border-radius:20px;
|
||||
display:inline-flex; align-items:center; justify-content:center; font-size:2.1rem;
|
||||
margin-bottom:16px; border:1px solid rgba(255,255,255,0.18);">
|
||||
💅
|
||||
</div>
|
||||
<h1 style="color:#fff; font-weight:800; font-size:1.8rem; letter-spacing:-0.04em; margin-bottom:5px;">
|
||||
NeoNail DB
|
||||
</h1>
|
||||
<p style="color:rgba(255,255,255,0.60); margin:0; font-size:0.92rem;">
|
||||
Melden Sie sich an, um Ihre Sammlung zu verwalten
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{{-- Card --}}
|
||||
<div class="card">
|
||||
<div class="card-body p-4">
|
||||
<div class="text-center mb-4">
|
||||
<i class="fas fa-palette fa-3x text-primary mb-3"></i>
|
||||
<h2 class="fw-bold">NeoNail DB</h2>
|
||||
<p class="text-muted">Anmelden um Ihre Sammlung zu verwalten</p>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="https://neonail.vogt.de.com/login">
|
||||
@if($errors->any())
|
||||
<div class="alert alert-danger mb-4">
|
||||
<i class="fas fa-exclamation-circle me-2"></i>
|
||||
{{ $errors->first() }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('login') }}">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">E-Mail-Adresse</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="fas fa-envelope"></i></span>
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror"
|
||||
name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
|
||||
</div>
|
||||
<input id="email" type="email"
|
||||
class="form-control @error('email') is-invalid @enderror"
|
||||
name="email" value="{{ old('email') }}"
|
||||
required autocomplete="email" autofocus
|
||||
placeholder="ihre@email.de">
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="mb-4">
|
||||
<label for="password" class="form-label">Passwort</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="fas fa-lock"></i></span>
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror"
|
||||
name="password" required autocomplete="current-password">
|
||||
</div>
|
||||
<input id="password" type="password"
|
||||
class="form-control @error('password') is-invalid @enderror"
|
||||
name="password" required autocomplete="current-password"
|
||||
placeholder="••••••••">
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="mb-4">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
|
||||
<label class="form-check-label" for="remember">
|
||||
<input class="form-check-input" type="checkbox" name="remember"
|
||||
id="remember" {{ old('remember') ? 'checked' : '' }}>
|
||||
<label class="form-check-label" for="remember"
|
||||
style="font-size:.85rem; color:#6b7280;">
|
||||
Angemeldet bleiben
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary btn-lg">
|
||||
<i class="fas fa-sign-in-alt me-2"></i>Anmelden
|
||||
</button>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100 btn-lg">
|
||||
<i class="fas fa-sign-in-alt me-2"></i>Anmelden
|
||||
</button>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@@ -4,148 +4,473 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>@yield("title", "NeoNail Datenbank")</title>
|
||||
<title>@yield('title', 'NeoNail DB')</title>
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary: #7c3aed;
|
||||
--primary-dark: #5b21b6;
|
||||
--accent: #ec4899;
|
||||
--accent-dark: #be185d;
|
||||
--t: .22s cubic-bezier(.4,0,.2,1);
|
||||
--r: 18px;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
html { scroll-behavior: smooth; }
|
||||
|
||||
body {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
font-family: 'Inter', sans-serif;
|
||||
background: linear-gradient(135deg, #2d1b69 0%, #6d28d9 45%, #9d174d 100%) fixed;
|
||||
min-height: 100vh;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* ─── Scrollbar ─── */
|
||||
::-webkit-scrollbar { width: 5px; }
|
||||
::-webkit-scrollbar-track { background: transparent; }
|
||||
::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.22); border-radius: 3px; }
|
||||
|
||||
/* ─── Navbar ─── */
|
||||
.navbar {
|
||||
background: rgba(255, 255, 255, 0.95) !important;
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(10, 5, 35, 0.82) !important;
|
||||
backdrop-filter: blur(24px);
|
||||
-webkit-backdrop-filter: blur(24px);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.09);
|
||||
padding: 10px 0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1030;
|
||||
}
|
||||
.navbar-brand {
|
||||
color: #fff !important;
|
||||
font-weight: 800;
|
||||
font-size: 1.1rem;
|
||||
letter-spacing: -0.03em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
}
|
||||
.brand-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: linear-gradient(135deg, var(--primary), var(--accent));
|
||||
border-radius: 9px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.nav-link {
|
||||
color: rgba(255,255,255,0.75) !important;
|
||||
font-weight: 500;
|
||||
font-size: 0.875rem;
|
||||
padding: 7px 13px !important;
|
||||
border-radius: 10px;
|
||||
transition: var(--t);
|
||||
}
|
||||
.nav-link:hover, .nav-link.active {
|
||||
color: #fff !important;
|
||||
background: rgba(255,255,255,0.11);
|
||||
}
|
||||
.dropdown-menu {
|
||||
background: rgba(12, 6, 38, 0.96);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255,255,255,0.11);
|
||||
border-radius: 14px;
|
||||
padding: 7px;
|
||||
box-shadow: 0 20px 48px rgba(0,0,0,0.45);
|
||||
min-width: 180px;
|
||||
}
|
||||
.dropdown-item {
|
||||
color: rgba(255,255,255,0.82) !important;
|
||||
border-radius: 9px;
|
||||
padding: 8px 13px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: var(--t);
|
||||
}
|
||||
.dropdown-item:hover {
|
||||
background: rgba(255,255,255,0.11);
|
||||
color: #fff !important;
|
||||
}
|
||||
.dropdown-item.text-danger { color: #f87171 !important; }
|
||||
.dropdown-item.text-danger:hover { background: rgba(248,113,113,0.12); }
|
||||
.navbar-toggler { border-color: rgba(255,255,255,0.28); }
|
||||
.navbar-toggler-icon { filter: invert(1); }
|
||||
.badge.bg-primary {
|
||||
background: linear-gradient(135deg, var(--primary), var(--accent)) !important;
|
||||
font-size: 0.68rem;
|
||||
padding: 3px 7px;
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
/* ─── Main ─── */
|
||||
main { padding: 28px 0 52px; }
|
||||
|
||||
/* ─── Cards ─── */
|
||||
.card {
|
||||
background: #fff;
|
||||
border: none;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: var(--r);
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.09);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||
border: none;
|
||||
border-radius: 25px;
|
||||
padding: 10px 25px;
|
||||
.card-header {
|
||||
background: transparent;
|
||||
border-bottom: 1px solid #f3f4f6;
|
||||
padding: 16px 20px;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.card-body { padding: 20px; }
|
||||
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(45deg, #5a6fd8, #6a4190);
|
||||
transform: translateY(-2px);
|
||||
/* ─── Nail-polish cards ─── */
|
||||
.np-card { transition: transform var(--t), box-shadow var(--t); }
|
||||
.np-card:hover {
|
||||
transform: translateY(-6px);
|
||||
box-shadow: 0 20px 50px rgba(0,0,0,0.18);
|
||||
}
|
||||
|
||||
.nail-polish-card {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.nail-polish-card:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.nail-polish-image {
|
||||
.np-img {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
display: block;
|
||||
}
|
||||
.np-placeholder {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background: linear-gradient(135deg, #6d28d9 0%, #9d174d 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: rgba(255,255,255,0.4);
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
.np-card .card-body { padding: 14px 16px; }
|
||||
.np-name {
|
||||
font-weight: 600;
|
||||
font-size: 0.92rem;
|
||||
color: #111827;
|
||||
line-height: 1.3;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.np-number {
|
||||
font-size: 0.76rem;
|
||||
color: #9ca3af;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
.np-brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
background: #f3f4f6;
|
||||
color: #6b7280;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
padding: 2px 8px;
|
||||
border-radius: 20px;
|
||||
margin-top: 7px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
border-radius: 25px;
|
||||
border: 2px solid #e9ecef;
|
||||
padding: 10px 20px;
|
||||
/* ─── Buttons ─── */
|
||||
.btn {
|
||||
font-weight: 600;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 50px;
|
||||
transition: var(--t);
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, var(--primary), var(--accent));
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
.btn-primary:hover, .btn-primary:focus {
|
||||
background: linear-gradient(135deg, var(--primary-dark), var(--accent-dark));
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 24px rgba(124,58,237,0.42);
|
||||
color: #fff;
|
||||
}
|
||||
.btn-success {
|
||||
background: linear-gradient(135deg, #059669, #0d9488);
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
.btn-success:hover, .btn-success:focus {
|
||||
background: linear-gradient(135deg, #047857, #0f766e);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 24px rgba(5,150,105,0.38);
|
||||
color: #fff;
|
||||
}
|
||||
/* Glass button — for use on gradient background */
|
||||
.btn-glass {
|
||||
border: 1.5px solid rgba(255,255,255,0.32);
|
||||
color: rgba(255,255,255,0.9);
|
||||
background: rgba(255,255,255,0.10);
|
||||
border-radius: 50px;
|
||||
font-weight: 600;
|
||||
font-size: 0.875rem;
|
||||
transition: var(--t);
|
||||
}
|
||||
.btn-glass:hover {
|
||||
background: rgba(255,255,255,0.20);
|
||||
border-color: rgba(255,255,255,0.50);
|
||||
color: #fff;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.btn-outline-secondary {
|
||||
border-radius: 50px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.btn-outline-danger { border-radius: 50px; }
|
||||
.btn-sm { padding: 6px 15px; font-size: 0.8rem; }
|
||||
.btn-lg { padding: 13px 28px; font-size: 1rem; }
|
||||
|
||||
/* ─── Page hero (text on gradient) ─── */
|
||||
.page-hero { margin-bottom: 24px; }
|
||||
.page-hero h1 {
|
||||
color: #fff;
|
||||
font-weight: 800;
|
||||
font-size: 1.85rem;
|
||||
letter-spacing: -0.035em;
|
||||
margin: 0 0 4px;
|
||||
}
|
||||
.page-hero p {
|
||||
color: rgba(255,255,255,0.62);
|
||||
margin: 0;
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
.count-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: rgba(255,255,255,0.13);
|
||||
backdrop-filter: blur(10px);
|
||||
color: #fff;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
padding: 6px 14px;
|
||||
border-radius: 50px;
|
||||
border: 1px solid rgba(255,255,255,0.18);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.search-box:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
|
||||
/* ─── Search ─── */
|
||||
.search-wrap { position: relative; }
|
||||
.search-icon {
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: rgba(255,255,255,0.5);
|
||||
pointer-events: none;
|
||||
font-size: 0.85rem;
|
||||
z-index: 1;
|
||||
}
|
||||
.search-input {
|
||||
background: rgba(255,255,255,0.12) !important;
|
||||
border: 1.5px solid rgba(255,255,255,0.22) !important;
|
||||
border-radius: 50px !important;
|
||||
color: #fff !important;
|
||||
padding: 11px 96px 11px 40px !important;
|
||||
font-size: 0.9rem;
|
||||
transition: var(--t);
|
||||
height: auto;
|
||||
}
|
||||
.search-input::placeholder { color: rgba(255,255,255,0.45) !important; }
|
||||
.search-input:focus {
|
||||
background: rgba(255,255,255,0.18) !important;
|
||||
border-color: rgba(255,255,255,0.50) !important;
|
||||
box-shadow: 0 0 0 4px rgba(255,255,255,0.07) !important;
|
||||
color: #fff !important;
|
||||
outline: none;
|
||||
}
|
||||
.search-submit {
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: rgba(255,255,255,0.18);
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
color: #fff;
|
||||
padding: 5px 14px;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: var(--t);
|
||||
}
|
||||
.search-submit:hover { background: rgba(255,255,255,0.28); }
|
||||
.search-clear {
|
||||
position: absolute;
|
||||
right: 70px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: rgba(255,255,255,0.5);
|
||||
font-size: 0.8rem;
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
padding: 4px 6px;
|
||||
border-radius: 50%;
|
||||
transition: var(--t);
|
||||
}
|
||||
.search-clear:hover { color: #fff; background: rgba(255,255,255,0.12); }
|
||||
|
||||
/* ─── Alerts ─── */
|
||||
.alert {
|
||||
border: none;
|
||||
border-radius: 13px;
|
||||
padding: 13px 16px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
background: rgba(255,255,255,0.97);
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
.alert-success {
|
||||
color: #065f46;
|
||||
border-left: 4px solid #059669;
|
||||
}
|
||||
.alert-danger {
|
||||
color: #7f1d1d;
|
||||
border-left: 4px solid #dc2626;
|
||||
}
|
||||
.alert-warning {
|
||||
color: #78350f;
|
||||
border-left: 4px solid #d97706;
|
||||
}
|
||||
.alert-info {
|
||||
color: #1e3a8a;
|
||||
border-left: 4px solid #2563eb;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
/* ─── Empty state ─── */
|
||||
.empty-state { text-align: center; padding: 56px 20px; }
|
||||
.empty-icon {
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
background: rgba(255,255,255,0.12);
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 2.2rem;
|
||||
color: rgba(255,255,255,0.55);
|
||||
margin-bottom: 18px;
|
||||
border: 1px solid rgba(255,255,255,0.18);
|
||||
}
|
||||
.empty-state h4 { color: #fff; font-weight: 700; font-size: 1.25rem; margin-bottom: 7px; }
|
||||
.empty-state p { color: rgba(255,255,255,0.60); margin-bottom: 22px; font-size: 0.92rem; }
|
||||
|
||||
.card {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
/* ─── Pagination ─── */
|
||||
.pagination { gap: 4px; }
|
||||
.pagination .page-link {
|
||||
background: rgba(255,255,255,0.12);
|
||||
border: 1px solid rgba(255,255,255,0.18);
|
||||
color: rgba(255,255,255,0.85);
|
||||
border-radius: 10px !important;
|
||||
padding: 7px 13px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
transition: var(--t);
|
||||
}
|
||||
.pagination .page-link:hover { background: rgba(255,255,255,0.22); color: #fff; }
|
||||
.pagination .page-item.active .page-link {
|
||||
background: linear-gradient(135deg, var(--primary), var(--accent));
|
||||
border-color: transparent;
|
||||
color: #fff;
|
||||
}
|
||||
.pagination .page-item.disabled .page-link {
|
||||
background: rgba(255,255,255,0.05);
|
||||
color: rgba(255,255,255,0.28);
|
||||
}
|
||||
|
||||
/* Dropdown-Menüs über alle anderen Elemente legen */
|
||||
.dropdown-menu {
|
||||
z-index: 9999 !important;
|
||||
position: absolute !important;
|
||||
/* ─── Form controls (inside white cards) ─── */
|
||||
.form-label { font-weight: 600; font-size: 0.85rem; color: #374151; margin-bottom: 5px; }
|
||||
.form-control, .form-select {
|
||||
border: 1.5px solid #e5e7eb;
|
||||
border-radius: 11px;
|
||||
padding: 9px 13px;
|
||||
font-size: 0.9rem;
|
||||
transition: var(--t);
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
/* Navbar hat höheren z-index */
|
||||
.navbar {
|
||||
z-index: 1000 !important;
|
||||
position: relative;
|
||||
.form-control:focus, .form-select:focus {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 3px rgba(124,58,237,0.12);
|
||||
}
|
||||
.form-text { font-size: 0.78rem; color: #9ca3af; }
|
||||
|
||||
/* Dropdown-Container */
|
||||
.dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Sicherstellen, dass Dropdowns über Cards angezeigt werden */
|
||||
.navbar-nav .dropdown-menu {
|
||||
z-index: 9999 !important;
|
||||
position: absolute !important;
|
||||
top: 100% !important;
|
||||
left: 0 !important;
|
||||
float: none !important;
|
||||
/* ─── Mobile ─── */
|
||||
@media (max-width: 767px) {
|
||||
main { padding: 18px 0 40px; }
|
||||
.page-hero h1 { font-size: 1.45rem; }
|
||||
.page-hero { margin-bottom: 18px; }
|
||||
.np-img, .np-placeholder { height: 160px; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@yield("styles")
|
||||
@yield('styles')
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container">
|
||||
<a class="navbar-brand fw-bold" href="{{ route("user-nail-polishes.index") }}">
|
||||
<i class="fas fa-palette me-2"></i>NeoNail DB
|
||||
<a class="navbar-brand" href="{{ route('user-nail-polishes.index') }}">
|
||||
<span class="brand-icon">💅</span>
|
||||
NeoNail DB
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarNav" aria-label="Navigation öffnen">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto">
|
||||
<ul class="navbar-nav me-auto gap-1">
|
||||
@auth
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("user-nail-polishes.index") }}">
|
||||
<a class="nav-link {{ request()->routeIs('user-nail-polishes.index') ? 'active' : '' }}"
|
||||
href="{{ route('user-nail-polishes.index') }}">
|
||||
<i class="fas fa-home me-1"></i>Meine Sammlung
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("user-nail-polishes.available") }}">
|
||||
<a class="nav-link {{ request()->routeIs('user-nail-polishes.available') ? 'active' : '' }}"
|
||||
href="{{ route('user-nail-polishes.available') }}">
|
||||
<i class="fas fa-plus me-1"></i>Verfügbare Lacke
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("manufacturers.index") }}">
|
||||
<a class="nav-link {{ request()->routeIs('manufacturers.*') ? 'active' : '' }}"
|
||||
href="{{ route('manufacturers.index') }}">
|
||||
<i class="fas fa-industry me-1"></i>Hersteller
|
||||
</a>
|
||||
</li>
|
||||
@if(auth()->user()->isAdmin())
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-cog me-1"></i>Admin
|
||||
<a class="nav-link dropdown-toggle {{ request()->routeIs('admin.*') || request()->routeIs('nail-polishes.*') ? 'active' : '' }}"
|
||||
href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-shield-alt me-1"></i>Admin
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="{{ route("admin.dashboard") }}">Dashboard</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("admin.users.index") }}">Benutzer</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("nail-polishes.index") }}">Nagellacke</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route("admin.statistics") }}">Statistiken</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route('admin.dashboard') }}">
|
||||
<i class="fas fa-chart-line me-2"></i>Dashboard</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route('admin.users.index') }}">
|
||||
<i class="fas fa-users me-2"></i>Benutzer</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route('nail-polishes.index') }}">
|
||||
<i class="fas fa-palette me-2"></i>Nagellacke</a></li>
|
||||
<li><a class="dropdown-item" href="{{ route('admin.statistics') }}">
|
||||
<i class="fas fa-chart-bar me-2"></i>Statistiken</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@endif
|
||||
@@ -155,23 +480,23 @@
|
||||
<ul class="navbar-nav">
|
||||
@guest
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route("login") }}">Anmelden</a>
|
||||
<a class="nav-link" href="{{ route('login') }}">Anmelden</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="fas fa-user me-1"></i>{{ Auth::user()->name }}
|
||||
<i class="fas fa-user-circle me-1"></i>{{ Auth::user()->name }}
|
||||
@if(auth()->user()->isAdmin())
|
||||
<span class="badge bg-primary ms-1">Admin</span>
|
||||
@endif
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route("logout") }}"
|
||||
onclick="event.preventDefault(); document.getElementById("logout-form").submit();">
|
||||
<i class="fas fa-sign-out-alt me-1"></i>Abmelden
|
||||
<a class="dropdown-item text-danger" href="{{ route('logout') }}"
|
||||
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
||||
<i class="fas fa-sign-out-alt me-2"></i>Abmelden
|
||||
</a>
|
||||
<form id="logout-form" action="{{ route("logout") }}" method="POST" class="d-none">
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
|
||||
@csrf
|
||||
</form>
|
||||
</li>
|
||||
@@ -183,46 +508,25 @@
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="py-4">
|
||||
<main>
|
||||
<div class="container">
|
||||
@if(session("success"))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-check-circle me-2"></i>{{ session("success") }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
@foreach(['success' => 'alert-success', 'error' => 'alert-danger', 'warning' => 'alert-warning'] as $key => $cls)
|
||||
@if(session($key))
|
||||
<div class="alert {{ $cls }} alert-dismissible fade show mb-4" role="alert">
|
||||
@if($key === 'success')<i class="fas fa-check-circle me-2"></i>
|
||||
@elseif($key === 'error')<i class="fas fa-exclamation-circle me-2"></i>
|
||||
@else<i class="fas fa-exclamation-triangle me-2"></i>@endif
|
||||
{{ session($key) }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
@if(session("error"))
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="fas fa-exclamation-circle me-2"></i>{{ session("error") }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@yield("content")
|
||||
@yield('content')
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<!-- HTTPS Form Security -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Alle Formulare mit data-https="true" auf HTTPS umleiten
|
||||
const forms = document.querySelectorAll('form[data-https="true"]');
|
||||
forms.forEach(function(form) {
|
||||
form.addEventListener('submit', function(e) {
|
||||
const currentUrl = window.location.href;
|
||||
if (currentUrl.startsWith('http://')) {
|
||||
const httpsUrl = currentUrl.replace('http://', 'https://');
|
||||
form.action = form.action.replace('http://', 'https://');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@yield("scripts")
|
||||
@yield('scripts')
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,124 +1,112 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Verfügbare Lacke - NeoNail DB')
|
||||
@section('title', 'Verfügbare Lacke – NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h2>
|
||||
<i class="fas fa-search me-2"></i>Verfügbare NeoNail-Lacke
|
||||
</h2>
|
||||
<p class="text-muted">Lacke, die Sie noch nicht in Ihrer Sammlung haben</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-end">
|
||||
<div class="d-flex gap-2 justify-content-end">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Lack hinzufügen
|
||||
|
||||
{{-- Page Hero --}}
|
||||
<div class="page-hero d-flex flex-column flex-md-row align-items-md-center justify-content-md-between gap-3">
|
||||
<div>
|
||||
<h1><i class="fas fa-search me-2" style="font-size:1.5rem;vertical-align:middle;opacity:.9;"></i>Verfügbare Lacke</h1>
|
||||
<p>Lacke aus dem Katalog, die noch nicht in Ihrer Sammlung sind</p>
|
||||
</div>
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Lack
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="btn btn-glass">
|
||||
<i class="fas fa-palette me-2"></i>Meine Sammlung
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Search + Count --}}
|
||||
<div class="d-flex align-items-center gap-3 mb-4">
|
||||
<div class="search-wrap flex-grow-1">
|
||||
<form method="GET" action="{{ route('user-nail-polishes.available') }}">
|
||||
<i class="fas fa-search search-icon"></i>
|
||||
<input type="text" name="search" class="form-control search-input"
|
||||
placeholder="Nach Name oder Nummer suchen…"
|
||||
value="{{ $search }}" autocomplete="off">
|
||||
@if($search)
|
||||
<a href="{{ route('user-nail-polishes.available') }}" class="search-clear" title="Zurücksetzen">
|
||||
<i class="fas fa-times"></i>
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="btn btn-primary">
|
||||
<i class="fas fa-palette me-2"></i>Meine Sammlung
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<button type="submit" class="search-submit">Suchen</button>
|
||||
</form>
|
||||
</div>
|
||||
<span class="count-chip">
|
||||
<i class="fas fa-boxes"></i>
|
||||
{{ $nailPolishes->total() }} verfügbar
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Info-Box -->
|
||||
<div class="alert alert-info mb-4">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<strong>Hinweis:</strong> Diese Lacke sind Teil des gemeinsamen Hauptkatalogs und können nicht gelöscht werden.
|
||||
Sie können sie nur zu Ihrer persönlichen Sammlung hinzufügen oder entfernen.
|
||||
</div>
|
||||
{{-- Grid --}}
|
||||
@if($nailPolishes->count() > 0)
|
||||
<div class="row g-3">
|
||||
@foreach($nailPolishes as $nailPolish)
|
||||
<div class="col-6 col-md-4 col-lg-3">
|
||||
<div class="card np-card h-100">
|
||||
@if($nailPolish->image_path)
|
||||
<img src="{{ Storage::url($nailPolish->image_path) }}"
|
||||
class="np-img" alt="{{ $nailPolish->name }}" loading="lazy">
|
||||
@else
|
||||
<div class="np-placeholder">
|
||||
<i class="fas fa-palette"></i>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Suchleiste -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<form method="GET" action="{{ route('user-nail-polishes.available') }}" class="d-flex">
|
||||
<input type="text" name="search" class="form-control me-2"
|
||||
placeholder="Nach Name oder Nummer suchen..."
|
||||
value="{{ $search }}">
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
@if($search)
|
||||
<a href="{{ route('user-nail-polishes.available') }}" class="btn btn-outline-secondary ms-2">
|
||||
<i class="fas fa-times"></i>
|
||||
</a>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<span class="text-muted">
|
||||
{{ $nailPolishes->total() }} verfügbare Lack{{ $nailPolishes->total() != 1 ? 'e' : '' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($nailPolishes->count() > 0)
|
||||
<div class="row">
|
||||
@foreach($nailPolishes as $nailPolish)
|
||||
<div class="col-md-3 col-sm-6 mb-4">
|
||||
<div class="card h-100 nail-polish-card">
|
||||
@if($nailPolish->image_path)
|
||||
<img src="{{ Storage::url($nailPolish->image_path) }}"
|
||||
class="card-img-top nail-polish-image"
|
||||
alt="{{ $nailPolish->name }}"
|
||||
loading="lazy">
|
||||
@else
|
||||
<div class="card-img-top nail-polish-placeholder d-flex align-items-center justify-content-center">
|
||||
<i class="fas fa-palette fa-3x text-muted"></i>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h6 class="card-title mb-1">{{ $nailPolish->name }}</h6>
|
||||
<p class="card-text text-muted mb-2">Nr. {{ $nailPolish->number }}</p>
|
||||
|
||||
<div class="mt-auto">
|
||||
<form method="POST" action="{{ route('user-nail-polishes.add', $nailPolish) }}"
|
||||
class="d-inline">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-success btn-sm w-100">
|
||||
<i class="fas fa-plus me-2"></i>Zur Sammlung hinzufügen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<div class="flex-grow-1">
|
||||
<div class="np-name">{{ $nailPolish->name }}</div>
|
||||
<div class="np-number">Nr. {{ $nailPolish->number }}</div>
|
||||
@if($nailPolish->manufacturer)
|
||||
<span class="np-brand">{{ $nailPolish->manufacturer->name }}</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<form method="POST" action="{{ route('user-nail-polishes.add', $nailPolish) }}">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-success btn-sm w-100">
|
||||
<i class="fas fa-plus me-1"></i>Zur Sammlung
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
@if($nailPolishes->hasPages())
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<nav aria-label="Seitennavigation">
|
||||
{{ $nailPolishes->appends(['search' => $search])->links() }}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="text-center py-5">
|
||||
<i class="fas fa-check-circle fa-4x text-success mb-3"></i>
|
||||
<h4 class="text-success">Glückwunsch!</h4>
|
||||
<p class="text-muted mb-4">
|
||||
@if($search)
|
||||
Keine verfügbaren Lacke gefunden, die "{{ $search }}" entsprechen.
|
||||
@else
|
||||
Sie haben bereits alle verfügbaren NeoNail-Lacke in Ihrer Sammlung!
|
||||
@endif
|
||||
</p>
|
||||
<div class="d-flex gap-2 justify-content-center">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Lack hinzufügen
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="btn btn-primary">
|
||||
<i class="fas fa-palette me-2"></i>Meine Sammlung anzeigen
|
||||
</a>
|
||||
</div>
|
||||
@if($nailPolishes->hasPages())
|
||||
<div class="d-flex justify-content-center mt-5">
|
||||
{{ $nailPolishes->appends(['search' => $search])->links() }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@else
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
</div>
|
||||
<h4>{{ $search ? 'Keine Ergebnisse' : 'Alles in Ihrer Sammlung!' }}</h4>
|
||||
<p>
|
||||
@if($search)
|
||||
Keine Lacke gefunden, die „{{ $search }}" entsprechen.
|
||||
@else
|
||||
Sie haben bereits alle verfügbaren Lacke in Ihrer Sammlung.
|
||||
@endif
|
||||
</p>
|
||||
<div class="d-flex gap-2 justify-content-center flex-wrap">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Lack hinzufügen
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="btn btn-glass">
|
||||
<i class="fas fa-palette me-2"></i>Meine Sammlung
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endsection
|
||||
|
||||
@@ -1,175 +1,232 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Neuen Lack hinzufügen - NeoNail DB')
|
||||
@section('title', 'Neuen Lack hinzufügen – NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0">
|
||||
<i class="fas fa-plus me-2"></i>Neuen NeoNail-Lack hinzufügen
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
<strong>Wichtig:</strong> Der neue Lack wird automatisch zum Hauptkatalog hinzugefügt und steht dann allen Benutzern zur Verfügung.
|
||||
Er wird auch automatisch zu Ihrer Sammlung hinzugefügt.
|
||||
</div>
|
||||
<div class="col-md-8 col-lg-7">
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
@foreach ($errors->all() as $error)
|
||||
<div class="page-hero mb-4">
|
||||
<h1><i class="fas fa-plus me-2" style="font-size:1.4rem;vertical-align:middle;opacity:.9;"></i>Neuen Lack hinzufügen</h1>
|
||||
<p>Der Lack wird zum Katalog hinzugefügt und automatisch in Ihre Sammlung aufgenommen.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body p-4">
|
||||
|
||||
@if($errors->any())
|
||||
<div class="alert alert-danger mb-4">
|
||||
<i class="fas fa-exclamation-circle me-2"></i>
|
||||
<strong>Bitte korrigieren Sie folgende Fehler:</strong>
|
||||
<ul class="mb-0 mt-2 ps-3">
|
||||
@foreach($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="https://neonail.vogt.de.com/create-nail-polish" enctype="multipart/form-data">
|
||||
<form method="POST" action="{{ route('user-nail-polishes.store') }}" enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name des Lackes *</label>
|
||||
<input type="text" class="form-control @error('name') is-invalid @enderror"
|
||||
id="name" name="name" value="{{ old('name') }}"
|
||||
placeholder="z.B. Classic Red" required>
|
||||
@error('name')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-7">
|
||||
<label for="name" class="form-label">Name des Lackes *</label>
|
||||
<input type="text" class="form-control @error('name') is-invalid @enderror"
|
||||
id="name" name="name" value="{{ old('name') }}"
|
||||
placeholder="z.B. Classic Red" required>
|
||||
@error('name')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="number" class="form-label">Nummer des Lackes *</label>
|
||||
<input type="text" class="form-control @error('number') is-invalid @enderror"
|
||||
id="number" name="number" value="{{ old('number') }}"
|
||||
placeholder="z.B. 001" required>
|
||||
@error('number')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label for="number" class="form-label">Nummer *</label>
|
||||
<input type="text" class="form-control @error('number') is-invalid @enderror"
|
||||
id="number" name="number" value="{{ old('number') }}"
|
||||
placeholder="z.B. 001" required>
|
||||
@error('number')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="manufacturer_id" class="form-label">Hersteller *</label>
|
||||
<select class="form-control @error('manufacturer_id') is-invalid @enderror"
|
||||
id="manufacturer_id" name="manufacturer_id" required>
|
||||
<option value="">Hersteller auswählen...</option>
|
||||
@foreach(\App\Models\Manufacturer::orderBy('name')->get() as $manufacturer)
|
||||
<option value="{{ $manufacturer->id }}" {{ old('manufacturer_id') == $manufacturer->id ? 'selected' : '' }}>
|
||||
{{ $manufacturer->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('manufacturer_id')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
<div class="form-text">
|
||||
<a href="https://neonail.vogt.de.com/manufacturers/create" target="_blank" class="text-decoration-none">
|
||||
<i class="fas fa-plus"></i> Neuen Hersteller erstellen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<label for="manufacturer_id" class="form-label">Hersteller auswählen</label>
|
||||
<select class="form-select @error('manufacturer_id') is-invalid @enderror"
|
||||
id="manufacturer_id" name="manufacturer_id">
|
||||
<option value="">— Hersteller wählen —</option>
|
||||
@foreach(\App\Models\Manufacturer::orderBy('name')->get() as $m)
|
||||
<option value="{{ $m->id }}" {{ old('manufacturer_id') == $m->id ? 'selected' : '' }}>
|
||||
{{ $m->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('manufacturer_id')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="new_manufacturer" class="form-label">Oder neuen Hersteller erstellen</label>
|
||||
<input type="text" class="form-control"
|
||||
id="new_manufacturer" name="new_manufacturer"
|
||||
placeholder="Name des neuen Herstellers">
|
||||
<div class="form-text">
|
||||
Falls der Hersteller noch nicht existiert, können Sie ihn hier erstellen.
|
||||
</div>
|
||||
</div>
|
||||
<label for="new_manufacturer" class="form-label">Oder neuen Hersteller anlegen</label>
|
||||
<input type="text" class="form-control @error('new_manufacturer') is-invalid @enderror"
|
||||
id="new_manufacturer" name="new_manufacturer"
|
||||
value="{{ old('new_manufacturer') }}"
|
||||
placeholder="Name des neuen Herstellers">
|
||||
@error('new_manufacturer')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
<div class="form-text">Wird automatisch angelegt, falls noch nicht vorhanden.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="image" class="form-label">Bild des Lackes (optional)</label>
|
||||
<input type="file" class="form-control @error('image') is-invalid @enderror"
|
||||
id="image" name="image" accept="image/*">
|
||||
<div class="form-text">
|
||||
<i class="fas fa-camera me-1"></i>
|
||||
Sie können ein Bild mit der Handykamera aufnehmen oder eine Datei auswählen.
|
||||
Maximale Größe: 10MB. Das Bild wird automatisch optimiert.
|
||||
{{-- Image Upload --}}
|
||||
<div class="mb-4">
|
||||
<label class="form-label">Foto (optional)</label>
|
||||
|
||||
{{-- Tab-Umschalter --}}
|
||||
<div class="d-flex gap-2 mb-3">
|
||||
<button type="button" id="tab-file" onclick="switchTab('file')"
|
||||
style="padding:6px 16px; border-radius:50px; font-size:.82rem; font-weight:600; cursor:pointer; transition:.18s;
|
||||
background:#7c3aed; color:#fff; border:none;">
|
||||
<i class="fas fa-upload me-1"></i>Datei
|
||||
</button>
|
||||
<button type="button" id="tab-url" onclick="switchTab('url')"
|
||||
style="padding:6px 16px; border-radius:50px; font-size:.82rem; font-weight:600; cursor:pointer; transition:.18s;
|
||||
background:#f3f4f6; color:#6b7280; border:none;">
|
||||
<i class="fas fa-link me-1"></i>URL
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{-- Panel: Datei --}}
|
||||
<div id="panel-file">
|
||||
<div id="drop-zone"
|
||||
style="border: 2px dashed #e5e7eb; border-radius: 13px; padding: 28px 20px; text-align: center; cursor: pointer; transition: border-color .2s, background .2s;"
|
||||
onclick="document.getElementById('image').click()"
|
||||
ondragover="event.preventDefault(); this.style.borderColor='#7c3aed'; this.style.background='#f5f3ff';"
|
||||
ondragleave="this.style.borderColor='#e5e7eb'; this.style.background='';"
|
||||
ondrop="handleDrop(event)">
|
||||
<div id="preview-wrap" class="d-none mb-3">
|
||||
<img id="preview-img" src="" alt="Vorschau"
|
||||
style="max-height:160px; border-radius:10px; object-fit:cover;">
|
||||
</div>
|
||||
<div id="drop-label">
|
||||
<i class="fas fa-camera fa-2x mb-2 d-block" style="color:#d1d5db;"></i>
|
||||
<span style="font-size:.88rem; font-weight:600; color:#6b7280;">Klicken oder Foto aufnehmen</span><br>
|
||||
<span style="font-size:.76rem; color:#9ca3af;">JPG, PNG, GIF · Max. 10 MB</span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="file" class="d-none @error('image') is-invalid @enderror"
|
||||
id="image" name="image" accept="image/*">
|
||||
@error('image')<div class="invalid-feedback d-block mt-1">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
|
||||
{{-- Panel: URL --}}
|
||||
<div id="panel-url" style="display:none;">
|
||||
<input type="url" id="image_url" name="image_url"
|
||||
class="form-control @error('image_url') is-invalid @enderror"
|
||||
placeholder="https://example.com/bild.jpg"
|
||||
value="{{ old('image_url') }}"
|
||||
oninput="previewUrl(this.value)">
|
||||
@error('image_url')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
<div class="form-text mb-2">Das Bild wird vom Server heruntergeladen und lokal gespeichert.</div>
|
||||
<div id="url-preview-wrap" style="display:none; margin-top:10px;">
|
||||
<img id="url-preview-img" src="" alt="Vorschau"
|
||||
style="max-height:160px; border-radius:10px; object-fit:cover; border:2px solid #e5e7eb;"
|
||||
onerror="this.parentElement.style.display='none'">
|
||||
</div>
|
||||
</div>
|
||||
@error('image')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary flex-fill">
|
||||
<i class="fas fa-save me-2"></i>Lack erstellen & zur Sammlung hinzufügen
|
||||
<i class="fas fa-plus me-2"></i>Lack erstellen & hinzufügen
|
||||
</button>
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-times me-2"></i>Abbrechen
|
||||
Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hinweise -->
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">
|
||||
<i class="fas fa-lightbulb me-2"></i>Hinweise
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="mb-0">
|
||||
<li>Der Lack wird automatisch zum Hauptkatalog hinzugefügt</li>
|
||||
<li>Andere Benutzer können den Lack dann zu ihrer Sammlung hinzufügen</li>
|
||||
<li>Das Bild wird automatisch auf 400x400 Pixel optimiert</li>
|
||||
<li>Sie können den Lack später in Ihren Einstellungen bearbeiten</li>
|
||||
<li>Neue Hersteller werden automatisch erstellt und stehen allen zur Verfügung</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const manufacturerSelect = document.getElementById('manufacturer_id');
|
||||
const newManufacturerInput = document.getElementById('new_manufacturer');
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const mSel = document.getElementById('manufacturer_id');
|
||||
const mNew = document.getElementById('new_manufacturer');
|
||||
const img = document.getElementById('image');
|
||||
const prev = document.getElementById('preview-img');
|
||||
const wrap = document.getElementById('preview-wrap');
|
||||
const lbl = document.getElementById('drop-label');
|
||||
const zone = document.getElementById('drop-zone');
|
||||
|
||||
// Wenn ein Hersteller ausgewählt wird, leere das neue Hersteller Feld
|
||||
manufacturerSelect.addEventListener('change', function() {
|
||||
if (this.value) {
|
||||
newManufacturerInput.value = '';
|
||||
newManufacturerInput.disabled = true;
|
||||
} else {
|
||||
newManufacturerInput.disabled = false;
|
||||
}
|
||||
// Hersteller-Toggle
|
||||
mSel.addEventListener('change', () => {
|
||||
if (mSel.value) { mNew.value = ''; mNew.disabled = true; }
|
||||
else mNew.disabled = false;
|
||||
});
|
||||
|
||||
// Wenn ein neuer Hersteller eingegeben wird, leere die Auswahl
|
||||
newManufacturerInput.addEventListener('input', function() {
|
||||
if (this.value.trim()) {
|
||||
manufacturerSelect.value = '';
|
||||
manufacturerSelect.disabled = true;
|
||||
} else {
|
||||
manufacturerSelect.disabled = false;
|
||||
}
|
||||
mNew.addEventListener('input', () => {
|
||||
if (mNew.value.trim()) { mSel.value = ''; mSel.disabled = true; }
|
||||
else mSel.disabled = false;
|
||||
});
|
||||
if (mNew.value.trim()) mSel.disabled = true;
|
||||
if (mSel.value) mNew.disabled = true;
|
||||
|
||||
// Initial state
|
||||
if (newManufacturerInput.value.trim()) {
|
||||
manufacturerSelect.disabled = true;
|
||||
}
|
||||
if (manufacturerSelect.value) {
|
||||
newManufacturerInput.disabled = true;
|
||||
// Datei-Vorschau
|
||||
function showFilePreview(file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = e => {
|
||||
prev.src = e.target.result;
|
||||
wrap.classList.remove('d-none');
|
||||
lbl.style.display = 'none';
|
||||
zone.style.borderColor = '#7c3aed';
|
||||
zone.style.background = '#f5f3ff';
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
img.addEventListener('change', function () {
|
||||
if (this.files && this.files[0]) showFilePreview(this.files[0]);
|
||||
});
|
||||
window.handleDrop = function (e) {
|
||||
e.preventDefault();
|
||||
zone.style.borderColor = '#e5e7eb';
|
||||
zone.style.background = '';
|
||||
if (e.dataTransfer.files.length) {
|
||||
const dt = new DataTransfer();
|
||||
dt.items.add(e.dataTransfer.files[0]);
|
||||
img.files = dt.files;
|
||||
showFilePreview(e.dataTransfer.files[0]);
|
||||
}
|
||||
};
|
||||
|
||||
// Tab-Umschalter
|
||||
window.switchTab = function (tab) {
|
||||
const isFile = tab === 'file';
|
||||
document.getElementById('panel-file').style.display = isFile ? '' : 'none';
|
||||
document.getElementById('panel-url').style.display = isFile ? 'none' : '';
|
||||
document.getElementById('tab-file').style.background = isFile ? '#7c3aed' : '#f3f4f6';
|
||||
document.getElementById('tab-file').style.color = isFile ? '#fff' : '#6b7280';
|
||||
document.getElementById('tab-url').style.background = isFile ? '#f3f4f6' : '#7c3aed';
|
||||
document.getElementById('tab-url').style.color = isFile ? '#6b7280' : '#fff';
|
||||
// Felder des inaktiven Tabs leeren
|
||||
if (isFile) { document.getElementById('image_url').value = ''; document.getElementById('url-preview-wrap').style.display = 'none'; }
|
||||
else { img.value = ''; wrap.classList.add('d-none'); lbl.style.display = ''; zone.style.borderColor = '#e5e7eb'; zone.style.background = ''; }
|
||||
};
|
||||
|
||||
// URL-Vorschau
|
||||
let urlTimer;
|
||||
window.previewUrl = function (val) {
|
||||
clearTimeout(urlTimer);
|
||||
const pw = document.getElementById('url-preview-wrap');
|
||||
const pi = document.getElementById('url-preview-img');
|
||||
if (!val.trim()) { pw.style.display = 'none'; return; }
|
||||
urlTimer = setTimeout(() => {
|
||||
pi.src = val;
|
||||
pw.style.display = '';
|
||||
}, 600);
|
||||
};
|
||||
|
||||
// Ggf. URL-Tab vorauswählen bei Validation-Fehler
|
||||
@if(old('image_url'))
|
||||
switchTab('url');
|
||||
previewUrl('{{ old('image_url') }}');
|
||||
@endif
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
||||
@@ -1,123 +1,113 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Meine Sammlung - NeoNail DB')
|
||||
@section('title', 'Meine Sammlung – NeoNail DB')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h2>
|
||||
<i class="fas fa-palette me-2"></i>Meine NeoNail-Sammlung
|
||||
</h2>
|
||||
<p class="text-muted">Verwalten Sie Ihre persönliche Nagellack-Sammlung</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-end">
|
||||
<div class="d-flex gap-2 justify-content-end">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Lack hinzufügen
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.available') }}" class="btn btn-primary">
|
||||
<i class="fas fa-search me-2"></i>Verfügbare Lacke
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Page Hero --}}
|
||||
<div class="page-hero d-flex flex-column flex-md-row align-items-md-center justify-content-md-between gap-3">
|
||||
<div>
|
||||
<h1>💅 Meine Sammlung</h1>
|
||||
<p>Verwalten Sie Ihre persönliche Nagellack-Sammlung</p>
|
||||
</div>
|
||||
|
||||
<!-- Suchleiste -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<form method="GET" action="{{ route('user-nail-polishes.index') }}" class="d-flex">
|
||||
<input type="text" name="search" class="form-control me-2"
|
||||
placeholder="Nach Name oder Nummer suchen..."
|
||||
value="{{ $search }}">
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
@if($search)
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="btn btn-outline-secondary ms-2">
|
||||
<i class="fas fa-times"></i>
|
||||
</a>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<span class="text-muted">
|
||||
{{ $nailPolishes->total() }} Lack{{ $nailPolishes->total() != 1 ? 'e' : '' }} in Ihrer Sammlung
|
||||
</span>
|
||||
</div>
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Neuen Lack
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.available') }}" class="btn btn-glass">
|
||||
<i class="fas fa-search me-2"></i>Verfügbare Lacke
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($nailPolishes->count() > 0)
|
||||
<div class="row">
|
||||
@foreach($nailPolishes as $nailPolish)
|
||||
<div class="col-md-3 col-sm-6 mb-4">
|
||||
<div class="card h-100 nail-polish-card">
|
||||
@if($nailPolish->image_path)
|
||||
<img src="{{ Storage::url($nailPolish->image_path) }}"
|
||||
class="card-img-top nail-polish-image"
|
||||
alt="{{ $nailPolish->name }}"
|
||||
loading="lazy">
|
||||
@else
|
||||
<div class="card-img-top nail-polish-placeholder d-flex align-items-center justify-content-center">
|
||||
<i class="fas fa-palette fa-3x text-muted"></i>
|
||||
</div>
|
||||
@endif
|
||||
{{-- Search + Count --}}
|
||||
<div class="d-flex align-items-center gap-3 mb-4">
|
||||
<div class="search-wrap flex-grow-1">
|
||||
<form method="GET" action="{{ route('user-nail-polishes.index') }}">
|
||||
<i class="fas fa-search search-icon"></i>
|
||||
<input type="text" name="search" class="form-control search-input"
|
||||
placeholder="Nach Name oder Nummer suchen…"
|
||||
value="{{ $search }}" autocomplete="off">
|
||||
@if($search)
|
||||
<a href="{{ route('user-nail-polishes.index') }}" class="search-clear" title="Zurücksetzen">
|
||||
<i class="fas fa-times"></i>
|
||||
</a>
|
||||
@endif
|
||||
<button type="submit" class="search-submit">Suchen</button>
|
||||
</form>
|
||||
</div>
|
||||
<span class="count-chip">
|
||||
<i class="fas fa-layer-group"></i>
|
||||
{{ $nailPolishes->total() }} {{ $nailPolishes->total() === 1 ? 'Lack' : 'Lacke' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h6 class="card-title mb-1">{{ $nailPolish->name }}</h6>
|
||||
<p class="card-text text-muted mb-2">Nr. {{ $nailPolish->number }}</p>
|
||||
{{-- Grid --}}
|
||||
@if($nailPolishes->count() > 0)
|
||||
<div class="row g-3">
|
||||
@foreach($nailPolishes as $nailPolish)
|
||||
<div class="col-6 col-md-4 col-lg-3">
|
||||
<div class="card np-card h-100">
|
||||
@if($nailPolish->image_path)
|
||||
<img src="{{ Storage::url($nailPolish->image_path) }}"
|
||||
class="np-img" alt="{{ $nailPolish->name }}" loading="lazy">
|
||||
@else
|
||||
<div class="np-placeholder">
|
||||
<i class="fas fa-palette"></i>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-body d-flex flex-column">
|
||||
<div class="flex-grow-1">
|
||||
<div class="np-name">{{ $nailPolish->name }}</div>
|
||||
<div class="np-number">Nr. {{ $nailPolish->number }}</div>
|
||||
@if($nailPolish->manufacturer)
|
||||
<p class="card-text text-muted mb-2">
|
||||
<small><i class="fas fa-industry"></i> {{ $nailPolish->manufacturer->name }}</small>
|
||||
</p>
|
||||
<span class="np-brand">{{ $nailPolish->manufacturer->name }}</span>
|
||||
@endif
|
||||
|
||||
<div class="mt-auto">
|
||||
<form method="POST" action="https://neonail.vogt.de.com/remove-from-collection/{{ $nailPolish->id }}"
|
||||
class="d-inline"
|
||||
onsubmit="return confirm('Möchten Sie diesen Lack wirklich aus Ihrer Sammlung entfernen?')">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-outline-danger btn-sm w-100">
|
||||
<i class="fas fa-trash me-2"></i>Entfernen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<form method="POST" action="{{ route('user-nail-polishes.remove', $nailPolish) }}"
|
||||
onsubmit="return confirm('Lack aus der Sammlung entfernen?')">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-outline-danger btn-sm w-100">
|
||||
<i class="fas fa-trash-alt me-1"></i>Entfernen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
@if($nailPolishes->hasPages())
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<nav aria-label="Seitennavigation">
|
||||
{{ $nailPolishes->appends(['search' => $search])->links() }}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="text-center py-5">
|
||||
<i class="fas fa-palette fa-4x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Ihre Sammlung ist noch leer</h4>
|
||||
<p class="text-muted mb-4">
|
||||
@if($search)
|
||||
Keine Lacke gefunden, die "{{ $search }}" entsprechen.
|
||||
@else
|
||||
Fügen Sie Ihren ersten NeoNail-Lack hinzu!
|
||||
@endif
|
||||
</p>
|
||||
<div class="d-flex gap-2 justify-content-center">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Ersten Lack hinzufügen
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.available') }}" class="btn btn-primary">
|
||||
<i class="fas fa-search me-2"></i>Verfügbare Lacke durchsuchen
|
||||
</a>
|
||||
</div>
|
||||
@if($nailPolishes->hasPages())
|
||||
<div class="d-flex justify-content-center mt-5">
|
||||
{{ $nailPolishes->appends(['search' => $search])->links() }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@else
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">
|
||||
<i class="fas fa-palette"></i>
|
||||
</div>
|
||||
<h4>{{ $search ? 'Keine Ergebnisse' : 'Sammlung ist noch leer' }}</h4>
|
||||
<p>
|
||||
@if($search)
|
||||
Keine Lacke gefunden, die „{{ $search }}" entsprechen.
|
||||
@else
|
||||
Fügen Sie Ihren ersten NeoNail-Lack hinzu!
|
||||
@endif
|
||||
</p>
|
||||
<div class="d-flex gap-2 justify-content-center flex-wrap">
|
||||
<a href="{{ route('user-nail-polishes.create') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus me-2"></i>Ersten Lack hinzufügen
|
||||
</a>
|
||||
<a href="{{ route('user-nail-polishes.available') }}" class="btn btn-glass">
|
||||
<i class="fas fa-search me-2"></i>Verfügbare Lacke durchsuchen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endsection
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
<?php
|
||||
// E-Mail an spezifischen User senden
|
||||
echo "📧 E-Mail an spezifischen User senden\n";
|
||||
echo "=====================================\n\n";
|
||||
|
||||
// Hier können Sie die E-Mail-Adresse des Users eingeben
|
||||
$targetEmail = 'oliver@vogt.de.com'; // Ändern Sie dies zur gewünschten E-Mail-Adresse
|
||||
|
||||
echo "📧 Sende E-Mail an: $targetEmail\n\n";
|
||||
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Laravel Bootstrap
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// User in der Datenbank suchen
|
||||
$user = \App\Models\User::where('email', $targetEmail)->first();
|
||||
|
||||
if (!$user) {
|
||||
echo "❌ User mit E-Mail '$targetEmail' nicht in der Datenbank gefunden!\n";
|
||||
echo "\n📋 Verfügbare User:\n";
|
||||
$allUsers = \App\Models\User::all();
|
||||
foreach ($allUsers as $u) {
|
||||
$adminBadge = $u->isAdmin() ? ' 👑' : '';
|
||||
echo " - {$u->name} ({$u->email}){$adminBadge}\n";
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
echo "✅ User gefunden: {$user->name} ({$user->email})\n";
|
||||
echo " - Admin-Status: " . ($user->isAdmin() ? 'Ja 👑' : 'Nein') . "\n";
|
||||
echo " - Registriert: {$user->created_at->format('d.m.Y H:i')}\n";
|
||||
|
||||
// E-Mail-Inhalt
|
||||
$emailContent = "Hallo {$user->name}!
|
||||
|
||||
🎨 Willkommen bei der NeoNail Datenbank!
|
||||
|
||||
Dies ist eine persönliche E-Mail, die speziell an Sie gesendet wurde.
|
||||
|
||||
📋 Ihre Account-Informationen:
|
||||
- Name: {$user->name}
|
||||
- E-Mail: {$user->email}
|
||||
- Registriert: {$user->created_at->format('d.m.Y H:i')}
|
||||
- Admin-Status: " . ($user->isAdmin() ? 'Ja 👑' : 'Nein') . "
|
||||
|
||||
🎯 Ihre NeoNail DB Features:
|
||||
- Persönliche Nagellack-Sammlung verwalten
|
||||
- Neue Lacke hinzufügen und fotografieren
|
||||
- Nach Lacken suchen (Name oder Nummer)
|
||||
- Mobile-optimierte Benutzeroberfläche
|
||||
|
||||
🔗 Direkte Links:
|
||||
- Meine Sammlung: https://neonail.vogt.de.com/my-collection
|
||||
- Verfügbare Lacke: https://neonail.vogt.de.com/available
|
||||
- Neuen Lack hinzufügen: https://neonail.vogt.de.com/create-nail-polish
|
||||
|
||||
" . ($user->isAdmin() ? "
|
||||
👑 Als Admin haben Sie zusätzlichen Zugriff:
|
||||
- User-Verwaltung: https://neonail.vogt.de.com/admin/users
|
||||
- Nagellack-Verwaltung: https://neonail.vogt.de.com/nail-polishes
|
||||
- Dashboard: https://neonail.vogt.de.com/admin/dashboard
|
||||
" : "") . "
|
||||
Viele Grüße,
|
||||
Ihr NeoNail DB Team
|
||||
|
||||
---
|
||||
Diese E-Mail wurde automatisch generiert.
|
||||
Bei Fragen wenden Sie sich an den Administrator.";
|
||||
|
||||
// E-Mail senden
|
||||
$result = \Illuminate\Support\Facades\Mail::raw($emailContent, function($message) use ($user) {
|
||||
$message->to($user->email, $user->name)
|
||||
->subject('🎨 NeoNail DB - Persönliche Willkommens-E-Mail')
|
||||
->from(config('mail.from.address'), config('mail.from.name'));
|
||||
});
|
||||
|
||||
echo "\n✅ E-Mail erfolgreich gesendet!\n";
|
||||
echo "📧 Empfänger: {$user->email}\n";
|
||||
echo "📅 Zeitstempel: " . now() . "\n";
|
||||
echo "📋 Betreff: 🎨 NeoNail DB - Persönliche Willkommens-E-Mail\n";
|
||||
|
||||
// Erfolgs-Bestätigung an Admin
|
||||
echo "\n📧 Sende Bestätigung an Admin...\n";
|
||||
|
||||
$adminContent = "Hallo Admin!
|
||||
|
||||
Eine persönliche E-Mail wurde erfolgreich an einen User gesendet.
|
||||
|
||||
📋 Details:
|
||||
- Empfänger: {$user->name} ({$user->email})
|
||||
- Admin-Status: " . ($user->isAdmin() ? 'Ja' : 'Nein') . "
|
||||
- Zeitstempel: " . now() . "
|
||||
- E-Mail-Konfiguration: ✅ Funktioniert perfekt
|
||||
|
||||
Die E-Mail-Funktionalität ist vollständig einsatzbereit!
|
||||
|
||||
Viele Grüße,
|
||||
NeoNail DB System";
|
||||
|
||||
$adminResult = \Illuminate\Support\Facades\Mail::raw($adminContent, function($message) {
|
||||
$message->to('oliver@vogt.de.com', 'Admin')
|
||||
->subject('✅ NeoNail DB - Persönliche User-E-Mail gesendet')
|
||||
->from(config('mail.from.address'), config('mail.from.name'));
|
||||
});
|
||||
|
||||
echo " ✅ Admin-Bestätigung gesendet!\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "❌ Fehler beim Senden der E-Mail:\n";
|
||||
echo " " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
echo "\n✅ Persönliche User-E-Mail abgeschlossen!\n";
|
||||
echo "📋 Nächste Schritte:\n";
|
||||
echo "1. Prüfen Sie das Postfach von: $targetEmail\n";
|
||||
echo "2. Prüfen Sie Ihr Admin-Postfach: oliver@vogt.de.com\n";
|
||||
echo "3. Falls keine E-Mails ankommen, prüfen Sie Spam-Ordner\n";
|
||||
echo "\n🎯 Die E-Mail-Funktionalität ist jetzt vollständig einsatzbereit!\n";
|
||||
?>
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
// Einfache Test-Mail senden
|
||||
echo "📧 Einfache Test-Mail senden\n";
|
||||
echo "===========================\n\n";
|
||||
|
||||
// E-Mail-Adresse für den Test (hier anpassen)
|
||||
$testEmail = 'oliver@vogt.de.com'; // Ändern Sie dies zu Ihrer E-Mail-Adresse
|
||||
|
||||
echo "📧 Sende Test-Mail an: $testEmail\n\n";
|
||||
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Laravel Bootstrap
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// Einfache Test-Mail senden
|
||||
$result = \Illuminate\Support\Facades\Mail::raw('Hallo!
|
||||
|
||||
Dies ist eine Test-Mail von der NeoNail Datenbank.
|
||||
|
||||
✅ E-Mail-Konfiguration funktioniert!
|
||||
📅 Zeitstempel: ' . now() . '
|
||||
🌐 Server: ' . ($_SERVER['SERVER_NAME'] ?? 'Unbekannt') . '
|
||||
|
||||
Die E-Mail-Funktionalität ist jetzt bereit.
|
||||
|
||||
Viele Grüße,
|
||||
NeoNail DB System', function($message) use ($testEmail) {
|
||||
$message->to($testEmail)
|
||||
->subject('✅ NeoNail DB - E-Mail-Test erfolgreich!')
|
||||
->from(config('mail.from.address'), config('mail.from.name'));
|
||||
});
|
||||
|
||||
echo "✅ Test-Mail erfolgreich gesendet!\n";
|
||||
echo "📧 Prüfen Sie Ihr Postfach: $testEmail\n";
|
||||
echo "📁 Falls keine E-Mail ankommt, prüfen Sie auch den Spam-Ordner\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "❌ Fehler beim Senden der Test-Mail:\n";
|
||||
echo " " . $e->getMessage() . "\n\n";
|
||||
|
||||
echo "🔍 Fehleranalyse:\n";
|
||||
if (strpos($e->getMessage(), 'Connection refused') !== false) {
|
||||
echo " - Problem: Verbindung zum SMTP-Server verweigert\n";
|
||||
echo " - Lösung: Prüfen Sie MAIL_HOST und MAIL_PORT\n";
|
||||
} elseif (strpos($e->getMessage(), 'Authentication failed') !== false) {
|
||||
echo " - Problem: Authentifizierung fehlgeschlagen\n";
|
||||
echo " - Lösung: Prüfen Sie MAIL_USERNAME und MAIL_PASSWORD\n";
|
||||
} elseif (strpos($e->getMessage(), 'SSL') !== false) {
|
||||
echo " - Problem: SSL/TLS Verbindungsproblem\n";
|
||||
echo " - Lösung: Prüfen Sie MAIL_ENCRYPTION (SSL/TLS)\n";
|
||||
} else {
|
||||
echo " - Unbekannter Fehler\n";
|
||||
}
|
||||
|
||||
echo "\n📋 Aktuelle E-Mail-Konfiguration:\n";
|
||||
echo " - MAIL_HOST: " . config('mail.mailers.smtp.host') . "\n";
|
||||
echo " - MAIL_PORT: " . config('mail.mailers.smtp.port') . "\n";
|
||||
echo " - MAIL_ENCRYPTION: " . config('mail.mailers.smtp.encryption') . "\n";
|
||||
echo " - MAIL_USERNAME: " . config('mail.mailers.smtp.username') . "\n";
|
||||
echo " - MAIL_FROM_ADDRESS: " . config('mail.from.address') . "\n";
|
||||
}
|
||||
?>
|
||||
@@ -1,116 +0,0 @@
|
||||
<?php
|
||||
// E-Mail an angelegten User senden
|
||||
echo "📧 E-Mail an angelegten User senden\n";
|
||||
echo "===================================\n\n";
|
||||
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Laravel Bootstrap
|
||||
$app = require_once 'bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
// Alle User auflisten
|
||||
echo "1. 👥 Verfügbare User:\n";
|
||||
$users = \App\Models\User::all();
|
||||
|
||||
if ($users->isEmpty()) {
|
||||
echo " ❌ Keine User in der Datenbank gefunden\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
foreach ($users as $index => $user) {
|
||||
$adminBadge = $user->isAdmin() ? ' 👑' : '';
|
||||
echo " " . ($index + 1) . ". {$user->name} ({$user->email}){$adminBadge}\n";
|
||||
}
|
||||
|
||||
// User auswählen (hier können Sie den Index ändern)
|
||||
$selectedUserIndex = 0; // Erster User (0-basiert)
|
||||
$selectedUser = $users[$selectedUserIndex];
|
||||
|
||||
echo "\n2. 📧 Sende E-Mail an: {$selectedUser->name} ({$selectedUser->email})\n";
|
||||
|
||||
// E-Mail-Inhalt
|
||||
$emailContent = "Hallo {$selectedUser->name}!
|
||||
|
||||
Willkommen bei der NeoNail Datenbank! 🎨
|
||||
|
||||
Dies ist eine Test-E-Mail, die an einen registrierten User gesendet wurde.
|
||||
|
||||
📋 Ihre Account-Details:
|
||||
- Name: {$selectedUser->name}
|
||||
- E-Mail: {$selectedUser->email}
|
||||
- Registriert: {$selectedUser->created_at->format('d.m.Y H:i')}
|
||||
- Admin-Status: " . ($selectedUser->isAdmin() ? 'Ja 👑' : 'Nein') . "
|
||||
|
||||
🎯 Was Sie mit der NeoNail DB machen können:
|
||||
- Ihre persönliche Nagellack-Sammlung verwalten
|
||||
- Neue Lacke hinzufügen
|
||||
- Nach Lacken suchen
|
||||
- Bilder von Ihren Lacken hochladen
|
||||
|
||||
🔗 Zugriff auf Ihre Sammlung:
|
||||
https://neonail.vogt.de.com/my-collection
|
||||
|
||||
Viele Grüße,
|
||||
Ihr NeoNail DB Team
|
||||
|
||||
---
|
||||
Diese E-Mail wurde automatisch generiert.
|
||||
Bei Fragen wenden Sie sich an den Administrator.";
|
||||
|
||||
// E-Mail senden
|
||||
$result = \Illuminate\Support\Facades\Mail::raw($emailContent, function($message) use ($selectedUser) {
|
||||
$message->to($selectedUser->email, $selectedUser->name)
|
||||
->subject('🎨 Willkommen bei der NeoNail DB - Test-E-Mail')
|
||||
->from(config('mail.from.address'), config('mail.from.name'));
|
||||
});
|
||||
|
||||
echo " ✅ E-Mail erfolgreich gesendet!\n";
|
||||
echo " 📧 Empfänger: {$selectedUser->email}\n";
|
||||
echo " 📅 Zeitstempel: " . now() . "\n";
|
||||
|
||||
// Zusätzliche Info-Mail an Admin
|
||||
echo "\n3. 📧 Sende Info-Mail an Admin...\n";
|
||||
|
||||
$adminInfoContent = "Hallo Admin!
|
||||
|
||||
Eine Test-E-Mail wurde erfolgreich an einen User gesendet.
|
||||
|
||||
📋 Details:
|
||||
- Empfänger: {$selectedUser->name} ({$selectedUser->email})
|
||||
- Zeitstempel: " . now() . "
|
||||
- E-Mail-Konfiguration: ✅ Funktioniert
|
||||
|
||||
Die E-Mail-Funktionalität ist bereit für:
|
||||
- Passwort-Reset
|
||||
- Benutzer-Benachrichtigungen
|
||||
- Admin-Benachrichtigungen
|
||||
|
||||
Viele Grüße,
|
||||
NeoNail DB System";
|
||||
|
||||
$adminResult = \Illuminate\Support\Facades\Mail::raw($adminInfoContent, function($message) {
|
||||
$message->to('oliver@vogt.de.com', 'Admin')
|
||||
->subject('📧 NeoNail DB - User-E-Mail erfolgreich gesendet')
|
||||
->from(config('mail.from.address'), config('mail.from.name'));
|
||||
});
|
||||
|
||||
echo " ✅ Admin-Info-Mail gesendet!\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "❌ Fehler beim Senden der E-Mail:\n";
|
||||
echo " " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
echo "\n✅ User-E-Mail-Test abgeschlossen!\n";
|
||||
echo "📋 Nächste Schritte:\n";
|
||||
echo "1. Prüfen Sie das Postfach von: {$selectedUser->email}\n";
|
||||
echo "2. Prüfen Sie Ihr Admin-Postfach: oliver@vogt.de.com\n";
|
||||
echo "3. Falls keine E-Mails ankommen, prüfen Sie Spam-Ordner\n";
|
||||
echo "\n🔗 E-Mail-Funktionen sind jetzt verfügbar für:\n";
|
||||
echo "- Passwort-Reset für User\n";
|
||||
echo "- Willkommens-E-Mails für neue User\n";
|
||||
echo "- Admin-Benachrichtigungen\n";
|
||||
echo "- System-Benachrichtigungen\n";
|
||||
?>
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🌐 Apache Setup für NeoNail DB"
|
||||
echo "=============================="
|
||||
|
||||
# 1. .htaccess im Hauptverzeichnis erstellen
|
||||
echo "📝 Erstelle .htaccess im Hauptverzeichnis..."
|
||||
cat > .htaccess << 'EOF'
|
||||
# NeoNail DB - Hauptverzeichnis .htaccess
|
||||
RewriteEngine On
|
||||
RewriteRule ^$ public/ [L]
|
||||
RewriteRule (.*) public/$1 [L]
|
||||
|
||||
# Sicherheit
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
EOF
|
||||
|
||||
# 2. Apache Virtual Host erstellen
|
||||
echo "🌐 Erstelle Apache Virtual Host..."
|
||||
cat > /etc/apache2/sites-available/neonail.conf << 'EOF'
|
||||
<VirtualHost *:80>
|
||||
ServerName 192.168.30.81
|
||||
DocumentRoot /var/www/html/public
|
||||
|
||||
<Directory /var/www/html/public>
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/neonail_error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/neonail_access.log combined
|
||||
</VirtualHost>
|
||||
EOF
|
||||
|
||||
# 3. Standard-Site deaktivieren
|
||||
echo "🔧 Deaktiviere Standard-Site..."
|
||||
a2dissite 000-default.conf 2>/dev/null || echo "⚠️ Standard-Site bereits deaktiviert"
|
||||
|
||||
# 4. NeoNail-Site aktivieren
|
||||
echo "✅ Aktiviere NeoNail-Site..."
|
||||
a2ensite neonail.conf
|
||||
|
||||
# 5. Apache neu laden
|
||||
echo "🔄 Lade Apache neu..."
|
||||
systemctl reload apache2
|
||||
|
||||
# 6. Status prüfen
|
||||
echo "🔍 Prüfe Apache-Status..."
|
||||
systemctl status apache2 --no-pager -l
|
||||
|
||||
echo ""
|
||||
echo "✅ Apache Setup abgeschlossen!"
|
||||
echo "📋 Testen Sie: http://192.168.30.81"
|
||||
echo ""
|
||||
echo "📋 Falls es nicht funktioniert:"
|
||||
echo "1. Apache-Logs prüfen: tail -f /var/log/apache2/neonail_error.log"
|
||||
echo "2. Berechtigungen prüfen: ls -la /var/www/html/public/"
|
||||
echo "3. .htaccess prüfen: cat /var/www/html/public/.htaccess"
|
||||
@@ -1,112 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🎨 NeoNail DB - Setup für HTML-Verzeichnis"
|
||||
echo "=========================================="
|
||||
|
||||
# 1. .env Datei erstellen
|
||||
echo "📝 Erstelle .env Datei..."
|
||||
cat > .env << 'EOF'
|
||||
APP_NAME="NeoNail DB"
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:+LTZYPKjkZ+O3iFTgU2sS+9bNvxxvG8Kw8JSEPiG7Rs=
|
||||
APP_DEBUG=false
|
||||
APP_URL=http://192.168.30.81
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=database.sqlite
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailpit
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_HOST=
|
||||
PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
EOF
|
||||
|
||||
# 2. Berechtigungen setzen
|
||||
echo "🔐 Setze Berechtigungen..."
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
chmod 644 .env
|
||||
|
||||
# 3. SQLite-Datenbank erstellen (falls nicht vorhanden)
|
||||
echo "🗄️ Erstelle SQLite-Datenbank..."
|
||||
touch database.sqlite
|
||||
chmod 664 database.sqlite
|
||||
|
||||
# 4. Composer install (falls Composer verfügbar)
|
||||
if command -v composer &> /dev/null; then
|
||||
echo "📦 Führe Composer install aus..."
|
||||
composer install --no-dev --optimize-autoloader
|
||||
else
|
||||
echo "⚠️ Composer nicht gefunden. Bitte manuell ausführen: composer install"
|
||||
fi
|
||||
|
||||
# 5. Laravel Setup
|
||||
echo "⚙️ Laravel Setup..."
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
|
||||
# 6. Migrationen ausführen
|
||||
echo "🗃️ Führe Migrationen aus..."
|
||||
php artisan migrate --force
|
||||
|
||||
# 7. Storage Link erstellen
|
||||
echo "🔗 Erstelle Storage Link..."
|
||||
php artisan storage:link
|
||||
|
||||
echo ""
|
||||
echo "✅ Setup abgeschlossen!"
|
||||
echo ""
|
||||
echo "📋 Nächste Schritte:"
|
||||
echo "1. Admin-User erstellen:"
|
||||
echo " php artisan tinker"
|
||||
echo " use App\Models\User;"
|
||||
echo " User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('ihr_passwort')]);"
|
||||
echo ""
|
||||
echo "2. Anwendung testen:"
|
||||
echo " http://192.168.30.81"
|
||||
echo ""
|
||||
echo "3. Bei Problemen Debug aktivieren:"
|
||||
echo " APP_DEBUG=true in .env setzen"
|
||||
@@ -1,131 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# NeoNail DB - Vollständiges Webspace Setup
|
||||
echo "🚀 NeoNail DB - Vollständiges Webspace Setup..."
|
||||
|
||||
# 1. .env erstellen (falls nicht vorhanden)
|
||||
echo "📝 .env Datei erstellen..."
|
||||
if [ ! -f .env ]; then
|
||||
cat > .env << 'EOF'
|
||||
APP_NAME="NeoNail DB"
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:+LTZYPKjkZ+O3iFTgU2sS+9bNvxxvG8Kw8JSEPiG7Rs=
|
||||
APP_DEBUG=false
|
||||
APP_URL=http://192.168.30.81/neonail
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=error
|
||||
|
||||
# SQLite Konfiguration
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=database.sqlite
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailpit
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_HOST=
|
||||
PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
EOF
|
||||
echo "✅ .env Datei erstellt"
|
||||
else
|
||||
echo "✅ .env Datei bereits vorhanden"
|
||||
fi
|
||||
|
||||
# 2. Storage-Verzeichnisse erstellen
|
||||
echo "📁 Storage-Verzeichnisse erstellen..."
|
||||
mkdir -p storage/framework/views
|
||||
mkdir -p storage/framework/cache
|
||||
mkdir -p storage/framework/sessions
|
||||
mkdir -p storage/logs
|
||||
mkdir -p bootstrap/cache
|
||||
|
||||
# 3. Berechtigungen setzen
|
||||
echo "🔐 Berechtigungen setzen..."
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
chmod 644 .env
|
||||
|
||||
# 4. SQLite-Datenbank erstellen
|
||||
echo "🗄️ SQLite-Datenbank erstellen..."
|
||||
if [ ! -f database.sqlite ]; then
|
||||
touch database.sqlite
|
||||
echo "✅ SQLite-Datenbank erstellt"
|
||||
else
|
||||
echo "✅ SQLite-Datenbank bereits vorhanden"
|
||||
fi
|
||||
chmod 664 database.sqlite
|
||||
|
||||
# 5. Composer installieren (falls verfügbar)
|
||||
echo "📦 Composer Dependencies installieren..."
|
||||
if command -v composer &> /dev/null; then
|
||||
composer install --optimize-autoloader --no-dev
|
||||
echo "✅ Composer Dependencies installiert"
|
||||
else
|
||||
echo "⚠️ Composer nicht verfügbar"
|
||||
fi
|
||||
|
||||
# 6. Laravel Setup
|
||||
echo "🔧 Laravel Setup..."
|
||||
if command -v php &> /dev/null; then
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ php artisan config:clear fehlgeschlagen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ php artisan cache:clear fehlgeschlagen"
|
||||
php artisan view:clear 2>/dev/null || echo "⚠️ php artisan view:clear fehlgeschlagen"
|
||||
php artisan storage:link 2>/dev/null || echo "⚠️ php artisan storage:link fehlgeschlagen"
|
||||
php artisan migrate --force 2>/dev/null || echo "⚠️ php artisan migrate fehlgeschlagen"
|
||||
php artisan config:cache 2>/dev/null || echo "⚠️ php artisan config:cache fehlgeschlagen"
|
||||
echo "✅ Laravel Setup abgeschlossen"
|
||||
else
|
||||
echo "⚠️ PHP nicht verfügbar"
|
||||
fi
|
||||
|
||||
echo "✅ Setup abgeschlossen!"
|
||||
echo ""
|
||||
echo "📋 Nächste Schritte:"
|
||||
echo "1. Seite testen: http://192.168.30.81/neonail/"
|
||||
echo "2. Admin-User erstellen (falls php verfügbar):"
|
||||
echo " php artisan tinker"
|
||||
echo " use App\Models\User;"
|
||||
echo " User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('passwort')]);"
|
||||
echo ""
|
||||
echo "💡 Falls Probleme bestehen:"
|
||||
echo "- APP_DEBUG=true in .env setzen für Debug-Informationen"
|
||||
echo "- Logs prüfen: storage/logs/laravel.log"
|
||||
echo "- Hosting-Provider kontaktieren"
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "📝 Einfache .htaccess Lösung"
|
||||
echo "==========================="
|
||||
|
||||
# 1. .htaccess im Hauptverzeichnis erstellen
|
||||
echo "📝 Erstelle .htaccess im Hauptverzeichnis..."
|
||||
cat > .htaccess << 'EOF'
|
||||
RewriteEngine On
|
||||
|
||||
# Umleitung auf public/
|
||||
RewriteRule ^$ public/ [L]
|
||||
RewriteRule (.*) public/$1 [L]
|
||||
|
||||
# Sicherheit
|
||||
<Files ".env">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "database.sqlite">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
# PHP-Dateien erlauben
|
||||
<Files "*.php">
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Files>
|
||||
EOF
|
||||
|
||||
# 2. Apache mod_rewrite aktivieren
|
||||
echo "🔧 Aktiviere mod_rewrite..."
|
||||
a2enmod rewrite
|
||||
|
||||
# 3. Apache neu laden
|
||||
echo "🔄 Lade Apache neu..."
|
||||
systemctl reload apache2
|
||||
|
||||
# 4. Test
|
||||
echo "🧪 Teste Anwendung..."
|
||||
curl -I http://192.168.30.81
|
||||
|
||||
echo ""
|
||||
echo "✅ .htaccess Lösung aktiviert!"
|
||||
echo "📋 Testen Sie: http://192.168.30.81"
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🎨 NeoNail DB - Einfaches Laravel Setup"
|
||||
echo "======================================"
|
||||
|
||||
# 1. .env erstellen (falls nicht vorhanden)
|
||||
if [ ! -f ".env" ]; then
|
||||
echo "📝 Erstelle .env Datei..."
|
||||
cp env-production-example.txt .env
|
||||
fi
|
||||
|
||||
# 2. Berechtigungen setzen
|
||||
echo "🔐 Setze Berechtigungen..."
|
||||
chmod -R 777 storage/
|
||||
chmod -R 777 bootstrap/cache/
|
||||
chmod 644 .env
|
||||
|
||||
# 3. SQLite-Datenbank erstellen
|
||||
echo "🗄️ Erstelle SQLite-Datenbank..."
|
||||
touch database.sqlite
|
||||
chmod 664 database.sqlite
|
||||
|
||||
# 4. Nur grundlegende Laravel-Befehle (ohne problematische Provider)
|
||||
echo "⚙️ Laravel Grund-Setup..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
|
||||
# 5. Migrationen ausführen (falls möglich)
|
||||
echo "🗃️ Führe Migrationen aus..."
|
||||
php artisan migrate --force 2>/dev/null || echo "⚠️ Migrationen übersprungen"
|
||||
|
||||
# 6. Storage Link erstellen
|
||||
echo "🔗 Erstelle Storage Link..."
|
||||
php artisan storage:link 2>/dev/null || echo "⚠️ Storage Link übersprungen"
|
||||
|
||||
echo ""
|
||||
echo "✅ Grund-Setup abgeschlossen!"
|
||||
echo ""
|
||||
echo "📋 Nächste Schritte:"
|
||||
echo "1. Vendor-Ordner hochladen (falls nicht vorhanden)"
|
||||
echo "2. Admin-User erstellen:"
|
||||
echo " php artisan tinker"
|
||||
echo " use App\Models\User;"
|
||||
echo " User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('ihr_passwort')]);"
|
||||
echo ""
|
||||
echo "3. Anwendung testen: http://192.168.30.81"
|
||||
@@ -1,62 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🧠 NeoNail DB - Intelligentes Setup"
|
||||
echo "=================================="
|
||||
|
||||
# 1. .env erstellen (falls nicht vorhanden)
|
||||
if [ ! -f ".env" ]; then
|
||||
echo "📝 Erstelle .env Datei..."
|
||||
cp env-production-example.txt .env
|
||||
else
|
||||
echo "✅ .env Datei bereits vorhanden"
|
||||
fi
|
||||
|
||||
# 2. SQLite-Datenbank erstellen
|
||||
if [ ! -f "database.sqlite" ]; then
|
||||
echo "🗄️ Erstelle SQLite-Datenbank..."
|
||||
touch database.sqlite
|
||||
else
|
||||
echo "✅ SQLite-Datenbank bereits vorhanden"
|
||||
fi
|
||||
chmod 664 database.sqlite
|
||||
|
||||
# 3. Berechtigungen setzen
|
||||
echo "🔐 Setze Berechtigungen..."
|
||||
chmod -R 777 storage/ 2>/dev/null
|
||||
chmod -R 777 bootstrap/cache/ 2>/dev/null
|
||||
chmod 644 .env 2>/dev/null
|
||||
|
||||
# 4. Storage Link prüfen
|
||||
echo "🔗 Prüfe Storage Link..."
|
||||
if [ ! -L "public/storage" ]; then
|
||||
echo "📎 Erstelle Storage Link..."
|
||||
php artisan storage:link 2>/dev/null || echo "⚠️ Storage Link übersprungen"
|
||||
else
|
||||
echo "✅ Storage Link bereits vorhanden"
|
||||
fi
|
||||
|
||||
# 5. Cache leeren (nur wenn nötig)
|
||||
echo "🧹 Leere Cache..."
|
||||
php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen"
|
||||
php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen"
|
||||
|
||||
# 6. Migrationen ausführen
|
||||
echo "🗃️ Führe Migrationen aus..."
|
||||
php artisan migrate --force 2>/dev/null || echo "⚠️ Migrationen übersprungen"
|
||||
|
||||
echo ""
|
||||
echo "✅ Intelligentes Setup abgeschlossen!"
|
||||
echo ""
|
||||
echo "📋 Status:"
|
||||
echo "• .env: $(test -f .env && echo '✅' || echo '❌')"
|
||||
echo "• database.sqlite: $(test -f database.sqlite && echo '✅' || echo '❌')"
|
||||
echo "• storage link: $(test -L public/storage && echo '✅' || echo '❌')"
|
||||
echo "• storage/ schreibbar: $(test -w storage && echo '✅' || echo '❌')"
|
||||
echo ""
|
||||
echo "📋 Nächste Schritte:"
|
||||
echo "1. Admin-User erstellen:"
|
||||
echo " php artisan tinker"
|
||||
echo " use App\Models\User;"
|
||||
echo " User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('ihr_passwort')]);"
|
||||
echo ""
|
||||
echo "2. Anwendung testen: http://192.168.30.81"
|
||||
@@ -1,138 +0,0 @@
|
||||
# 📧 SMTP-Mail-Konfiguration - Korrekte Einrichtung
|
||||
|
||||
## ✅ **Korrekte .env Konfiguration:**
|
||||
|
||||
```env
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mail.selfhost.de
|
||||
MAIL_PORT=465
|
||||
MAIL_USERNAME=postmaster@hjzyyqdm.mail.selfhost.de
|
||||
MAIL_PASSWORD=Ikmyra
|
||||
MAIL_ENCRYPTION=SSL
|
||||
MAIL_FROM_ADDRESS="neonail@vogt.de.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
```
|
||||
|
||||
## 🔧 **Schritte zur Behebung:**
|
||||
|
||||
### **Schritt 1: .env Datei korrigieren**
|
||||
|
||||
Stelle sicher, dass die `.env` Datei auf dem Webspace die korrekten Werte enthält:
|
||||
|
||||
```bash
|
||||
# Auf dem Webspace
|
||||
nano .env
|
||||
|
||||
# Oder mit sed (falls verfügbar)
|
||||
sed -i 's/MAIL_MAILER=log/MAIL_MAILER=smtp/' .env
|
||||
sed -i 's/MAIL_HOST=127.0.0.1/MAIL_HOST=mail.selfhost.de/' .env
|
||||
sed -i 's/MAIL_PORT=1025/MAIL_PORT=465/' .env
|
||||
sed -i 's/MAIL_USERNAME=null/MAIL_USERNAME=postmaster@hjzyyqdm.mail.selfhost.de/' .env
|
||||
sed -i 's/MAIL_PASSWORD=null/MAIL_PASSWORD=Ikmyra/' .env
|
||||
sed -i 's/MAIL_ENCRYPTION=null/MAIL_ENCRYPTION=SSL/' .env
|
||||
sed -i 's/MAIL_FROM_ADDRESS=.*/MAIL_FROM_ADDRESS="neonail@vogt.de.com"/' .env
|
||||
```
|
||||
|
||||
### **Schritt 2: Cache leeren**
|
||||
|
||||
```bash
|
||||
php artisan config:clear
|
||||
php artisan cache:clear
|
||||
```
|
||||
|
||||
### **Schritt 3: Mail-Verbindung testen**
|
||||
|
||||
```bash
|
||||
# Script ausführbar machen
|
||||
chmod +x test-mail-connection.sh
|
||||
|
||||
# Mail-Test ausführen
|
||||
./test-mail-connection.sh
|
||||
```
|
||||
|
||||
### **Schritt 4: Manueller Test (falls Script nicht funktioniert)**
|
||||
|
||||
```bash
|
||||
php artisan tinker --execute="
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
try {
|
||||
Mail::raw('Test-Mail von NeoNail DB - ' . now(), function(\$message) {
|
||||
\$message->to('oliver@vogt.de.com')
|
||||
->subject('NeoNail DB - SMTP Test')
|
||||
->from('neonail@vogt.de.com', 'NeoNail DB');
|
||||
});
|
||||
echo '✅ Test-Mail erfolgreich gesendet!';
|
||||
} catch(Exception \$e) {
|
||||
echo '❌ Mail-Fehler: ' . \$e->getMessage();
|
||||
}
|
||||
"
|
||||
```
|
||||
|
||||
## 🔍 **Troubleshooting:**
|
||||
|
||||
### **Problem 1: "Connection could not be established"**
|
||||
|
||||
**Ursache:** SMTP-Server nicht erreichbar
|
||||
**Lösung:**
|
||||
```bash
|
||||
# Teste Port-Erreichbarkeit
|
||||
telnet mail.selfhost.de 465
|
||||
|
||||
# Oder mit nc
|
||||
nc -zv mail.selfhost.de 465
|
||||
```
|
||||
|
||||
### **Problem 2: "Authentication failed"**
|
||||
|
||||
**Ursache:** Falsche Anmeldedaten
|
||||
**Lösung:**
|
||||
- Username/Password in `.env` prüfen
|
||||
- SSL/TLS-Einstellungen prüfen
|
||||
|
||||
### **Problem 3: "SSL certificate problem"**
|
||||
|
||||
**Ursache:** SSL-Zertifikat-Problem
|
||||
**Lösung:**
|
||||
```env
|
||||
MAIL_ENCRYPTION=SSL
|
||||
# Oder versuchen:
|
||||
MAIL_ENCRYPTION=tls
|
||||
```
|
||||
|
||||
## 📋 **Mail-Logs prüfen:**
|
||||
|
||||
```bash
|
||||
# Alle Mail-bezogenen Logs anzeigen
|
||||
grep -i "mail\|email\|smtp" storage/logs/laravel.log
|
||||
|
||||
# Letzte Mail-Fehler
|
||||
tail -n 50 storage/logs/laravel.log | grep -i mail
|
||||
|
||||
# Spezifische Mail suchen
|
||||
grep -i "willkommens-e-mail" storage/logs/laravel.log
|
||||
```
|
||||
|
||||
## 🎯 **Nach erfolgreicher Konfiguration:**
|
||||
|
||||
1. **Neuen User erstellen** - E-Mail sollte versendet werden
|
||||
2. **Admin-Benachrichtigung** - Admin sollte E-Mail erhalten
|
||||
3. **Mail-Logs prüfen** - Erfolgreiche Versendung bestätigen
|
||||
|
||||
## ⚠️ **Wichtige Hinweise:**
|
||||
|
||||
- **Port 465** erfordert SSL-Verschlüsselung
|
||||
- **Username** muss vollständig sein (mit Domain)
|
||||
- **Password** darf keine Sonderzeichen enthalten
|
||||
- **Firewall** muss Port 465 erlauben
|
||||
- **SMTP-Server** muss für externe Verbindungen konfiguriert sein
|
||||
|
||||
## 🚀 **Alternative: Log-Modus für Testing**
|
||||
|
||||
Falls SMTP-Probleme bestehen, temporär auf Log-Modus umstellen:
|
||||
|
||||
```env
|
||||
MAIL_MAILER=log
|
||||
```
|
||||
|
||||
E-Mails werden dann in `storage/logs/laravel.log` geschrieben.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user