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