Script erstellt
This commit is contained in:
commit
2a15995cbb
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@ -0,0 +1,18 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[docker-compose.yml]
|
||||
indent_size = 4
|
||||
65
.env.example
Normal file
65
.env.example
Normal file
@ -0,0 +1,65 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
|
||||
APP_LOCALE=en
|
||||
APP_FALLBACK_LOCALE=en
|
||||
APP_FAKER_LOCALE=en_US
|
||||
|
||||
APP_MAINTENANCE_DRIVER=file
|
||||
# APP_MAINTENANCE_STORE=database
|
||||
|
||||
PHP_CLI_SERVER_WORKERS=4
|
||||
|
||||
BCRYPT_ROUNDS=12
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_STACK=single
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
# DB_HOST=127.0.0.1
|
||||
# DB_PORT=3306
|
||||
# DB_DATABASE=laravel
|
||||
# DB_USERNAME=root
|
||||
# DB_PASSWORD=
|
||||
|
||||
SESSION_DRIVER=database
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_ENCRYPT=false
|
||||
SESSION_PATH=/
|
||||
SESSION_DOMAIN=null
|
||||
|
||||
BROADCAST_CONNECTION=log
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=database
|
||||
|
||||
CACHE_STORE=database
|
||||
# CACHE_PREFIX=
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_CLIENT=phpredis
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=log
|
||||
MAIL_SCHEME=null
|
||||
MAIL_HOST=127.0.0.1
|
||||
MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=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
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
* text=auto eol=lf
|
||||
|
||||
*.blade.php diff=html
|
||||
*.css diff=css
|
||||
*.html diff=html
|
||||
*.md diff=markdown
|
||||
*.php diff=php
|
||||
|
||||
/.github export-ignore
|
||||
CHANGELOG.md export-ignore
|
||||
.styleci.yml export-ignore
|
||||
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
*.log
|
||||
.DS_Store
|
||||
.env
|
||||
.env.backup
|
||||
.env.production
|
||||
.phpactor.json
|
||||
.phpunit.result.cache
|
||||
/.fleet
|
||||
/.idea
|
||||
/.nova
|
||||
/.phpunit.cache
|
||||
/.vscode
|
||||
/.zed
|
||||
/auth.json
|
||||
/node_modules
|
||||
/public/build
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/storage/pail
|
||||
/vendor
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
Thumbs.db
|
||||
30
.htaccess
Normal file
30
.htaccess
Normal file
@ -0,0 +1,30 @@
|
||||
# Redirect to public directory
|
||||
RewriteEngine On
|
||||
RewriteRule ^$ public/ [L]
|
||||
RewriteRule (.*) public/$1 [L]
|
||||
|
||||
# Prevent directory listing
|
||||
Options -Indexes
|
||||
|
||||
# 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"
|
||||
</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>
|
||||
323
DEPLOYMENT.md
Executable file
323
DEPLOYMENT.md
Executable file
@ -0,0 +1,323 @@
|
||||
# 🚀 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! 🎉**
|
||||
340
NEONAIL_PROJECT_PROMPT.md
Executable file
340
NEONAIL_PROJECT_PROMPT.md
Executable file
@ -0,0 +1,340 @@
|
||||
# 🎨 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)
|
||||
-- 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. 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)
|
||||
- ✅ Admin-User erstellt
|
||||
- ✅ Hersteller-Feature vollständig implementiert und deployed
|
||||
|
||||
## 🔄 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. ✅ **Admin-User** erstellt
|
||||
5. ✅ **Anwendung getestet** - Hersteller-Feature funktioniert
|
||||
6. ✅ **HTTPS-Sicherheit** für alle Hersteller-Forms implementiert
|
||||
|
||||
### Admin-User erstellen
|
||||
```bash
|
||||
php artisan tinker
|
||||
```
|
||||
```php
|
||||
use App\Models\User;
|
||||
User::create([
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@neonail.com',
|
||||
'password' => bcrypt('ihr_passwort')
|
||||
]);
|
||||
```
|
||||
|
||||
## 📱 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
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
## 📞 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
|
||||
|
||||
## 🎯 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
|
||||
|
||||
### Nächste Schritte 🚀
|
||||
1. ✅ Webspace-Deployment abgeschlossen
|
||||
2. ✅ Admin-User erstellt
|
||||
3. ✅ Anwendung getestet (inkl. Hersteller-Feature)
|
||||
4. User-Feedback sammeln
|
||||
5. Weitere Features entwickeln
|
||||
|
||||
---
|
||||
|
||||
**Projekt-Status:** 100% abgeschlossen, Hersteller-Feature implementiert
|
||||
**Letzte Aktion:** Hersteller-Feature vollständig deployed und getestet
|
||||
**Nächste Aktion:** User-Feedback sammeln und weitere Features entwickeln
|
||||
163
README.md
Executable file
163
README.md
Executable file
@ -0,0 +1,163 @@
|
||||
# NeoNail Datenbank
|
||||
|
||||
Eine Laravel-basierte Webanwendung zur Verwaltung von NeoNail-Nagellack-Sammlungen. Die Anwendung ermöglicht es Benutzern, ihre persönliche Nagellack-Sammlung zu verwalten und ist speziell für die mobile Nutzung optimiert.
|
||||
|
||||
## Features
|
||||
|
||||
### Für Benutzer
|
||||
- **Persönliche Sammlung**: Benutzer können ihre NeoNail-Lacke verwalten
|
||||
- **Mobile Optimierung**: Handy-optimiertes Design für schnelle Nutzung im Laden
|
||||
- **Suchfunktion**: Suche nach Namen oder Nummer der Lacke
|
||||
- **Bild-Upload**: Möglichkeit, Bilder per Handykamera hochzuladen
|
||||
- **Hersteller-Verwaltung**: Erstellen und verwalten von Herstellern
|
||||
- **Responsive Design**: Funktioniert auf allen Geräten
|
||||
|
||||
### Für Administratoren
|
||||
- **Benutzer-Verwaltung**: Erstellen, bearbeiten und löschen von Benutzern
|
||||
- **Nagellack-Verwaltung**: Vollständige CRUD-Operationen für Nagellacke
|
||||
- **Hersteller-Verwaltung**: Verwaltung aller Hersteller im System
|
||||
- **Bildoptimierung**: Automatische Optimierung hochgeladener Bilder
|
||||
- **Statistiken**: Übersicht über Benutzer, Sammlungen und Hersteller
|
||||
- **Admin-Dashboard**: Übersichtliche Verwaltungsoberfläche
|
||||
|
||||
## Technische Details
|
||||
|
||||
### Datenbank-Struktur
|
||||
- **Users**: Benutzer-Verwaltung
|
||||
- **Manufacturers**: Hersteller-Daten (Name, Beschreibung, Website, Land)
|
||||
- **NailPolishes**: Nagellack-Daten (Name, Nummer, Hersteller, Bild)
|
||||
- **UserNailPolishes**: Many-to-Many Beziehung zwischen Benutzern und Lacken
|
||||
|
||||
### Technologien
|
||||
- **Laravel 12**: PHP-Framework
|
||||
- **Bootstrap 5**: CSS-Framework für responsive Design
|
||||
- **Intervention Image**: Bildoptimierung
|
||||
- **SQLite**: Datenbank (für einfache Entwicklung)
|
||||
|
||||
## Installation
|
||||
|
||||
### Voraussetzungen
|
||||
- PHP 8.2+
|
||||
- Composer
|
||||
- Node.js (optional für Asset-Compilation)
|
||||
|
||||
### Setup
|
||||
1. Repository klonen:
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd neonail-database
|
||||
```
|
||||
|
||||
2. Abhängigkeiten installieren:
|
||||
```bash
|
||||
composer install
|
||||
```
|
||||
|
||||
3. Umgebungsvariablen konfigurieren:
|
||||
```bash
|
||||
cp .env.example .env
|
||||
php artisan key:generate
|
||||
```
|
||||
|
||||
4. Datenbank einrichten:
|
||||
```bash
|
||||
php artisan migrate
|
||||
```
|
||||
|
||||
5. Storage-Link erstellen:
|
||||
```bash
|
||||
php artisan storage:link
|
||||
```
|
||||
|
||||
6. Admin-Benutzer erstellen:
|
||||
```bash
|
||||
php artisan tinker
|
||||
```
|
||||
```php
|
||||
App\Models\User::create([
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@neonail.com',
|
||||
'password' => bcrypt('password')
|
||||
]);
|
||||
```
|
||||
|
||||
7. Server starten:
|
||||
```bash
|
||||
php artisan serve
|
||||
```
|
||||
|
||||
## Verwendung
|
||||
|
||||
### Admin-Zugang
|
||||
- **E-Mail**: admin@neonail.com
|
||||
- **Passwort**: password
|
||||
|
||||
### Benutzer-Flow
|
||||
1. **Anmeldung**: Benutzer melden sich mit ihren Zugangsdaten an
|
||||
2. **Sammlung anzeigen**: Übersicht über alle eigenen Lacke
|
||||
3. **Lack hinzufügen**: Aus verfügbaren Lacken auswählen
|
||||
4. **Hersteller verwalten**: Hersteller erstellen und verwalten
|
||||
5. **Suchen**: Schnelle Suche nach Namen oder Nummer
|
||||
6. **Bilder**: Kamera-Upload für neue Lacke (Admin)
|
||||
|
||||
### Admin-Flow
|
||||
1. **Dashboard**: Übersicht über Statistiken
|
||||
2. **Benutzer verwalten**: CRUD-Operationen für Benutzer
|
||||
3. **Nagellacke verwalten**: Vollständige Verwaltung der Lacke
|
||||
4. **Hersteller verwalten**: Verwaltung aller Hersteller
|
||||
5. **Statistiken**: Detaillierte Auswertungen
|
||||
|
||||
## Mobile Optimierung
|
||||
|
||||
Die Anwendung ist speziell für mobile Geräte optimiert:
|
||||
- **Touch-freundlich**: Große Buttons und Touch-Targets
|
||||
- **Kamera-Integration**: Direkter Zugriff auf Handykamera
|
||||
- **Responsive Design**: Anpassung an verschiedene Bildschirmgrößen
|
||||
- **Schnelle Navigation**: Optimiert für schnelle Nutzung im Laden
|
||||
|
||||
## Sicherheit
|
||||
|
||||
- **Authentifizierung**: Laravel's eingebaute Auth-System
|
||||
- **Admin-Middleware**: Geschützte Admin-Bereiche
|
||||
- **Bildvalidierung**: Sichere Bild-Uploads
|
||||
- **CSRF-Schutz**: Automatischer CSRF-Schutz
|
||||
|
||||
## Entwicklung
|
||||
|
||||
### Hinzufügen neuer Features
|
||||
1. Migration erstellen: `php artisan make:migration`
|
||||
2. Model anpassen/erstellen
|
||||
3. Controller-Logik implementieren
|
||||
4. Views erstellen
|
||||
5. Routes definieren
|
||||
|
||||
### Testing
|
||||
```bash
|
||||
php artisan test
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### Produktionsumgebung
|
||||
1. `.env` für Produktion konfigurieren
|
||||
2. `APP_ENV=production` setzen
|
||||
3. `APP_DEBUG=false` setzen
|
||||
4. Datenbank-Migrationen ausführen
|
||||
5. Storage-Links erstellen
|
||||
|
||||
### Empfohlene Server-Konfiguration
|
||||
- **Webserver**: Nginx oder Apache
|
||||
- **PHP**: 8.2+ mit erforderlichen Extensions
|
||||
- **Datenbank**: MySQL/PostgreSQL für Produktion
|
||||
- **SSL**: HTTPS für sichere Übertragung
|
||||
|
||||
## Support
|
||||
|
||||
Bei Fragen oder Problemen:
|
||||
1. Issues im Repository erstellen
|
||||
2. Dokumentation prüfen
|
||||
3. Laravel-Dokumentation konsultieren
|
||||
|
||||
## Lizenz
|
||||
|
||||
Dieses Projekt ist für interne Nutzung bestimmt.
|
||||
205
WEBSPACE-SETUP.md
Executable file
205
WEBSPACE-SETUP.md
Executable file
@ -0,0 +1,205 @@
|
||||
# 🌐 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! 🎉**
|
||||
37
activate-admin-role.sh
Executable file
37
activate-admin-role.sh
Executable file
@ -0,0 +1,37 @@
|
||||
#!/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"
|
||||
17
add-admin-role-migration.php
Normal file
17
add-admin-role-migration.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?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";
|
||||
?>
|
||||
47
admin-check.php
Executable file
47
admin-check.php
Executable file
@ -0,0 +1,47 @@
|
||||
<?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>";
|
||||
}
|
||||
?>
|
||||
28
apache-config.txt
Executable file
28
apache-config.txt
Executable file
@ -0,0 +1,28 @@
|
||||
# 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>
|
||||
74
apache-diagnose.sh
Executable file
74
apache-diagnose.sh
Executable file
@ -0,0 +1,74 @@
|
||||
#!/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"
|
||||
212
app/Http/Controllers/AdminController.php
Executable file
212
app/Http/Controllers/AdminController.php
Executable file
@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\NailPolish;
|
||||
use App\Models\Manufacturer;
|
||||
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();
|
||||
$totalManufacturers = Manufacturer::count();
|
||||
$recentUsers = User::latest()->take(5)->get();
|
||||
$recentNailPolishes = NailPolish::latest()->take(5)->get();
|
||||
$recentManufacturers = Manufacturer::latest()->take(5)->get();
|
||||
|
||||
return view("admin.dashboard", compact("totalUsers", "totalNailPolishes", "totalManufacturers", "recentUsers", "recentNailPolishes", "recentManufacturers"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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"
|
||||
));
|
||||
}
|
||||
}
|
||||
43
app/Http/Controllers/Auth/LoginController.php
Executable file
43
app/Http/Controllers/Auth/LoginController.php
Executable file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
public function showLoginForm()
|
||||
{
|
||||
return view('auth.login');
|
||||
}
|
||||
|
||||
public function login(Request $request)
|
||||
{
|
||||
$credentials = $request->validate([
|
||||
'email' => ['required', 'email'],
|
||||
'password' => ['required'],
|
||||
]);
|
||||
|
||||
if (Auth::attempt($credentials, $request->boolean('remember'))) {
|
||||
$request->session()->regenerate();
|
||||
|
||||
return redirect()->intended(route('user-nail-polishes.index'));
|
||||
}
|
||||
|
||||
return back()->withErrors([
|
||||
'email' => 'Die angegebenen Anmeldedaten stimmen nicht überein.',
|
||||
])->onlyInput('email');
|
||||
}
|
||||
|
||||
public function logout(Request $request)
|
||||
{
|
||||
Auth::logout();
|
||||
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return redirect('/');
|
||||
}
|
||||
}
|
||||
8
app/Http/Controllers/Controller.php
Executable file
8
app/Http/Controllers/Controller.php
Executable file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
abstract class Controller
|
||||
{
|
||||
//
|
||||
}
|
||||
154
app/Http/Controllers/ManufacturerController.php
Normal file
154
app/Http/Controllers/ManufacturerController.php
Normal file
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Manufacturer;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ManufacturerController extends Controller
|
||||
{
|
||||
/**
|
||||
* Zeigt alle Hersteller an
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$search = $request->get('search');
|
||||
|
||||
$query = Manufacturer::withCount('nailPolishes');
|
||||
|
||||
if ($search) {
|
||||
$query->search($search);
|
||||
}
|
||||
|
||||
$manufacturers = $query->orderBy('name')->paginate(20);
|
||||
|
||||
return view('manufacturers.index', compact('manufacturers', 'search'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt das Formular zum Erstellen eines neuen Herstellers
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('manufacturers.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Speichert einen neuen Hersteller
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'required|string|max:255|unique:manufacturers',
|
||||
'description' => 'nullable|string|max:1000',
|
||||
'website' => 'nullable|url|max:255',
|
||||
'country' => 'nullable|string|max:100',
|
||||
]);
|
||||
|
||||
try {
|
||||
$manufacturer = Manufacturer::create([
|
||||
'name' => $request->name,
|
||||
'description' => $request->description,
|
||||
'website' => $request->website,
|
||||
'country' => $request->country,
|
||||
]);
|
||||
|
||||
return redirect()->route('manufacturers.index')
|
||||
->with('success', "Hersteller '{$manufacturer->name}' wurde erfolgreich erstellt!");
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("Fehler beim Erstellen des Herstellers: " . $e->getMessage());
|
||||
return back()->with('error', 'Fehler beim Erstellen des Herstellers. Bitte versuchen Sie es erneut.')
|
||||
->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt einen Hersteller an
|
||||
*/
|
||||
public function show(Manufacturer $manufacturer)
|
||||
{
|
||||
$manufacturer->load(['nailPolishes' => function($query) {
|
||||
$query->orderBy('name');
|
||||
}]);
|
||||
|
||||
return view('manufacturers.show', compact('manufacturer'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt das Formular zum Bearbeiten eines Herstellers
|
||||
*/
|
||||
public function edit(Manufacturer $manufacturer)
|
||||
{
|
||||
return view('manufacturers.edit', compact('manufacturer'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert einen Hersteller
|
||||
*/
|
||||
public function update(Request $request, Manufacturer $manufacturer)
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'required|string|max:255|unique:manufacturers,name,' . $manufacturer->id,
|
||||
'description' => 'nullable|string|max:1000',
|
||||
'website' => 'nullable|url|max:255',
|
||||
'country' => 'nullable|string|max:100',
|
||||
]);
|
||||
|
||||
try {
|
||||
$manufacturer->update([
|
||||
'name' => $request->name,
|
||||
'description' => $request->description,
|
||||
'website' => $request->website,
|
||||
'country' => $request->country,
|
||||
]);
|
||||
|
||||
return redirect()->route('manufacturers.index')
|
||||
->with('success', "Hersteller '{$manufacturer->name}' wurde erfolgreich aktualisiert!");
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("Fehler beim Aktualisieren des Herstellers: " . $e->getMessage());
|
||||
return back()->with('error', 'Fehler beim Aktualisieren des Herstellers. Bitte versuchen Sie es erneut.')
|
||||
->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Löscht einen Hersteller
|
||||
*/
|
||||
public function destroy(Manufacturer $manufacturer)
|
||||
{
|
||||
try {
|
||||
// Prüfe, ob der Hersteller noch Nagellacke hat
|
||||
if ($manufacturer->hasNailPolishes()) {
|
||||
return back()->with('error', "Hersteller '{$manufacturer->name}' kann nicht gelöscht werden, da noch Nagellacke zugeordnet sind.");
|
||||
}
|
||||
|
||||
$name = $manufacturer->name;
|
||||
$manufacturer->delete();
|
||||
|
||||
return redirect()->route('manufacturers.index')
|
||||
->with('success', "Hersteller '{$name}' wurde erfolgreich gelöscht!");
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("Fehler beim Löschen des Herstellers: " . $e->getMessage());
|
||||
return back()->with('error', 'Fehler beim Löschen des Herstellers. Bitte versuchen Sie es erneut.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API-Endpoint für AJAX-Suche nach Herstellern
|
||||
*/
|
||||
public function search(Request $request)
|
||||
{
|
||||
$search = $request->get('q');
|
||||
|
||||
$manufacturers = Manufacturer::where('name', 'like', "%{$search}%")
|
||||
->orderBy('name')
|
||||
->limit(10)
|
||||
->get(['id', 'name']);
|
||||
|
||||
return response()->json($manufacturers);
|
||||
}
|
||||
}
|
||||
165
app/Http/Controllers/NailPolishController.php
Executable file
165
app/Http/Controllers/NailPolishController.php
Executable file
@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\NailPolish;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Intervention\Image\Facades\Image;
|
||||
|
||||
class NailPolishController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$search = $request->get('search');
|
||||
|
||||
$nailPolishes = NailPolish::when($search, function($query) use ($search) {
|
||||
return $query->search($search);
|
||||
})->orderBy('name')->paginate(20);
|
||||
|
||||
return view('nail-polishes.index', compact('nailPolishes', 'search'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('nail-polishes.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'number' => 'required|string|max:50|unique:nail_polishes',
|
||||
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048'
|
||||
]);
|
||||
|
||||
$nailPolish = new NailPolish();
|
||||
$nailPolish->name = $request->name;
|
||||
$nailPolish->number = $request->number;
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
$image = $request->file('image');
|
||||
$filename = time() . '_' . $image->getClientOriginalName();
|
||||
|
||||
// Bild optimieren und speichern
|
||||
$optimizedImage = Image::make($image)
|
||||
->resize(300, 300, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})
|
||||
->encode('jpg', 80);
|
||||
|
||||
Storage::disk('public')->put('nail-polishes/' . $filename, $optimizedImage);
|
||||
$nailPolish->image_path = 'nail-polishes/' . $filename;
|
||||
}
|
||||
|
||||
$nailPolish->save();
|
||||
|
||||
return redirect()->route('nail-polishes.index')
|
||||
->with('success', 'Nagellack erfolgreich hinzugefügt!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(NailPolish $nailPolish)
|
||||
{
|
||||
return view('nail-polishes.show', compact('nailPolish'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(NailPolish $nailPolish)
|
||||
{
|
||||
return view('nail-polishes.edit', compact('nailPolish'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, NailPolish $nailPolish)
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'number' => 'required|string|max:50|unique:nail_polishes,number,' . $nailPolish->id,
|
||||
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048'
|
||||
]);
|
||||
|
||||
$nailPolish->name = $request->name;
|
||||
$nailPolish->number = $request->number;
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
// Altes Bild löschen
|
||||
if ($nailPolish->image_path) {
|
||||
Storage::disk('public')->delete($nailPolish->image_path);
|
||||
}
|
||||
|
||||
$image = $request->file('image');
|
||||
$filename = time() . '_' . $image->getClientOriginalName();
|
||||
|
||||
// Bild optimieren und speichern
|
||||
$optimizedImage = Image::make($image)
|
||||
->resize(300, 300, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})
|
||||
->encode('jpg', 80);
|
||||
|
||||
Storage::disk('public')->put('nail-polishes/' . $filename, $optimizedImage);
|
||||
$nailPolish->image_path = 'nail-polishes/' . $filename;
|
||||
}
|
||||
|
||||
$nailPolish->save();
|
||||
|
||||
return redirect()->route('nail-polishes.index')
|
||||
->with('success', 'Nagellack erfolgreich aktualisiert!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Löscht einen Nagellack
|
||||
*/
|
||||
public function destroy(NailPolish $nailPolish)
|
||||
{
|
||||
try {
|
||||
// Prüfe, ob der Lack von anderen Usern verwendet wird
|
||||
$usersWithThisPolish = $nailPolish->users()->count();
|
||||
|
||||
if ($usersWithThisPolish > 0) {
|
||||
return back()->with('error', "Dieser Lack kann nicht gelöscht werden, da er von {$usersWithThisPolish} Benutzer(n) in ihrer Sammlung verwendet wird. Bitte entfernen Sie ihn zuerst aus allen Sammlungen.");
|
||||
}
|
||||
|
||||
// Lösche das Bild, falls vorhanden
|
||||
if ($nailPolish->image_path && Storage::disk('public')->exists($nailPolish->image_path)) {
|
||||
Storage::disk('public')->delete($nailPolish->image_path);
|
||||
}
|
||||
|
||||
$nailPolish->delete();
|
||||
|
||||
return redirect()->route('nail-polishes.index')
|
||||
->with('success', "Lack '{$nailPolish->name}' wurde erfolgreich gelöscht!");
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return back()->with('error', 'Fehler beim Löschen des Lackes: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt an, welche User einen bestimmten Lack haben
|
||||
*/
|
||||
public function showUsers(NailPolish $nailPolish)
|
||||
{
|
||||
$users = $nailPolish->users()->paginate(20);
|
||||
|
||||
return view('nail-polishes.show-users', compact('nailPolish', 'users'));
|
||||
}
|
||||
}
|
||||
186
app/Http/Controllers/UserNailPolishController.php
Executable file
186
app/Http/Controllers/UserNailPolishController.php
Executable file
@ -0,0 +1,186 @@
|
||||
<?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",
|
||||
"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
|
||||
], [
|
||||
"name.required" => "Der Name des Lackes ist erforderlich.",
|
||||
"number.required" => "Die Nummer des Lackes ist erforderlich.",
|
||||
"manufacturer_id.required_without" => "Bitte wählen Sie einen Hersteller aus oder erstellen Sie einen neuen.",
|
||||
"new_manufacturer.required_without" => "Bitte wählen Sie einen Hersteller aus oder erstellen Sie einen neuen.",
|
||||
"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.",
|
||||
]);
|
||||
|
||||
try {
|
||||
// Hersteller verarbeiten
|
||||
$manufacturerId = null;
|
||||
if ($request->filled('new_manufacturer')) {
|
||||
// Neuen Hersteller erstellen
|
||||
$manufacturer = \App\Models\Manufacturer::create([
|
||||
'name' => trim($request->new_manufacturer),
|
||||
]);
|
||||
$manufacturerId = $manufacturer->id;
|
||||
} else {
|
||||
$manufacturerId = $request->manufacturer_id;
|
||||
}
|
||||
|
||||
$nailPolish = new NailPolish();
|
||||
$nailPolish->name = trim($request->name);
|
||||
$nailPolish->number = trim($request->number);
|
||||
$nailPolish->manufacturer_id = $manufacturerId;
|
||||
|
||||
// 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);
|
||||
|
||||
$successMessage = "Lack \"{$nailPolish->name}\" wurde erfolgreich erstellt und zu Ihrer Sammlung hinzugefügt!";
|
||||
if ($request->filled('new_manufacturer')) {
|
||||
$successMessage .= " Neuer Hersteller \"{$request->new_manufacturer}\" wurde ebenfalls erstellt.";
|
||||
}
|
||||
|
||||
return redirect()->route("user-nail-polishes.index")
|
||||
->with("success", $successMessage);
|
||||
|
||||
} 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"));
|
||||
}
|
||||
}
|
||||
25
app/Http/Middleware/AdminMiddleware.php
Executable file
25
app/Http/Middleware/AdminMiddleware.php
Executable file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class AdminMiddleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
// Admin-Berechtigung mit is_admin Spalte
|
||||
if (!auth()->check() || !auth()->user()->isAdmin()) {
|
||||
abort(403, 'Zugriff verweigert. Admin-Berechtigung erforderlich.');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
29
app/Http/Middleware/Authenticate.php
Executable file
29
app/Http/Middleware/Authenticate.php
Executable file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class Authenticate
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, string ...$guards): Response
|
||||
{
|
||||
$guards = empty($guards) ? [null] : $guards;
|
||||
|
||||
foreach ($guards as $guard) {
|
||||
if (!Auth::guard($guard)->check()) {
|
||||
return redirect()->route('login');
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
29
app/Http/Middleware/RedirectIfAuthenticated.php
Executable file
29
app/Http/Middleware/RedirectIfAuthenticated.php
Executable file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class RedirectIfAuthenticated
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, string ...$guards): Response
|
||||
{
|
||||
$guards = empty($guards) ? [null] : $guards;
|
||||
|
||||
foreach ($guards as $guard) {
|
||||
if (Auth::guard($guard)->check()) {
|
||||
return redirect()->route('user-nail-polishes.index');
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
65
app/Models/Manufacturer.php
Normal file
65
app/Models/Manufacturer.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Manufacturer extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* Die Tabelle, die dem Model zugeordnet ist.
|
||||
*/
|
||||
protected $table = 'manufacturers';
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'website',
|
||||
'country',
|
||||
];
|
||||
|
||||
/**
|
||||
* Beziehung zu Nagellacken
|
||||
*/
|
||||
public function nailPolishes()
|
||||
{
|
||||
return $this->hasMany(NailPolish::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope für Suche nach Name
|
||||
*/
|
||||
public function scopeSearch($query, $search)
|
||||
{
|
||||
return $query->where('name', 'like', "%{$search}%")
|
||||
->orWhere('description', 'like', "%{$search}%")
|
||||
->orWhere('country', 'like', "%{$search}%");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Namen des Herstellers zurück
|
||||
*/
|
||||
public function getDisplayNameAttribute()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob der Hersteller Nagellacke hat
|
||||
*/
|
||||
public function hasNailPolishes()
|
||||
{
|
||||
return $this->nailPolishes()->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Anzahl der Nagellacke dieses Herstellers
|
||||
*/
|
||||
public function getNailPolishCountAttribute()
|
||||
{
|
||||
return $this->nailPolishes()->count();
|
||||
}
|
||||
}
|
||||
48
app/Models/NailPolish.php
Executable file
48
app/Models/NailPolish.php
Executable file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class NailPolish extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* Die Tabelle, die dem Model zugeordnet ist.
|
||||
*/
|
||||
protected $table = 'nail_polishes';
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'number',
|
||||
'manufacturer_id',
|
||||
'image_path',
|
||||
];
|
||||
|
||||
/**
|
||||
* Beziehung zu Benutzern
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->belongsToMany(User::class, 'user_nail_polishes', 'nail_polish_id', 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Beziehung zum Hersteller
|
||||
*/
|
||||
public function manufacturer()
|
||||
{
|
||||
return $this->belongsTo(Manufacturer::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope für Suche nach Name oder Nummer
|
||||
*/
|
||||
public function scopeSearch($query, $search)
|
||||
{
|
||||
return $query->where('name', 'like', "%{$search}%")
|
||||
->orWhere('number', 'like', "%{$search}%");
|
||||
}
|
||||
}
|
||||
83
app/Models/User.php
Executable file
83
app/Models/User.php
Executable file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasFactory, Notifiable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
'password',
|
||||
'is_admin',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the attributes that should be cast.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Beziehung zu Nagellacken
|
||||
*/
|
||||
public function nailPolishes()
|
||||
{
|
||||
return $this->belongsToMany(NailPolish::class, 'user_nail_polishes', 'user_id', 'nail_polish_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob der User ein Admin ist
|
||||
*/
|
||||
public function isAdmin()
|
||||
{
|
||||
return $this->is_admin || in_array($this->email, ['admin@neonail.com', 'neueradmin@neonail.com']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Macht den User zum Admin
|
||||
*/
|
||||
public function makeAdmin()
|
||||
{
|
||||
$this->is_admin = true;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Entfernt Admin-Rechte
|
||||
*/
|
||||
public function removeAdmin()
|
||||
{
|
||||
$this->is_admin = false;
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
27
app/Providers/AppServiceProvider.php
Executable file
27
app/Providers/AppServiceProvider.php
Executable file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
if (config('app.env') === 'production') {
|
||||
URL::forceScheme('https');
|
||||
}
|
||||
}
|
||||
}
|
||||
18
artisan
Executable file
18
artisan
Executable file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Application;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
// Register the Composer autoloader...
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
// Bootstrap Laravel and handle the command...
|
||||
/** @var Application $app */
|
||||
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||
|
||||
$status = $app->handleCommand(new ArgvInput);
|
||||
|
||||
exit($status);
|
||||
24
bootstrap/app.php
Executable file
24
bootstrap/app.php
Executable file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Foundation\Configuration\Exceptions;
|
||||
use Illuminate\Foundation\Configuration\Middleware;
|
||||
|
||||
return Application::configure(basePath: dirname(__DIR__))
|
||||
->withRouting(
|
||||
web: __DIR__.'/../routes/web.php',
|
||||
commands: __DIR__.'/../routes/console.php',
|
||||
health: '/up',
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware): void {
|
||||
$middleware->alias([
|
||||
'admin' => \App\Http\Middleware\AdminMiddleware::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
]);
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions): void {
|
||||
//
|
||||
})
|
||||
->withProviders()
|
||||
->create();
|
||||
2
bootstrap/cache/.gitignore
vendored
Normal file
2
bootstrap/cache/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
6
bootstrap/providers.php
Executable file
6
bootstrap/providers.php
Executable file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
App\Providers\AppServiceProvider::class,
|
||||
Intervention\Image\ImageServiceProvider::class,
|
||||
];
|
||||
53
check-admin-user.php
Executable file
53
check-admin-user.php
Executable file
@ -0,0 +1,53 @@
|
||||
<?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>";
|
||||
}
|
||||
?>
|
||||
45
check-laravel-logs.sh
Executable file
45
check-laravel-logs.sh
Executable file
@ -0,0 +1,45 @@
|
||||
#!/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"
|
||||
77
check-user-collection.php
Normal file
77
check-user-collection.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?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>";
|
||||
}
|
||||
?>
|
||||
37
clear-route-cache.sh
Executable file
37
clear-route-cache.sh
Executable file
@ -0,0 +1,37 @@
|
||||
#!/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"
|
||||
72
complete-fix.sh
Executable file
72
complete-fix.sh
Executable file
@ -0,0 +1,72 @@
|
||||
#!/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')]);"
|
||||
79
composer.json
Executable file
79
composer.json
Executable file
@ -0,0 +1,79 @@
|
||||
{
|
||||
"$schema": "https://getcomposer.org/schema.json",
|
||||
"name": "laravel/laravel",
|
||||
"type": "project",
|
||||
"description": "The skeleton application for the Laravel framework.",
|
||||
"keywords": ["laravel", "framework"],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"intervention/image": "^3.11",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/tinker": "^2.10.1",
|
||||
"laravel/ui": "*",
|
||||
"smalot/pdfparser": "^2.12"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.23",
|
||||
"laravel/pail": "^1.2.2",
|
||||
"laravel/pint": "^1.13",
|
||||
"laravel/sail": "^1.41",
|
||||
"mockery/mockery": "^1.6",
|
||||
"nunomaduro/collision": "^8.6",
|
||||
"phpunit/phpunit": "^11.5.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "app/",
|
||||
"Database\\Factories\\": "database/factories/",
|
||||
"Database\\Seeders\\": "database/seeders/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-autoload-dump": [
|
||||
"@php artisan config:clear",
|
||||
"@php artisan clear-compiled",
|
||||
"@php artisan package:discover --ansi"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
|
||||
],
|
||||
"post-root-package-install": [
|
||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||
],
|
||||
"post-create-project-cmd": [
|
||||
"@php artisan key:generate --ansi",
|
||||
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
|
||||
"@php artisan migrate --graceful --ansi"
|
||||
],
|
||||
"dev": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite"
|
||||
],
|
||||
"test": [
|
||||
"@php artisan config:clear --ansi",
|
||||
"@php artisan test"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"dont-discover": []
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true,
|
||||
"php-http/discovery": true
|
||||
}
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true
|
||||
}
|
||||
8424
composer.lock
generated
Executable file
8424
composer.lock
generated
Executable file
File diff suppressed because it is too large
Load Diff
126
config/app.php
Executable file
126
config/app.php
Executable file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value is the name of your application, which will be used when the
|
||||
| framework needs to place the application's name in a notification or
|
||||
| other UI elements where an application name needs to be displayed.
|
||||
|
|
||||
*/
|
||||
|
||||
'name' => env('APP_NAME', 'Laravel'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Environment
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines the "environment" your application is currently
|
||||
| running in. This may determine how you prefer to configure various
|
||||
| services the application utilizes. Set this in your ".env" file.
|
||||
|
|
||||
*/
|
||||
|
||||
'env' => env('APP_ENV', 'production'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Debug Mode
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When your application is in debug mode, detailed error messages with
|
||||
| stack traces will be shown on every error that occurs within your
|
||||
| application. If disabled, a simple generic error page is shown.
|
||||
|
|
||||
*/
|
||||
|
||||
'debug' => (bool) env('APP_DEBUG', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application URL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This URL is used by the console to properly generate URLs when using
|
||||
| the Artisan command line tool. You should set this to the root of
|
||||
| the application so that it's available within Artisan commands.
|
||||
|
|
||||
*/
|
||||
|
||||
'url' => env('APP_URL', 'http://localhost'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Timezone
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default timezone for your application, which
|
||||
| will be used by the PHP date and date-time functions. The timezone
|
||||
| is set to "UTC" by default as it is suitable for most use cases.
|
||||
|
|
||||
*/
|
||||
|
||||
'timezone' => 'UTC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Locale Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The application locale determines the default locale that will be used
|
||||
| by Laravel's translation / localization methods. This option can be
|
||||
| set to any locale for which you plan to have translation strings.
|
||||
|
|
||||
*/
|
||||
|
||||
'locale' => env('APP_LOCALE', 'en'),
|
||||
|
||||
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
|
||||
|
||||
'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Encryption Key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This key is utilized by Laravel's encryption services and should be set
|
||||
| to a random, 32 character string to ensure that all encrypted values
|
||||
| are secure. You should do this prior to deploying the application.
|
||||
|
|
||||
*/
|
||||
|
||||
'cipher' => 'AES-256-CBC',
|
||||
|
||||
'key' => env('APP_KEY'),
|
||||
|
||||
'previous_keys' => [
|
||||
...array_filter(
|
||||
explode(',', (string) env('APP_PREVIOUS_KEYS', ''))
|
||||
),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Maintenance Mode Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These configuration options determine the driver used to determine and
|
||||
| manage Laravel's "maintenance mode" status. The "cache" driver will
|
||||
| allow maintenance mode to be controlled across multiple machines.
|
||||
|
|
||||
| Supported drivers: "file", "cache"
|
||||
|
|
||||
*/
|
||||
|
||||
'maintenance' => [
|
||||
'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
|
||||
'store' => env('APP_MAINTENANCE_STORE', 'database'),
|
||||
],
|
||||
|
||||
];
|
||||
115
config/auth.php
Executable file
115
config/auth.php
Executable file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Defaults
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option defines the default authentication "guard" and password
|
||||
| reset "broker" for your application. You may change these values
|
||||
| as required, but they're a perfect start for most applications.
|
||||
|
|
||||
*/
|
||||
|
||||
'defaults' => [
|
||||
'guard' => env('AUTH_GUARD', 'web'),
|
||||
'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Guards
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Next, you may define every authentication guard for your application.
|
||||
| Of course, a great default configuration has been defined for you
|
||||
| which utilizes session storage plus the Eloquent user provider.
|
||||
|
|
||||
| All authentication guards have a user provider, which defines how the
|
||||
| users are actually retrieved out of your database or other storage
|
||||
| system used by the application. Typically, Eloquent is utilized.
|
||||
|
|
||||
| Supported: "session"
|
||||
|
|
||||
*/
|
||||
|
||||
'guards' => [
|
||||
'web' => [
|
||||
'driver' => 'session',
|
||||
'provider' => 'users',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| User Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| All authentication guards have a user provider, which defines how the
|
||||
| users are actually retrieved out of your database or other storage
|
||||
| system used by the application. Typically, Eloquent is utilized.
|
||||
|
|
||||
| If you have multiple user tables or models you may configure multiple
|
||||
| providers to represent the model / table. These providers may then
|
||||
| be assigned to any extra authentication guards you have defined.
|
||||
|
|
||||
| Supported: "database", "eloquent"
|
||||
|
|
||||
*/
|
||||
|
||||
'providers' => [
|
||||
'users' => [
|
||||
'driver' => 'eloquent',
|
||||
'model' => env('AUTH_MODEL', App\Models\User::class),
|
||||
],
|
||||
|
||||
// 'users' => [
|
||||
// 'driver' => 'database',
|
||||
// 'table' => 'users',
|
||||
// ],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Resetting Passwords
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These configuration options specify the behavior of Laravel's password
|
||||
| reset functionality, including the table utilized for token storage
|
||||
| and the user provider that is invoked to actually retrieve users.
|
||||
|
|
||||
| The expiry time is the number of minutes that each reset token will be
|
||||
| considered valid. This security feature keeps tokens short-lived so
|
||||
| they have less time to be guessed. You may change this as needed.
|
||||
|
|
||||
| The throttle setting is the number of seconds a user must wait before
|
||||
| generating more password reset tokens. This prevents the user from
|
||||
| quickly generating a very large amount of password reset tokens.
|
||||
|
|
||||
*/
|
||||
|
||||
'passwords' => [
|
||||
'users' => [
|
||||
'provider' => 'users',
|
||||
'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
|
||||
'expire' => 60,
|
||||
'throttle' => 60,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Confirmation Timeout
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define the number of seconds before a password confirmation
|
||||
| window expires and users are asked to re-enter their password via the
|
||||
| confirmation screen. By default, the timeout lasts for three hours.
|
||||
|
|
||||
*/
|
||||
|
||||
'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),
|
||||
|
||||
];
|
||||
108
config/cache.php
Executable file
108
config/cache.php
Executable file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default cache store that will be used by the
|
||||
| framework. This connection is utilized if another isn't explicitly
|
||||
| specified when running a cache operation inside the application.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('CACHE_STORE', 'database'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Stores
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the cache "stores" for your application as
|
||||
| well as their drivers. You may even define multiple stores for the
|
||||
| same cache driver to group types of items stored in your caches.
|
||||
|
|
||||
| Supported drivers: "array", "database", "file", "memcached",
|
||||
| "redis", "dynamodb", "octane", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'stores' => [
|
||||
|
||||
'array' => [
|
||||
'driver' => 'array',
|
||||
'serialize' => false,
|
||||
],
|
||||
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'connection' => env('DB_CACHE_CONNECTION'),
|
||||
'table' => env('DB_CACHE_TABLE', 'cache'),
|
||||
'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'),
|
||||
'lock_table' => env('DB_CACHE_LOCK_TABLE'),
|
||||
],
|
||||
|
||||
'file' => [
|
||||
'driver' => 'file',
|
||||
'path' => storage_path('framework/cache/data'),
|
||||
'lock_path' => storage_path('framework/cache/data'),
|
||||
],
|
||||
|
||||
'memcached' => [
|
||||
'driver' => 'memcached',
|
||||
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
|
||||
'sasl' => [
|
||||
env('MEMCACHED_USERNAME'),
|
||||
env('MEMCACHED_PASSWORD'),
|
||||
],
|
||||
'options' => [
|
||||
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
|
||||
],
|
||||
'servers' => [
|
||||
[
|
||||
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
|
||||
'port' => env('MEMCACHED_PORT', 11211),
|
||||
'weight' => 100,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => env('REDIS_CACHE_CONNECTION', 'cache'),
|
||||
'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'),
|
||||
],
|
||||
|
||||
'dynamodb' => [
|
||||
'driver' => 'dynamodb',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
|
||||
'endpoint' => env('DYNAMODB_ENDPOINT'),
|
||||
],
|
||||
|
||||
'octane' => [
|
||||
'driver' => 'octane',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Key Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing the APC, database, memcached, Redis, and DynamoDB cache
|
||||
| stores, there might be other applications using the same cache. For
|
||||
| that reason, you may prefix every cache key to avoid collisions.
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-cache-'),
|
||||
|
||||
];
|
||||
8
config/csrf.php
Normal file
8
config/csrf.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'cookie' => [
|
||||
'secure' => true,
|
||||
'same_site' => 'lax',
|
||||
],
|
||||
];
|
||||
174
config/database.php
Executable file
174
config/database.php
Executable file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Database Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which of the database connections below you wish
|
||||
| to use as your default connection for database operations. This is
|
||||
| the connection which will be utilized unless another connection
|
||||
| is explicitly specified when you execute a query / statement.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('DB_CONNECTION', 'sqlite'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Below are all of the database connections defined for your application.
|
||||
| An example configuration is provided for each database system which
|
||||
| is supported by Laravel. You're free to add / remove connections.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
|
||||
'sqlite' => [
|
||||
'driver' => 'sqlite',
|
||||
'url' => env('DB_URL'),
|
||||
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
||||
'prefix' => '',
|
||||
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||
'busy_timeout' => null,
|
||||
'journal_mode' => null,
|
||||
'synchronous' => null,
|
||||
],
|
||||
|
||||
'mysql' => [
|
||||
'driver' => 'mysql',
|
||||
'url' => env('DB_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '3306'),
|
||||
'database' => env('DB_DATABASE', 'laravel'),
|
||||
'username' => env('DB_USERNAME', 'root'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'unix_socket' => env('DB_SOCKET', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8mb4'),
|
||||
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'strict' => true,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||
]) : [],
|
||||
],
|
||||
|
||||
'mariadb' => [
|
||||
'driver' => 'mariadb',
|
||||
'url' => env('DB_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '3306'),
|
||||
'database' => env('DB_DATABASE', 'laravel'),
|
||||
'username' => env('DB_USERNAME', 'root'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'unix_socket' => env('DB_SOCKET', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8mb4'),
|
||||
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'strict' => true,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||
]) : [],
|
||||
],
|
||||
|
||||
'pgsql' => [
|
||||
'driver' => 'pgsql',
|
||||
'url' => env('DB_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '5432'),
|
||||
'database' => env('DB_DATABASE', 'laravel'),
|
||||
'username' => env('DB_USERNAME', 'root'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'search_path' => 'public',
|
||||
'sslmode' => 'prefer',
|
||||
],
|
||||
|
||||
'sqlsrv' => [
|
||||
'driver' => 'sqlsrv',
|
||||
'url' => env('DB_URL'),
|
||||
'host' => env('DB_HOST', 'localhost'),
|
||||
'port' => env('DB_PORT', '1433'),
|
||||
'database' => env('DB_DATABASE', 'laravel'),
|
||||
'username' => env('DB_USERNAME', 'root'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
// 'encrypt' => env('DB_ENCRYPT', 'yes'),
|
||||
// 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Migration Repository Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This table keeps track of all the migrations that have already run for
|
||||
| your application. Using this information, we can determine which of
|
||||
| the migrations on disk haven't actually been run on the database.
|
||||
|
|
||||
*/
|
||||
|
||||
'migrations' => [
|
||||
'table' => 'migrations',
|
||||
'update_date_on_publish' => true,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Redis Databases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Redis is an open source, fast, and advanced key-value store that also
|
||||
| provides a richer body of commands than a typical key-value system
|
||||
| such as Memcached. You may define your connection settings here.
|
||||
|
|
||||
*/
|
||||
|
||||
'redis' => [
|
||||
|
||||
'client' => env('REDIS_CLIENT', 'phpredis'),
|
||||
|
||||
'options' => [
|
||||
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||
'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-database-'),
|
||||
'persistent' => env('REDIS_PERSISTENT', false),
|
||||
],
|
||||
|
||||
'default' => [
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'username' => env('REDIS_USERNAME'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'database' => env('REDIS_DB', '0'),
|
||||
],
|
||||
|
||||
'cache' => [
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'username' => env('REDIS_USERNAME'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'database' => env('REDIS_CACHE_DB', '1'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
80
config/filesystems.php
Executable file
80
config/filesystems.php
Executable file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default filesystem disk that should be used
|
||||
| by the framework. The "local" disk, as well as a variety of cloud
|
||||
| based disks are available to your application for file storage.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('FILESYSTEM_DISK', 'local'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Filesystem Disks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Below you may configure as many filesystem disks as necessary, and you
|
||||
| may even configure multiple disks for the same driver. Examples for
|
||||
| most supported storage drivers are configured here for reference.
|
||||
|
|
||||
| Supported drivers: "local", "ftp", "sftp", "s3"
|
||||
|
|
||||
*/
|
||||
|
||||
'disks' => [
|
||||
|
||||
'local' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/private'),
|
||||
'serve' => true,
|
||||
'throw' => false,
|
||||
'report' => false,
|
||||
],
|
||||
|
||||
'public' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/public'),
|
||||
'url' => env('APP_URL').'/storage',
|
||||
'visibility' => 'public',
|
||||
'throw' => false,
|
||||
'report' => false,
|
||||
],
|
||||
|
||||
's3' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION'),
|
||||
'bucket' => env('AWS_BUCKET'),
|
||||
'url' => env('AWS_URL'),
|
||||
'endpoint' => env('AWS_ENDPOINT'),
|
||||
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
|
||||
'throw' => false,
|
||||
'report' => false,
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Symbolic Links
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the symbolic links that will be created when the
|
||||
| `storage:link` Artisan command is executed. The array keys should be
|
||||
| the locations of the links and the values should be their targets.
|
||||
|
|
||||
*/
|
||||
|
||||
'links' => [
|
||||
public_path('storage') => storage_path('app/public'),
|
||||
],
|
||||
|
||||
];
|
||||
132
config/logging.php
Executable file
132
config/logging.php
Executable file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
use Monolog\Handler\NullHandler;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Handler\SyslogUdpHandler;
|
||||
use Monolog\Processor\PsrLogMessageProcessor;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option defines the default log channel that is utilized to write
|
||||
| messages to your logs. The value provided here should match one of
|
||||
| the channels present in the list of "channels" configured below.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('LOG_CHANNEL', 'stack'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Deprecations Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the log channel that should be used to log warnings
|
||||
| regarding deprecated PHP and library features. This allows you to get
|
||||
| your application ready for upcoming major versions of dependencies.
|
||||
|
|
||||
*/
|
||||
|
||||
'deprecations' => [
|
||||
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
|
||||
'trace' => env('LOG_DEPRECATIONS_TRACE', false),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Channels
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the log channels for your application. Laravel
|
||||
| utilizes the Monolog PHP logging library, which includes a variety
|
||||
| of powerful log handlers and formatters that you're free to use.
|
||||
|
|
||||
| Available drivers: "single", "daily", "slack", "syslog",
|
||||
| "errorlog", "monolog", "custom", "stack"
|
||||
|
|
||||
*/
|
||||
|
||||
'channels' => [
|
||||
|
||||
'stack' => [
|
||||
'driver' => 'stack',
|
||||
'channels' => explode(',', (string) env('LOG_STACK', 'single')),
|
||||
'ignore_exceptions' => false,
|
||||
],
|
||||
|
||||
'single' => [
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'daily' => [
|
||||
'driver' => 'daily',
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'days' => env('LOG_DAILY_DAYS', 14),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'slack' => [
|
||||
'driver' => 'slack',
|
||||
'url' => env('LOG_SLACK_WEBHOOK_URL'),
|
||||
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
|
||||
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
|
||||
'level' => env('LOG_LEVEL', 'critical'),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'papertrail' => [
|
||||
'driver' => 'monolog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
|
||||
'handler_with' => [
|
||||
'host' => env('PAPERTRAIL_URL'),
|
||||
'port' => env('PAPERTRAIL_PORT'),
|
||||
'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'),
|
||||
],
|
||||
'processors' => [PsrLogMessageProcessor::class],
|
||||
],
|
||||
|
||||
'stderr' => [
|
||||
'driver' => 'monolog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'handler' => StreamHandler::class,
|
||||
'handler_with' => [
|
||||
'stream' => 'php://stderr',
|
||||
],
|
||||
'formatter' => env('LOG_STDERR_FORMATTER'),
|
||||
'processors' => [PsrLogMessageProcessor::class],
|
||||
],
|
||||
|
||||
'syslog' => [
|
||||
'driver' => 'syslog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'errorlog' => [
|
||||
'driver' => 'errorlog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'null' => [
|
||||
'driver' => 'monolog',
|
||||
'handler' => NullHandler::class,
|
||||
],
|
||||
|
||||
'emergency' => [
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
118
config/mail.php
Executable file
118
config/mail.php
Executable file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Mailer
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default mailer that is used to send all email
|
||||
| messages unless another mailer is explicitly specified when sending
|
||||
| the message. All additional mailers can be configured within the
|
||||
| "mailers" array. Examples of each type of mailer are provided.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('MAIL_MAILER', 'log'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Mailer Configurations
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure all of the mailers used by your application plus
|
||||
| their respective settings. Several examples have been configured for
|
||||
| you and you are free to add your own as your application requires.
|
||||
|
|
||||
| Laravel supports a variety of mail "transport" drivers that can be used
|
||||
| when delivering an email. You may specify which one you're using for
|
||||
| your mailers below. You may also add additional mailers if needed.
|
||||
|
|
||||
| Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2",
|
||||
| "postmark", "resend", "log", "array",
|
||||
| "failover", "roundrobin"
|
||||
|
|
||||
*/
|
||||
|
||||
'mailers' => [
|
||||
|
||||
'smtp' => [
|
||||
'transport' => 'smtp',
|
||||
'scheme' => env('MAIL_SCHEME'),
|
||||
'url' => env('MAIL_URL'),
|
||||
'host' => env('MAIL_HOST', '127.0.0.1'),
|
||||
'port' => env('MAIL_PORT', 2525),
|
||||
'username' => env('MAIL_USERNAME'),
|
||||
'password' => env('MAIL_PASSWORD'),
|
||||
'timeout' => null,
|
||||
'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url((string) env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
|
||||
],
|
||||
|
||||
'ses' => [
|
||||
'transport' => 'ses',
|
||||
],
|
||||
|
||||
'postmark' => [
|
||||
'transport' => 'postmark',
|
||||
// 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
|
||||
// 'client' => [
|
||||
// 'timeout' => 5,
|
||||
// ],
|
||||
],
|
||||
|
||||
'resend' => [
|
||||
'transport' => 'resend',
|
||||
],
|
||||
|
||||
'sendmail' => [
|
||||
'transport' => 'sendmail',
|
||||
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),
|
||||
],
|
||||
|
||||
'log' => [
|
||||
'transport' => 'log',
|
||||
'channel' => env('MAIL_LOG_CHANNEL'),
|
||||
],
|
||||
|
||||
'array' => [
|
||||
'transport' => 'array',
|
||||
],
|
||||
|
||||
'failover' => [
|
||||
'transport' => 'failover',
|
||||
'mailers' => [
|
||||
'smtp',
|
||||
'log',
|
||||
],
|
||||
'retry_after' => 60,
|
||||
],
|
||||
|
||||
'roundrobin' => [
|
||||
'transport' => 'roundrobin',
|
||||
'mailers' => [
|
||||
'ses',
|
||||
'postmark',
|
||||
],
|
||||
'retry_after' => 60,
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global "From" Address
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may wish for all emails sent by your application to be sent from
|
||||
| the same address. Here you may specify a name and address that is
|
||||
| used globally for all emails that are sent by your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'from' => [
|
||||
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
|
||||
'name' => env('MAIL_FROM_NAME', 'Example'),
|
||||
],
|
||||
|
||||
];
|
||||
112
config/queue.php
Executable file
112
config/queue.php
Executable file
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Queue Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Laravel's queue supports a variety of backends via a single, unified
|
||||
| API, giving you convenient access to each backend using identical
|
||||
| syntax for each. The default queue connection is defined below.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('QUEUE_CONNECTION', 'database'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Queue Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the connection options for every queue backend
|
||||
| used by your application. An example configuration is provided for
|
||||
| each backend supported by Laravel. You're also free to add more.
|
||||
|
|
||||
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
|
||||
'sync' => [
|
||||
'driver' => 'sync',
|
||||
],
|
||||
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'connection' => env('DB_QUEUE_CONNECTION'),
|
||||
'table' => env('DB_QUEUE_TABLE', 'jobs'),
|
||||
'queue' => env('DB_QUEUE', 'default'),
|
||||
'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
'beanstalkd' => [
|
||||
'driver' => 'beanstalkd',
|
||||
'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'),
|
||||
'queue' => env('BEANSTALKD_QUEUE', 'default'),
|
||||
'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90),
|
||||
'block_for' => 0,
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
'sqs' => [
|
||||
'driver' => 'sqs',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
|
||||
'queue' => env('SQS_QUEUE', 'default'),
|
||||
'suffix' => env('SQS_SUFFIX'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
|
||||
'queue' => env('REDIS_QUEUE', 'default'),
|
||||
'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),
|
||||
'block_for' => null,
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Job Batching
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following options configure the database and table that store job
|
||||
| batching information. These options can be updated to any database
|
||||
| connection and table which has been defined by your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'batching' => [
|
||||
'database' => env('DB_CONNECTION', 'sqlite'),
|
||||
'table' => 'job_batches',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Failed Queue Jobs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These options configure the behavior of failed queue job logging so you
|
||||
| can control how and where failed jobs are stored. Laravel ships with
|
||||
| support for storing failed jobs in a simple file or in a database.
|
||||
|
|
||||
| Supported drivers: "database-uuids", "dynamodb", "file", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'failed' => [
|
||||
'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
|
||||
'database' => env('DB_CONNECTION', 'sqlite'),
|
||||
'table' => 'failed_jobs',
|
||||
],
|
||||
|
||||
];
|
||||
38
config/services.php
Executable file
38
config/services.php
Executable file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Third Party Services
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is for storing the credentials for third party services such
|
||||
| as Mailgun, Postmark, AWS and more. This file provides the de facto
|
||||
| location for this type of information, allowing packages to have
|
||||
| a conventional file to locate the various service credentials.
|
||||
|
|
||||
*/
|
||||
|
||||
'postmark' => [
|
||||
'token' => env('POSTMARK_TOKEN'),
|
||||
],
|
||||
|
||||
'resend' => [
|
||||
'key' => env('RESEND_KEY'),
|
||||
],
|
||||
|
||||
'ses' => [
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
],
|
||||
|
||||
'slack' => [
|
||||
'notifications' => [
|
||||
'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
|
||||
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
217
config/session.php
Executable file
217
config/session.php
Executable file
@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Session Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines the default session driver that is utilized for
|
||||
| incoming requests. Laravel supports a variety of storage options to
|
||||
| persist session data. Database storage is a great default choice.
|
||||
|
|
||||
| Supported: "file", "cookie", "database", "memcached",
|
||||
| "redis", "dynamodb", "array"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => env('SESSION_DRIVER', 'database'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Lifetime
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the number of minutes that you wish the session
|
||||
| to be allowed to remain idle before it expires. If you want them
|
||||
| to expire immediately when the browser is closed then you may
|
||||
| indicate that via the expire_on_close configuration option.
|
||||
|
|
||||
*/
|
||||
|
||||
'lifetime' => (int) env('SESSION_LIFETIME', 120),
|
||||
|
||||
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Encryption
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option allows you to easily specify that all of your session data
|
||||
| should be encrypted before it's stored. All encryption is performed
|
||||
| automatically by Laravel and you may use the session like normal.
|
||||
|
|
||||
*/
|
||||
|
||||
'encrypt' => env('SESSION_ENCRYPT', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session File Location
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing the "file" session driver, the session files are placed
|
||||
| on disk. The default storage location is defined here; however, you
|
||||
| are free to provide another location where they should be stored.
|
||||
|
|
||||
*/
|
||||
|
||||
'files' => storage_path('framework/sessions'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" or "redis" session drivers, you may specify a
|
||||
| connection that should be used to manage these sessions. This should
|
||||
| correspond to a connection in your database configuration options.
|
||||
|
|
||||
*/
|
||||
|
||||
'connection' => env('SESSION_CONNECTION'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" session driver, you may specify the table to
|
||||
| be used to store sessions. Of course, a sensible default is defined
|
||||
| for you; however, you're welcome to change this to another table.
|
||||
|
|
||||
*/
|
||||
|
||||
'table' => env('SESSION_TABLE', 'sessions'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using one of the framework's cache driven session backends, you may
|
||||
| define the cache store which should be used to store the session data
|
||||
| between requests. This must match one of your defined cache stores.
|
||||
|
|
||||
| Affects: "dynamodb", "memcached", "redis"
|
||||
|
|
||||
*/
|
||||
|
||||
'store' => env('SESSION_STORE'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Sweeping Lottery
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some session drivers must manually sweep their storage location to get
|
||||
| rid of old sessions from storage. Here are the chances that it will
|
||||
| happen on a given request. By default, the odds are 2 out of 100.
|
||||
|
|
||||
*/
|
||||
|
||||
'lottery' => [2, 100],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the name of the session cookie that is created by
|
||||
| the framework. Typically, you should not need to change this value
|
||||
| since doing so does not grant a meaningful security improvement.
|
||||
|
|
||||
*/
|
||||
|
||||
'cookie' => env(
|
||||
'SESSION_COOKIE',
|
||||
Str::slug(env('APP_NAME', 'laravel')).'-session'
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The session cookie path determines the path for which the cookie will
|
||||
| be regarded as available. Typically, this will be the root path of
|
||||
| your application, but you're free to change this when necessary.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => env('SESSION_PATH', '/'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Domain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines the domain and subdomains the session cookie is
|
||||
| available to. By default, the cookie will be available to the root
|
||||
| domain and all subdomains. Typically, this shouldn't be changed.
|
||||
|
|
||||
*/
|
||||
|
||||
'domain' => env('SESSION_DOMAIN'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTPS Only Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By setting this option to true, session cookies will only be sent back
|
||||
| to the server if the browser has a HTTPS connection. This will keep
|
||||
| the cookie from being sent to you when it can't be done securely.
|
||||
|
|
||||
*/
|
||||
|
||||
'secure' => env('SESSION_SECURE_COOKIE'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTP Access Only
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Setting this value to true will prevent JavaScript from accessing the
|
||||
| value of the cookie and the cookie will only be accessible through
|
||||
| the HTTP protocol. It's unlikely you should disable this option.
|
||||
|
|
||||
*/
|
||||
|
||||
'http_only' => env('SESSION_HTTP_ONLY', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Same-Site Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines how your cookies behave when cross-site requests
|
||||
| take place, and can be used to mitigate CSRF attacks. By default, we
|
||||
| will set this value to "lax" to permit secure cross-site requests.
|
||||
|
|
||||
| See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
|
||||
|
|
||||
| Supported: "lax", "strict", "none", null
|
||||
|
|
||||
*/
|
||||
|
||||
'same_site' => env('SESSION_SAME_SITE', 'lax'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Partitioned Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Setting this value to true will tie the cookie to the top-level site for
|
||||
| a cross-site context. Partitioned cookies are accepted by the browser
|
||||
| when flagged "secure" and the Same-Site attribute is set to "none".
|
||||
|
|
||||
*/
|
||||
|
||||
'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),
|
||||
|
||||
];
|
||||
15
config/trusted-proxies.php
Normal file
15
config/trusted-proxies.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?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',
|
||||
],
|
||||
];
|
||||
40
create-admin.php
Executable file
40
create-admin.php
Executable file
@ -0,0 +1,40 @@
|
||||
<?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>";
|
||||
}
|
||||
?>
|
||||
BIN
database.sqlite
Executable file
BIN
database.sqlite
Executable file
Binary file not shown.
1
database/.gitignore
vendored
Normal file
1
database/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.sqlite*
|
||||
44
database/factories/UserFactory.php
Executable file
44
database/factories/UserFactory.php
Executable file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
|
||||
*/
|
||||
class UserFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The current password being used by the factory.
|
||||
*/
|
||||
protected static ?string $password;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => fake()->name(),
|
||||
'email' => fake()->unique()->safeEmail(),
|
||||
'email_verified_at' => now(),
|
||||
'password' => static::$password ??= Hash::make('password'),
|
||||
'remember_token' => Str::random(10),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the model's email address should be unverified.
|
||||
*/
|
||||
public function unverified(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
49
database/migrations/0001_01_01_000000_create_users_table.php
Executable file
49
database/migrations/0001_01_01_000000_create_users_table.php
Executable file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('email')->unique();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('password');
|
||||
$table->rememberToken();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('password_reset_tokens', function (Blueprint $table) {
|
||||
$table->string('email')->primary();
|
||||
$table->string('token');
|
||||
$table->timestamp('created_at')->nullable();
|
||||
});
|
||||
|
||||
Schema::create('sessions', function (Blueprint $table) {
|
||||
$table->string('id')->primary();
|
||||
$table->foreignId('user_id')->nullable()->index();
|
||||
$table->string('ip_address', 45)->nullable();
|
||||
$table->text('user_agent')->nullable();
|
||||
$table->longText('payload');
|
||||
$table->integer('last_activity')->index();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('users');
|
||||
Schema::dropIfExists('password_reset_tokens');
|
||||
Schema::dropIfExists('sessions');
|
||||
}
|
||||
};
|
||||
35
database/migrations/0001_01_01_000001_create_cache_table.php
Executable file
35
database/migrations/0001_01_01_000001_create_cache_table.php
Executable file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('cache', function (Blueprint $table) {
|
||||
$table->string('key')->primary();
|
||||
$table->mediumText('value');
|
||||
$table->integer('expiration');
|
||||
});
|
||||
|
||||
Schema::create('cache_locks', function (Blueprint $table) {
|
||||
$table->string('key')->primary();
|
||||
$table->string('owner');
|
||||
$table->integer('expiration');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('cache');
|
||||
Schema::dropIfExists('cache_locks');
|
||||
}
|
||||
};
|
||||
57
database/migrations/0001_01_01_000002_create_jobs_table.php
Executable file
57
database/migrations/0001_01_01_000002_create_jobs_table.php
Executable file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('jobs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('queue')->index();
|
||||
$table->longText('payload');
|
||||
$table->unsignedTinyInteger('attempts');
|
||||
$table->unsignedInteger('reserved_at')->nullable();
|
||||
$table->unsignedInteger('available_at');
|
||||
$table->unsignedInteger('created_at');
|
||||
});
|
||||
|
||||
Schema::create('job_batches', function (Blueprint $table) {
|
||||
$table->string('id')->primary();
|
||||
$table->string('name');
|
||||
$table->integer('total_jobs');
|
||||
$table->integer('pending_jobs');
|
||||
$table->integer('failed_jobs');
|
||||
$table->longText('failed_job_ids');
|
||||
$table->mediumText('options')->nullable();
|
||||
$table->integer('cancelled_at')->nullable();
|
||||
$table->integer('created_at');
|
||||
$table->integer('finished_at')->nullable();
|
||||
});
|
||||
|
||||
Schema::create('failed_jobs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uuid')->unique();
|
||||
$table->text('connection');
|
||||
$table->text('queue');
|
||||
$table->longText('payload');
|
||||
$table->longText('exception');
|
||||
$table->timestamp('failed_at')->useCurrent();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('jobs');
|
||||
Schema::dropIfExists('job_batches');
|
||||
Schema::dropIfExists('failed_jobs');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('manufacturers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->unique(); // Name des Herstellers (eindeutig)
|
||||
$table->text('description')->nullable(); // Beschreibung des Herstellers
|
||||
$table->string('website')->nullable(); // Website des Herstellers
|
||||
$table->string('country')->nullable(); // Land des Herstellers
|
||||
$table->timestamps();
|
||||
|
||||
// Index für schnelle Suche
|
||||
$table->index('name');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('manufacturers');
|
||||
}
|
||||
};
|
||||
33
database/migrations/2025_08_10_020520_create_nail_polishes_table.php
Executable file
33
database/migrations/2025_08_10_020520_create_nail_polishes_table.php
Executable file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('nail_polishes', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name'); // Name des Nagellacks
|
||||
$table->string('number'); // Nummer des Nagellacks
|
||||
$table->string('image_path')->nullable(); // Pfad zum Bild
|
||||
$table->timestamps();
|
||||
|
||||
// Index für schnelle Suche
|
||||
$table->index(['name', 'number']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('nail_polishes');
|
||||
}
|
||||
};
|
||||
32
database/migrations/2025_08_10_020523_create_user_nail_polishes_table.php
Executable file
32
database/migrations/2025_08_10_020523_create_user_nail_polishes_table.php
Executable file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('user_nail_polishes', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->constrained()->onDelete('cascade');
|
||||
$table->foreignId('nail_polish_id')->constrained()->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
|
||||
// Verhindert doppelte Einträge
|
||||
$table->unique(['user_id', 'nail_polish_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('user_nail_polishes');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('nail_polishes', function (Blueprint $table) {
|
||||
$table->foreignId('manufacturer_id')->nullable()->after('number')->constrained()->onDelete('set null');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('nail_polishes', function (Blueprint $table) {
|
||||
$table->dropForeign(['manufacturer_id']);
|
||||
$table->dropColumn('manufacturer_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
23
database/seeders/DatabaseSeeder.php
Executable file
23
database/seeders/DatabaseSeeder.php
Executable file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\User;
|
||||
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed the application's database.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
// User::factory(10)->create();
|
||||
|
||||
User::factory()->create([
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
}
|
||||
}
|
||||
118
debug-405-error.php
Normal file
118
debug-405-error.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?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";
|
||||
?>
|
||||
131
debug-500-error.php
Normal file
131
debug-500-error.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?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";
|
||||
?>
|
||||
194
debug-image-upload.php
Normal file
194
debug-image-upload.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?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";
|
||||
?>
|
||||
202
debug-logout-detailed.php
Normal file
202
debug-logout-detailed.php
Normal file
@ -0,0 +1,202 @@
|
||||
<?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
Normal file
218
debug-logout.php
Normal file
@ -0,0 +1,218 @@
|
||||
<?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";
|
||||
?>
|
||||
67
deploy-manufacturer-feature.sh
Executable file
67
deploy-manufacturer-feature.sh
Executable file
@ -0,0 +1,67 @@
|
||||
#!/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!"
|
||||
64
deploy-sqlite.sh
Executable file
64
deploy-sqlite.sh
Executable file
@ -0,0 +1,64 @@
|
||||
#!/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
Executable file
43
deploy.sh
Executable file
@ -0,0 +1,43 @@
|
||||
#!/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"
|
||||
111
deployment-checklist.md
Executable file
111
deployment-checklist.md
Executable file
@ -0,0 +1,111 @@
|
||||
# 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
|
||||
66
emergency-apache-fix.sh
Executable file
66
emergency-apache-fix.sh
Executable file
@ -0,0 +1,66 @@
|
||||
#!/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"
|
||||
55
env-production-example.txt
Executable file
55
env-production-example.txt
Executable file
@ -0,0 +1,55 @@
|
||||
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}"
|
||||
64
env-sqlite-example.txt
Executable file
64
env-sqlite-example.txt
Executable file
@ -0,0 +1,64 @@
|
||||
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}"
|
||||
55
fix-405-error.sh
Executable file
55
fix-405-error.sh
Executable file
@ -0,0 +1,55 @@
|
||||
#!/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"
|
||||
284
fix-admin-controller-email.php
Normal file
284
fix-admin-controller-email.php
Normal file
@ -0,0 +1,284 @@
|
||||
<?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";
|
||||
?>
|
||||
291
fix-admin-layout.php
Normal file
291
fix-admin-layout.php
Normal file
@ -0,0 +1,291 @@
|
||||
<?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";
|
||||
?>
|
||||
120
fix-admin-role-database.php
Normal file
120
fix-admin-role-database.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?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";
|
||||
}
|
||||
?>
|
||||
54
fix-admin-role.php
Executable file
54
fix-admin-role.php
Executable file
@ -0,0 +1,54 @@
|
||||
<?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";
|
||||
}
|
||||
?>
|
||||
165
fix-admin-routes.php
Normal file
165
fix-admin-routes.php
Normal file
@ -0,0 +1,165 @@
|
||||
<?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";
|
||||
?>
|
||||
158
fix-admin-view.php
Normal file
158
fix-admin-view.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?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";
|
||||
?>
|
||||
50
fix-all-405-errors.sh
Normal file
50
fix-all-405-errors.sh
Normal file
@ -0,0 +1,50 @@
|
||||
#!/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"
|
||||
97
fix-all-forms-https.sh
Executable file
97
fix-all-forms-https.sh
Executable file
@ -0,0 +1,97 @@
|
||||
#!/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"
|
||||
189
fix-all-safari-warnings.sh
Executable file
189
fix-all-safari-warnings.sh
Executable file
@ -0,0 +1,189 @@
|
||||
#!/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)"
|
||||
67
fix-apache-documentroot.sh
Executable file
67
fix-apache-documentroot.sh
Executable file
@ -0,0 +1,67 @@
|
||||
#!/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"
|
||||
103
fix-apache-headers.sh
Executable file
103
fix-apache-headers.sh
Executable file
@ -0,0 +1,103 @@
|
||||
#!/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"
|
||||
27
fix-appserviceprovider-syntax.sh
Normal file
27
fix-appserviceprovider-syntax.sh
Normal file
@ -0,0 +1,27 @@
|
||||
#!/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"
|
||||
48
fix-https-config.sh
Executable file
48
fix-https-config.sh
Executable file
@ -0,0 +1,48 @@
|
||||
#!/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"
|
||||
70
fix-https-form-security.sh
Executable file
70
fix-https-form-security.sh
Executable file
@ -0,0 +1,70 @@
|
||||
#!/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"
|
||||
55
fix-image-display.sh
Executable file
55
fix-image-display.sh
Executable file
@ -0,0 +1,55 @@
|
||||
#!/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"
|
||||
49
fix-image-upload-fallback.php
Normal file
49
fix-image-upload-fallback.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?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;
|
||||
}
|
||||
?>
|
||||
282
fix-image-upload-final.php
Normal file
282
fix-image-upload-final.php
Normal file
@ -0,0 +1,282 @@
|
||||
<?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";
|
||||
?>
|
||||
222
fix-image-upload-simple.php
Normal file
222
fix-image-upload-simple.php
Normal file
@ -0,0 +1,222 @@
|
||||
<?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";
|
||||
?>
|
||||
60
fix-image-urls.php
Normal file
60
fix-image-urls.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?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)
|
||||
?>
|
||||
53
fix-laravel-setup.sh
Executable file
53
fix-laravel-setup.sh
Executable file
@ -0,0 +1,53 @@
|
||||
#!/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"
|
||||
110
fix-logout-final.php
Normal file
110
fix-logout-final.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?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";
|
||||
?>
|
||||
194
fix-logout-route.php
Normal file
194
fix-logout-route.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?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";
|
||||
?>
|
||||
147
fix-logout-simple-2.php
Normal file
147
fix-logout-simple-2.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?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";
|
||||
?>
|
||||
81
fix-logout-simple.php
Normal file
81
fix-logout-simple.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?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
Normal file
277
fix-logout.php
Normal file
@ -0,0 +1,277 @@
|
||||
<?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";
|
||||
?>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user