commit 2a15995cbb9f6179f5e08406b3811571e16a8a3a Author: Housemann <40449280+Housemann@users.noreply.github.com> Date: Sun Aug 10 18:09:07 2025 +0200 Script erstellt diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8f0de65 --- /dev/null +++ b/.editorconfig @@ -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 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..35db1dd --- /dev/null +++ b/.env.example @@ -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}" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fcb21d3 --- /dev/null +++ b/.gitattributes @@ -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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b71b1ea --- /dev/null +++ b/.gitignore @@ -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 diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..127c6c1 --- /dev/null +++ b/.htaccess @@ -0,0 +1,30 @@ +# Redirect to public directory +RewriteEngine On +RewriteRule ^$ public/ [L] +RewriteRule (.*) public/$1 [L] + +# Prevent directory listing +Options -Indexes + +# Security headers + + Header always set X-Content-Type-Options nosniff + Header always set X-Frame-Options DENY + Header always set X-XSS-Protection "1; mode=block" + + +# Protect sensitive files + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100755 index 0000000..ea2d32b --- /dev/null +++ b/DEPLOYMENT.md @@ -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 + + Order allow,deny + Deny from all + +``` + +### MySQL-spezifische Sicherheit +```apache +# .htaccess bereits konfiguriert +# Zusätzliche Sicherheit: + + Order allow,deny + Deny from all + +``` + +## 📱 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! 🎉** diff --git a/NEONAIL_PROJECT_PROMPT.md b/NEONAIL_PROJECT_PROMPT.md new file mode 100755 index 0000000..14b5623 --- /dev/null +++ b/NEONAIL_PROJECT_PROMPT.md @@ -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 diff --git a/README.md b/README.md new file mode 100755 index 0000000..970bf92 --- /dev/null +++ b/README.md @@ -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 +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. diff --git a/WEBSPACE-SETUP.md b/WEBSPACE-SETUP.md new file mode 100755 index 0000000..db3c52a --- /dev/null +++ b/WEBSPACE-SETUP.md @@ -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 + + ServerName ihre-domain.de + DocumentRoot /var/www/neonail/public + + + AllowOverride All + Require all granted + + +``` + +**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 + '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! 🎉** diff --git a/activate-admin-role.sh b/activate-admin-role.sh new file mode 100755 index 0000000..cc9395a --- /dev/null +++ b/activate-admin-role.sh @@ -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" diff --git a/add-admin-role-migration.php b/add-admin-role-migration.php new file mode 100644 index 0000000..ee1388a --- /dev/null +++ b/add-admin-role-migration.php @@ -0,0 +1,17 @@ + diff --git a/admin-check.php b/admin-check.php new file mode 100755 index 0000000..5b92ec9 --- /dev/null +++ b/admin-check.php @@ -0,0 +1,47 @@ +🔍 Admin-User Check"; + +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 "

Benutzer in der Datenbank:

"; + if ($users->count() > 0) { + echo "

{$users->count()} Benutzer gefunden

"; + + foreach ($users as $user) { + echo "
"; + echo "ID: {$user->id}
"; + echo "Name: {$user->name}
"; + echo "Email: {$user->email}
"; + echo "Erstellt: {$user->created_at}
"; + echo "
"; + } + + // Admin-User prüfen + $admin = \App\Models\User::where('email', 'admin@neonail.com')->first(); + if ($admin) { + echo "

👑 Admin-User gefunden!

"; + echo "

Sie können sich mit admin@neonail.com anmelden.

"; + echo "

🚀 Zur Anwendung

"; + } + + } else { + echo "

❌ Keine Benutzer gefunden

"; + 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')]);"; + } + +} catch (Exception $e) { + echo "

❌ Fehler:

"; + echo "

{$e->getMessage()}

"; +} +?> diff --git a/apache-config.txt b/apache-config.txt new file mode 100755 index 0000000..ee2f31d --- /dev/null +++ b/apache-config.txt @@ -0,0 +1,28 @@ +# Apache Virtual Host Konfiguration für NeoNail DB +# Datei: /etc/apache2/sites-available/neonail.conf + + + ServerName 192.168.30.81 + DocumentRoot /var/www/html/public + + + AllowOverride All + Require all granted + + + # Sicherheit - Zugriff auf sensible Dateien verhindern + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + ErrorLog ${APACHE_LOG_DIR}/neonail_error.log + CustomLog ${APACHE_LOG_DIR}/neonail_access.log combined + diff --git a/apache-diagnose.sh b/apache-diagnose.sh new file mode 100755 index 0000000..6cdc98d --- /dev/null +++ b/apache-diagnose.sh @@ -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" diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php new file mode 100755 index 0000000..c6b0c37 --- /dev/null +++ b/app/Http/Controllers/AdminController.php @@ -0,0 +1,212 @@ +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" + )); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php new file mode 100755 index 0000000..24b8545 --- /dev/null +++ b/app/Http/Controllers/Auth/LoginController.php @@ -0,0 +1,43 @@ +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('/'); + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php new file mode 100755 index 0000000..8677cd5 --- /dev/null +++ b/app/Http/Controllers/Controller.php @@ -0,0 +1,8 @@ +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); + } +} diff --git a/app/Http/Controllers/NailPolishController.php b/app/Http/Controllers/NailPolishController.php new file mode 100755 index 0000000..f87877a --- /dev/null +++ b/app/Http/Controllers/NailPolishController.php @@ -0,0 +1,165 @@ +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')); + } +} diff --git a/app/Http/Controllers/UserNailPolishController.php b/app/Http/Controllers/UserNailPolishController.php new file mode 100755 index 0000000..15811e2 --- /dev/null +++ b/app/Http/Controllers/UserNailPolishController.php @@ -0,0 +1,186 @@ +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")); + } +} \ No newline at end of file diff --git a/app/Http/Middleware/AdminMiddleware.php b/app/Http/Middleware/AdminMiddleware.php new file mode 100755 index 0000000..ee06267 --- /dev/null +++ b/app/Http/Middleware/AdminMiddleware.php @@ -0,0 +1,25 @@ +check() || !auth()->user()->isAdmin()) { + abort(403, 'Zugriff verweigert. Admin-Berechtigung erforderlich.'); + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php new file mode 100755 index 0000000..f222ff5 --- /dev/null +++ b/app/Http/Middleware/Authenticate.php @@ -0,0 +1,29 @@ +check()) { + return redirect()->route('login'); + } + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php new file mode 100755 index 0000000..f80ebfb --- /dev/null +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -0,0 +1,29 @@ +check()) { + return redirect()->route('user-nail-polishes.index'); + } + } + + return $next($request); + } +} diff --git a/app/Models/Manufacturer.php b/app/Models/Manufacturer.php new file mode 100644 index 0000000..2a6dba6 --- /dev/null +++ b/app/Models/Manufacturer.php @@ -0,0 +1,65 @@ +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(); + } +} diff --git a/app/Models/NailPolish.php b/app/Models/NailPolish.php new file mode 100755 index 0000000..9f37a43 --- /dev/null +++ b/app/Models/NailPolish.php @@ -0,0 +1,48 @@ +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}%"); + } +} diff --git a/app/Models/User.php b/app/Models/User.php new file mode 100755 index 0000000..385a0f6 --- /dev/null +++ b/app/Models/User.php @@ -0,0 +1,83 @@ + */ + use HasFactory, Notifiable; + + /** + * The attributes that are mass assignable. + * + * @var list + */ + protected $fillable = [ + 'name', + 'email', + 'password', + 'is_admin', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var list + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * Get the attributes that should be cast. + * + * @return array + */ + 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(); + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php new file mode 100755 index 0000000..fd52d92 --- /dev/null +++ b/app/Providers/AppServiceProvider.php @@ -0,0 +1,27 @@ +handleCommand(new ArgvInput); + +exit($status); diff --git a/bootstrap/app.php b/bootstrap/app.php new file mode 100755 index 0000000..bc6a11f --- /dev/null +++ b/bootstrap/app.php @@ -0,0 +1,24 @@ +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(); diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/bootstrap/providers.php b/bootstrap/providers.php new file mode 100755 index 0000000..4dcc88a --- /dev/null +++ b/bootstrap/providers.php @@ -0,0 +1,6 @@ +make('Illuminate\Contracts\Console\Kernel')->bootstrap(); + + echo "

🔍 Admin-User Status

"; + + // Alle User anzeigen + $users = User::all(); + + if ($users->count() > 0) { + echo "

✅ Benutzer gefunden:

"; + echo ""; + echo ""; + + foreach ($users as $user) { + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + } + echo "
IDNameEmailErstellt
{$user->id}{$user->name}{$user->email}{$user->created_at}
"; + + // Admin-User finden + $admin = User::where('email', 'admin@neonail.com')->first(); + if ($admin) { + echo "

👑 Admin-User gefunden:

"; + echo "

Name: {$admin->name}

"; + echo "

Email: {$admin->email}

"; + echo "

ID: {$admin->id}

"; + } + + } else { + echo "

❌ Keine Benutzer gefunden

"; + echo "

Bitte 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')]);"; + } + +} catch (Exception $e) { + echo "

❌ Fehler:

"; + echo "

{$e->getMessage()}

"; +} +?> diff --git a/check-laravel-logs.sh b/check-laravel-logs.sh new file mode 100755 index 0000000..423725d --- /dev/null +++ b/check-laravel-logs.sh @@ -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" diff --git a/check-user-collection.php b/check-user-collection.php new file mode 100644 index 0000000..4132901 --- /dev/null +++ b/check-user-collection.php @@ -0,0 +1,77 @@ +make('Illuminate\Contracts\Console\Kernel')->bootstrap(); + + echo "

🔍 User-Sammlung prüfen

"; + + // Admin-User finden + $admin = User::where('email', 'admin@neonail.com')->first(); + + if ($admin) { + echo "

👑 Admin-User gefunden:

"; + echo "

Name: {$admin->name}

"; + echo "

Email: {$admin->email}

"; + echo "

ID: {$admin->id}

"; + + // Sammlung prüfen + $collection = $admin->nailPolishes; + + echo "

📦 Sammlung ({$collection->count()} Lacke):

"; + + if ($collection->count() > 0) { + echo ""; + echo ""; + + foreach ($collection as $polish) { + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + } + echo "
IDNameNummerBild
{$polish->id}{$polish->name}{$polish->number}" . ($polish->image_path ? "✅" : "❌") . "
"; + } else { + echo "

❌ Keine Lacke in der Sammlung

"; + } + + // Alle Lacke prüfen + echo "

🗄️ Alle Lacke in der Datenbank:

"; + $allPolishes = NailPolish::all(); + + if ($allPolishes->count() > 0) { + echo ""; + echo ""; + + foreach ($allPolishes as $polish) { + $inCollection = $admin->nailPolishes()->where('nail_polish_id', $polish->id)->exists(); + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + } + echo "
IDNameNummerBildIn Sammlung
{$polish->id}{$polish->name}{$polish->number}" . ($polish->image_path ? "✅" : "❌") . "" . ($inCollection ? "✅" : "❌") . "
"; + } else { + echo "

❌ Keine Lacke in der Datenbank

"; + } + + } else { + echo "

❌ Admin-User nicht gefunden

"; + } + +} catch (Exception $e) { + echo "

❌ Fehler:

"; + echo "

{$e->getMessage()}

"; +} +?> diff --git a/clear-route-cache.sh b/clear-route-cache.sh new file mode 100755 index 0000000..1925be9 --- /dev/null +++ b/clear-route-cache.sh @@ -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" diff --git a/complete-fix.sh b/complete-fix.sh new file mode 100755 index 0000000..c36c51d --- /dev/null +++ b/complete-fix.sh @@ -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')]);" diff --git a/composer.json b/composer.json new file mode 100755 index 0000000..b7e8d20 --- /dev/null +++ b/composer.json @@ -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 +} diff --git a/composer.lock b/composer.lock new file mode 100755 index 0000000..003c86d --- /dev/null +++ b/composer.lock @@ -0,0 +1,8424 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "97658dfcf2c6faba669b2fb988db0a69", + "packages": [ + { + "name": "brick/math", + "version": "0.13.1", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "6.8.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.13.1" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2025-03-29T13:50:30+00:00" + }, + { + "name": "carbonphp/carbon-doctrine-types", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/dbal": "<4.0.0 || >=5.0.0" + }, + "require-dev": { + "doctrine/dbal": "^4.0.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2024-02-09T16:56:22+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" + }, + "time": "2024-07-08T12:26:09+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.10", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2024-02-18T20:23:39+00:00" + }, + { + "name": "doctrine/lexer", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:56:58+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "8c784d071debd117328803d86b2097615b457500" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2024-10-09T13:47:03+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2025-03-06T22:45:56+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-10-12T05:21:21+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:45:45+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:37:11+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:27:01+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.7.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.7.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2025-03-27T12:30:47+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.4" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2025-02-03T10:55:03+00:00" + }, + { + "name": "intervention/gif", + "version": "4.2.2", + "source": { + "type": "git", + "url": "https://github.com/Intervention/gif.git", + "reference": "5999eac6a39aa760fb803bc809e8909ee67b451a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Intervention/gif/zipball/5999eac6a39aa760fb803bc809e8909ee67b451a", + "reference": "5999eac6a39aa760fb803bc809e8909ee67b451a", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "slevomat/coding-standard": "~8.0", + "squizlabs/php_codesniffer": "^3.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Intervention\\Gif\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@intervention.io", + "homepage": "https://intervention.io/" + } + ], + "description": "Native PHP GIF Encoder/Decoder", + "homepage": "https://github.com/intervention/gif", + "keywords": [ + "animation", + "gd", + "gif", + "image" + ], + "support": { + "issues": "https://github.com/Intervention/gif/issues", + "source": "https://github.com/Intervention/gif/tree/4.2.2" + }, + "funding": [ + { + "url": "https://paypal.me/interventionio", + "type": "custom" + }, + { + "url": "https://github.com/Intervention", + "type": "github" + }, + { + "url": "https://ko-fi.com/interventionphp", + "type": "ko_fi" + } + ], + "time": "2025-03-29T07:46:21+00:00" + }, + { + "name": "intervention/image", + "version": "3.11.4", + "source": { + "type": "git", + "url": "https://github.com/Intervention/image.git", + "reference": "8c49eb21a6d2572532d1bc425964264f3e496846" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Intervention/image/zipball/8c49eb21a6d2572532d1bc425964264f3e496846", + "reference": "8c49eb21a6d2572532d1bc425964264f3e496846", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "intervention/gif": "^4.2", + "php": "^8.1" + }, + "require-dev": { + "mockery/mockery": "^1.6", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "slevomat/coding-standard": "~8.0", + "squizlabs/php_codesniffer": "^3.8" + }, + "suggest": { + "ext-exif": "Recommended to be able to read EXIF data properly." + }, + "type": "library", + "autoload": { + "psr-4": { + "Intervention\\Image\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@intervention.io", + "homepage": "https://intervention.io/" + } + ], + "description": "PHP image manipulation", + "homepage": "https://image.intervention.io/", + "keywords": [ + "gd", + "image", + "imagick", + "resize", + "thumbnail", + "watermark" + ], + "support": { + "issues": "https://github.com/Intervention/image/issues", + "source": "https://github.com/Intervention/image/tree/3.11.4" + }, + "funding": [ + { + "url": "https://paypal.me/interventionio", + "type": "custom" + }, + { + "url": "https://github.com/Intervention", + "type": "github" + }, + { + "url": "https://ko-fi.com/interventionphp", + "type": "ko_fi" + } + ], + "time": "2025-07-30T13:13:19+00:00" + }, + { + "name": "laravel/framework", + "version": "v12.22.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "d33ee45184126f32f593d4b809a846ed88a1dc43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/d33ee45184126f32f593d4b809a846ed88a1dc43", + "reference": "d33ee45184126f32f593d4b809a846ed88a1dc43", + "shasum": "" + }, + "require": { + "brick/math": "^0.11|^0.12|^0.13", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.4", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.3", + "guzzlehttp/guzzle": "^7.8.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/prompts": "^0.3.0", + "laravel/serializable-closure": "^1.3|^2.0", + "league/commonmark": "^2.7", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", + "league/uri": "^7.5.1", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^3.8.4", + "nunomaduro/termwind": "^2.0", + "php": "^8.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^7.2.0", + "symfony/error-handler": "^7.2.0", + "symfony/finder": "^7.2.0", + "symfony/http-foundation": "^7.2.0", + "symfony/http-kernel": "^7.2.0", + "symfony/mailer": "^7.2.0", + "symfony/mime": "^7.2.0", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.2.0", + "symfony/routing": "^7.2.0", + "symfony/uid": "^7.2.0", + "symfony/var-dumper": "^7.2.0", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/log-implementation": "1.0|2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version", + "spatie/once": "*" + }, + "require-dev": { + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.322.9", + "ext-gmp": "*", + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "laravel/pint": "^1.18", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^10.0.0", + "pda/pheanstalk": "^5.0.6|^7.0.0", + "php-http/discovery": "^1.15", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", + "predis/predis": "^2.3|^3.0", + "resend/resend-php": "^0.10.0", + "symfony/cache": "^7.2.0", + "symfony/http-client": "^7.2.0", + "symfony/psr-http-message-bridge": "^7.2.0", + "symfony/translation": "^7.2.0" + }, + "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", + "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", + "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", + "mockery/mockery": "Required to use mocking (^1.6).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1).", + "predis/predis": "Required to use the predis connector (^2.3|^3.0).", + "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "12.x-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Collections/functions.php", + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Filesystem/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2025-08-08T13:58:03+00:00" + }, + { + "name": "laravel/prompts", + "version": "v0.3.6", + "source": { + "type": "git", + "url": "https://github.com/laravel/prompts.git", + "reference": "86a8b692e8661d0fb308cec64f3d176821323077" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/prompts/zipball/86a8b692e8661d0fb308cec64f3d176821323077", + "reference": "86a8b692e8661d0fb308cec64f3d176821323077", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "ext-mbstring": "*", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, + "require-dev": { + "illuminate/collections": "^10.0|^11.0|^12.0", + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3|^3.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Laravel\\Prompts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Add beautiful and user-friendly forms to your command-line applications.", + "support": { + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.3.6" + }, + "time": "2025-07-07T14:17:42+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v2.0.4", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "illuminate/support": "^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36|^3.0", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2025-03-19T13:51:03+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.10.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.11.1|^0.12.0", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.8|^9.3.3|^10.0" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0)." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.10.1" + }, + "time": "2025-01-27T14:24:01+00:00" + }, + { + "name": "laravel/ui", + "version": "v4.6.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/ui.git", + "reference": "7d6ffa38d79f19c9b3e70a751a9af845e8f41d88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/ui/zipball/7d6ffa38d79f19c9b3e70a751a9af845e8f41d88", + "reference": "7d6ffa38d79f19c9b3e70a751a9af845e8f41d88", + "shasum": "" + }, + "require": { + "illuminate/console": "^9.21|^10.0|^11.0|^12.0", + "illuminate/filesystem": "^9.21|^10.0|^11.0|^12.0", + "illuminate/support": "^9.21|^10.0|^11.0|^12.0", + "illuminate/validation": "^9.21|^10.0|^11.0|^12.0", + "php": "^8.0", + "symfony/console": "^6.0|^7.0" + }, + "require-dev": { + "orchestra/testbench": "^7.35|^8.15|^9.0|^10.0", + "phpunit/phpunit": "^9.3|^10.4|^11.5" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Ui\\UiServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Ui\\": "src/", + "Illuminate\\Foundation\\Auth\\": "auth-backend/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel UI utilities and presets.", + "keywords": [ + "laravel", + "ui" + ], + "support": { + "source": "https://github.com/laravel/ui/tree/v4.6.1" + }, + "time": "2025-01-28T15:15:29+00:00" + }, + { + "name": "league/commonmark", + "version": "2.7.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "10732241927d3971d28e7ea7b5712721fa2296ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca", + "reference": "10732241927d3971d28e7ea7b5712721fa2296ca", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.31.1", + "commonmark/commonmark.js": "0.31.1", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2025-07-20T12:47:49+00:00" + }, + { + "name": "league/config", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "support": { + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } + ], + "time": "2022-12-11T20:36:23+00:00" + }, + { + "name": "league/flysystem", + "version": "3.30.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3|^2", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2|^2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.30.0" + }, + "time": "2025-06-25T13:29:59+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.30.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0" + }, + "time": "2025-05-21T10:34:19+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.16.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2024-09-21T08:32:55+00:00" + }, + { + "name": "league/uri", + "version": "7.5.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "81fb5145d2644324614cc532b28efd0215bda430" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "shasum": "" + }, + "require": { + "league/uri-interfaces": "^7.5", + "php": "^8.1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.5.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:40:02+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "7.5.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^8.1", + "psr/http-factory": "^1", + "psr/http-message": "^1.1 || ^2.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common interfaces and classes for URI representation and interaction", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:18:47+00:00" + }, + { + "name": "monolog/monolog", + "version": "3.9.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2025-03-24T10:02:05+00:00" + }, + { + "name": "nesbot/carbon", + "version": "3.10.2", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24", + "reference": "76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24", + "shasum": "" + }, + "require": { + "carbonphp/carbon-doctrine-types": "<100.0", + "ext-json": "*", + "php": "^8.1", + "psr/clock": "^1.0", + "symfony/clock": "^6.3.12 || ^7.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.75.0", + "kylekatarnls/multi-tester": "^2.5.3", + "phpmd/phpmd": "^2.15.0", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.17", + "phpunit/phpunit": "^10.5.46", + "squizlabs/php_codesniffer": "^3.13.0" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2025-08-02T09:36:06+00:00" + }, + { + "name": "nette/schema", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.4" + }, + "require-dev": { + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.3.2" + }, + "time": "2024-10-06T23:10:23+00:00" + }, + { + "name": "nette/utils", + "version": "v4.0.8", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede", + "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.0.8" + }, + "time": "2025-08-06T21:43:34+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.6.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/221b0d0fdf1369c71047ad1d18bb5880017bbc56", + "reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.0" + }, + "time": "2025-07-27T20:03:57+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.2", + "symfony/console": "^7.2.6" + }, + "require-dev": { + "illuminate/console": "^11.44.7", + "laravel/pint": "^1.22.0", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0 || ^3.8.2", + "phpstan/phpstan": "^1.12.25", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.2.6", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "support": { + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2025-05-08T08:14:37+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.3", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:41:07+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.12.10", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "6e80abe6f2257121f1eb9a4c55bf29d921025b22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/6e80abe6f2257121f1eb9a4c55bf29d921025b22", + "reference": "6e80abe6f2257121f1eb9a4c55bf29d921025b22", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false, + "forward-command": false + }, + "branch-alias": { + "dev-main": "0.12.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "https://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.12.10" + }, + "time": "2025-08-04T12:39:37+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.1.1" + }, + "time": "2025-03-22T05:38:12+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.9.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.25", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.9.0" + }, + "time": "2025-06-25T14:20:11+00:00" + }, + { + "name": "smalot/pdfparser", + "version": "v2.12.0", + "source": { + "type": "git", + "url": "https://github.com/smalot/pdfparser.git", + "reference": "8440edbf58c8596074e78ada38dcb0bd041a5948" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/smalot/pdfparser/zipball/8440edbf58c8596074e78ada38dcb0bd041a5948", + "reference": "8440edbf58c8596074e78ada38dcb0bd041a5948", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-zlib": "*", + "php": ">=7.1", + "symfony/polyfill-mbstring": "^1.18" + }, + "type": "library", + "autoload": { + "psr-0": { + "Smalot\\PdfParser\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Sebastien MALOT", + "email": "sebastien@malot.fr" + } + ], + "description": "Pdf parser library. Can read and extract information from pdf file.", + "homepage": "https://www.pdfparser.org", + "keywords": [ + "extract", + "parse", + "parser", + "pdf", + "text" + ], + "support": { + "issues": "https://github.com/smalot/pdfparser/issues", + "source": "https://github.com/smalot/pdfparser/tree/v2.12.0" + }, + "time": "2025-03-31T13:16:09+00:00" + }, + { + "name": "symfony/clock", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/console", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "5f360ebc65c55265a74d23d7fe27f957870158a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/5f360ebc65c55265a74d23d7fe27f957870158a1", + "reference": "5f360ebc65c55265a74d23d7fe27f957870158a1", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^7.2" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-30T17:13:41+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/0b31a944fcd8759ae294da4d2808cbc53aebd0c3", + "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-07T08:17:57+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-22T09:11:45+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T13:41:35+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "6877c122b3a6cc3695849622720054f6e6fa5fa6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6877c122b3a6cc3695849622720054f6e6fa5fa6", + "reference": "6877c122b3a6cc3695849622720054f6e6fa5fa6", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + }, + "require-dev": { + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/clock": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-10T08:47:49+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "6ecc895559ec0097e221ed2fd5eb44d5fede083c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6ecc895559ec0097e221ed2fd5eb44d5fede083c", + "reference": "6ecc895559ec0097e221ed2fd5eb44d5fede083c", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.3", + "symfony/http-foundation": "^7.3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<6.4", + "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/translation": "<6.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.12" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-31T10:45:04+00:00" + }, + { + "name": "symfony/mailer", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "d43e84d9522345f96ad6283d5dfccc8c1cfc299b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/d43e84d9522345f96ad6283d5dfccc8c1cfc299b", + "reference": "d43e84d9522345f96ad6283d5dfccc8c1cfc299b", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.2", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/mime": "^7.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/twig-bridge": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T11:36:08+00:00" + }, + { + "name": "symfony/mime", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/e0a0f859148daf1edf6c60b398eb40bfc96697d1", + "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T13:41:35+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-10T14:38:51+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-23T08:48:59+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-02T08:10:11+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-17T09:11:12+00:00" + }, + { + "name": "symfony/routing", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/7614b8ca5fa89b9cd233e21b627bfc5774f586e4", + "reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T11:36:08+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-25T09:37:31+00:00" + }, + { + "name": "symfony/string", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca", + "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-10T08:47:49+00:00" + }, + { + "name": "symfony/translation", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "81b48f4daa96272efcce9c7a6c4b58e629df3c90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/81b48f4daa96272efcce9c7a6c4b58e629df3c90", + "reference": "81b48f4daa96272efcce9c7a6c4b58e629df3c90", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "nikic/php-parser": "<5.0", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-30T17:31:46+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-27T08:32:26+00:00" + }, + { + "name": "symfony/uid", + "version": "v7.3.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb", + "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v7.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-27T19:55:54+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "53205bea27450dc5c65377518b3275e126d45e75" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/53205bea27450dc5c65377518b3275e126d45e75", + "reference": "53205bea27450dc5c65377518b3275e126d45e75", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-29T20:02:46+00:00" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^7.4 || ^8.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" + }, + "time": "2024-12-21T16:25:41+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.2", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.3", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2025-04-30T23:37:27+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "https://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2024-11-21T01:49:47+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "fakerphp/faker", + "version": "v1.24.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" + }, + "time": "2024-11-21T13:46:39+00:00" + }, + { + "name": "filp/whoops", + "version": "2.18.4", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/d2102955e48b9fd9ab24280a7ad12ed552752c4d", + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.18.4" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2025-08-08T12:00:00+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" + }, + "time": "2025-04-30T06:54:44+00:00" + }, + { + "name": "laravel/pail", + "version": "v1.2.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/pail.git", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pail/zipball/8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "illuminate/console": "^10.24|^11.0|^12.0", + "illuminate/contracts": "^10.24|^11.0|^12.0", + "illuminate/log": "^10.24|^11.0|^12.0", + "illuminate/process": "^10.24|^11.0|^12.0", + "illuminate/support": "^10.24|^11.0|^12.0", + "nunomaduro/termwind": "^1.15|^2.0", + "php": "^8.2", + "symfony/console": "^6.0|^7.0" + }, + "require-dev": { + "laravel/framework": "^10.24|^11.0|^12.0", + "laravel/pint": "^1.13", + "orchestra/testbench-core": "^8.13|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "pestphp/pest-plugin-type-coverage": "^2.3|^3.0", + "phpstan/phpstan": "^1.12.27", + "symfony/var-dumper": "^6.3|^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Pail\\PailServiceProvider" + ] + }, + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Pail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Easily delve into your Laravel application's log files directly from the command line.", + "homepage": "https://github.com/laravel/pail", + "keywords": [ + "dev", + "laravel", + "logs", + "php", + "tail" + ], + "support": { + "issues": "https://github.com/laravel/pail/issues", + "source": "https://github.com/laravel/pail" + }, + "time": "2025-06-05T13:55:57+00:00" + }, + { + "name": "laravel/pint", + "version": "v1.24.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/pint.git", + "reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pint/zipball/0345f3b05f136801af8c339f9d16ef29e6b4df8a", + "reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.82.2", + "illuminate/view": "^11.45.1", + "larastan/larastan": "^3.5.0", + "laravel-zero/framework": "^11.45.0", + "mockery/mockery": "^1.6.12", + "nunomaduro/termwind": "^2.3.1", + "pestphp/pest": "^2.36.0" + }, + "bin": [ + "builds/pint" + ], + "type": "project", + "autoload": { + "files": [ + "overrides/Runner/Parallel/ProcessFactory.php" + ], + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", + "keywords": [ + "format", + "formatter", + "lint", + "linter", + "php" + ], + "support": { + "issues": "https://github.com/laravel/pint/issues", + "source": "https://github.com/laravel/pint" + }, + "time": "2025-07-10T18:09:32+00:00" + }, + { + "name": "laravel/sail", + "version": "v1.44.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/sail.git", + "reference": "a09097bd2a8a38e23ac472fa6a6cf5b0d1c1d3fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sail/zipball/a09097bd2a8a38e23ac472fa6a6cf5b0d1c1d3fe", + "reference": "a09097bd2a8a38e23ac472fa6a6cf5b0d1c1d3fe", + "shasum": "" + }, + "require": { + "illuminate/console": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/contracts": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/support": "^9.52.16|^10.0|^11.0|^12.0", + "php": "^8.0", + "symfony/console": "^6.0|^7.0", + "symfony/yaml": "^6.0|^7.0" + }, + "require-dev": { + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", + "phpstan/phpstan": "^1.10" + }, + "bin": [ + "bin/sail" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sail\\SailServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Docker files for running a basic Laravel application.", + "keywords": [ + "docker", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/sail/issues", + "source": "https://github.com/laravel/sail" + }, + "time": "2025-07-04T16:17:06+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-08-01T08:46:24+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v8.8.2", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.18.1", + "nunomaduro/termwind": "^2.3.1", + "php": "^8.2.0", + "symfony/console": "^7.3.0" + }, + "conflict": { + "laravel/framework": "<11.44.2 || >=13.0.0", + "phpunit/phpunit": "<11.5.15 || >=13.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.8.3", + "larastan/larastan": "^3.4.2", + "laravel/framework": "^11.44.2 || ^12.18", + "laravel/pint": "^1.22.1", + "laravel/sail": "^1.43.1", + "laravel/sanctum": "^4.1.1", + "laravel/tinker": "^2.10.1", + "orchestra/testbench-core": "^9.12.0 || ^10.4", + "pestphp/pest": "^3.8.2", + "sebastian/environment": "^7.2.1 || ^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "dev", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2025-06-25T02:12:12+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "11.0.10", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "1a800a7446add2d79cc6b3c01c45381810367d76" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1a800a7446add2d79cc6b3c01c45381810367d76", + "reference": "1a800a7446add2d79cc6b3c01c45381810367d76", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.4.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.2" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/show" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" + } + ], + "time": "2025-06-18T08:56:18+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-27T05:02:59+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:08:43+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:09:35+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "11.5.29", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "804ac91b99e3a36a23f1584a9c4347fd69b0a384" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/804ac91b99e3a36a23f1584a9c4347fd69b0a384", + "reference": "804ac91b99e3a36a23f1584a9c4347fd69b0a384", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.10", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.3", + "sebastian/comparator": "^6.3.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.1", + "sebastian/exporter": "^6.3.0", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.3", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.29" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2025-08-09T07:11:30+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:41:36+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-19T07:56:08+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-07T06:57:01+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:49:50+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "sebastian/environment", + "version": "7.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" + } + ], + "time": "2025-05-21T11:55:47+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-12-05T09:17:50+00:00" + }, + { + "name": "sebastian/global-state", + "version": "7.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:57:36+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:58:38+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:00:13+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:01:32+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:10:34+00:00" + }, + { + "name": "sebastian/type", + "version": "5.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" + } + ], + "time": "2025-08-09T06:55:48+00:00" + }, + { + "name": "sebastian/version", + "version": "5.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-09T05:16:32+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "b8d7d868da9eb0919e99c8830431ea087d6aae30" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/b8d7d868da9eb0919e99c8830431ea087d6aae30", + "reference": "b8d7d868da9eb0919e99c8830431ea087d6aae30", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-10T08:47:49+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^8.2" + }, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/config/app.php b/config/app.php new file mode 100755 index 0000000..423eed5 --- /dev/null +++ b/config/app.php @@ -0,0 +1,126 @@ + 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'), + ], + +]; diff --git a/config/auth.php b/config/auth.php new file mode 100755 index 0000000..7d1eb0d --- /dev/null +++ b/config/auth.php @@ -0,0 +1,115 @@ + [ + '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), + +]; diff --git a/config/cache.php b/config/cache.php new file mode 100755 index 0000000..c2d927d --- /dev/null +++ b/config/cache.php @@ -0,0 +1,108 @@ + 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-'), + +]; diff --git a/config/csrf.php b/config/csrf.php new file mode 100644 index 0000000..f880dff --- /dev/null +++ b/config/csrf.php @@ -0,0 +1,8 @@ + [ + 'secure' => true, + 'same_site' => 'lax', + ], +]; diff --git a/config/database.php b/config/database.php new file mode 100755 index 0000000..5b318f5 --- /dev/null +++ b/config/database.php @@ -0,0 +1,174 @@ + 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'), + ], + + ], + +]; diff --git a/config/filesystems.php b/config/filesystems.php new file mode 100755 index 0000000..3d671bd --- /dev/null +++ b/config/filesystems.php @@ -0,0 +1,80 @@ + 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'), + ], + +]; diff --git a/config/logging.php b/config/logging.php new file mode 100755 index 0000000..9e998a4 --- /dev/null +++ b/config/logging.php @@ -0,0 +1,132 @@ + 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'), + ], + + ], + +]; diff --git a/config/mail.php b/config/mail.php new file mode 100755 index 0000000..522b284 --- /dev/null +++ b/config/mail.php @@ -0,0 +1,118 @@ + 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'), + ], + +]; diff --git a/config/queue.php b/config/queue.php new file mode 100755 index 0000000..116bd8d --- /dev/null +++ b/config/queue.php @@ -0,0 +1,112 @@ + 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', + ], + +]; diff --git a/config/services.php b/config/services.php new file mode 100755 index 0000000..6182e4b --- /dev/null +++ b/config/services.php @@ -0,0 +1,38 @@ + [ + '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'), + ], + ], + +]; diff --git a/config/session.php b/config/session.php new file mode 100755 index 0000000..f715097 --- /dev/null +++ b/config/session.php @@ -0,0 +1,217 @@ + 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), + +]; diff --git a/config/trusted-proxies.php b/config/trusted-proxies.php new file mode 100644 index 0000000..203a13c --- /dev/null +++ b/config/trusted-proxies.php @@ -0,0 +1,15 @@ + [ + '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', + ], +]; diff --git a/create-admin.php b/create-admin.php new file mode 100755 index 0000000..9ad798f --- /dev/null +++ b/create-admin.php @@ -0,0 +1,40 @@ +👑 Admin-User erstellen"; + +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 "

✅ Admin-User existiert bereits!

"; + echo "

Name: {$existingAdmin->name}

"; + echo "

Email: {$existingAdmin->email}

"; + echo "

ID: {$existingAdmin->id}

"; + echo "

🚀 Zur Anwendung

"; + } else { + // Admin-User erstellen + $admin = \App\Models\User::create([ + 'name' => 'Admin', + 'email' => 'admin@neonail.com', + 'password' => bcrypt('admin123') + ]); + + echo "

✅ Admin-User erstellt!

"; + echo "

Name: {$admin->name}

"; + echo "

Email: {$admin->email}

"; + echo "

Passwort: admin123

"; + echo "

ID: {$admin->id}

"; + echo "

🚀 Zur Anwendung

"; + } + +} catch (Exception $e) { + echo "

❌ Fehler:

"; + echo "

{$e->getMessage()}

"; +} +?> diff --git a/database.sqlite b/database.sqlite new file mode 100755 index 0000000..2b7b3c9 Binary files /dev/null and b/database.sqlite differ diff --git a/database/.gitignore b/database/.gitignore new file mode 100644 index 0000000..9b19b93 --- /dev/null +++ b/database/.gitignore @@ -0,0 +1 @@ +*.sqlite* diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php new file mode 100755 index 0000000..584104c --- /dev/null +++ b/database/factories/UserFactory.php @@ -0,0 +1,44 @@ + + */ +class UserFactory extends Factory +{ + /** + * The current password being used by the factory. + */ + protected static ?string $password; + + /** + * Define the model's default state. + * + * @return array + */ + 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, + ]); + } +} diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php new file mode 100755 index 0000000..05fb5d9 --- /dev/null +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -0,0 +1,49 @@ +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'); + } +}; diff --git a/database/migrations/0001_01_01_000001_create_cache_table.php b/database/migrations/0001_01_01_000001_create_cache_table.php new file mode 100755 index 0000000..b9c106b --- /dev/null +++ b/database/migrations/0001_01_01_000001_create_cache_table.php @@ -0,0 +1,35 @@ +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'); + } +}; diff --git a/database/migrations/0001_01_01_000002_create_jobs_table.php b/database/migrations/0001_01_01_000002_create_jobs_table.php new file mode 100755 index 0000000..425e705 --- /dev/null +++ b/database/migrations/0001_01_01_000002_create_jobs_table.php @@ -0,0 +1,57 @@ +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'); + } +}; diff --git a/database/migrations/2025_01_15_000000_create_manufacturers_table.php b/database/migrations/2025_01_15_000000_create_manufacturers_table.php new file mode 100644 index 0000000..9bd1cb6 --- /dev/null +++ b/database/migrations/2025_01_15_000000_create_manufacturers_table.php @@ -0,0 +1,34 @@ +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'); + } +}; diff --git a/database/migrations/2025_08_10_020520_create_nail_polishes_table.php b/database/migrations/2025_08_10_020520_create_nail_polishes_table.php new file mode 100755 index 0000000..b713687 --- /dev/null +++ b/database/migrations/2025_08_10_020520_create_nail_polishes_table.php @@ -0,0 +1,33 @@ +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'); + } +}; diff --git a/database/migrations/2025_08_10_020523_create_user_nail_polishes_table.php b/database/migrations/2025_08_10_020523_create_user_nail_polishes_table.php new file mode 100755 index 0000000..6b1d9d2 --- /dev/null +++ b/database/migrations/2025_08_10_020523_create_user_nail_polishes_table.php @@ -0,0 +1,32 @@ +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'); + } +}; diff --git a/database/migrations/2025_08_10_020524_add_manufacturer_id_to_nail_polishes_table.php b/database/migrations/2025_08_10_020524_add_manufacturer_id_to_nail_polishes_table.php new file mode 100644 index 0000000..0bda1dd --- /dev/null +++ b/database/migrations/2025_08_10_020524_add_manufacturer_id_to_nail_polishes_table.php @@ -0,0 +1,29 @@ +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'); + }); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php new file mode 100755 index 0000000..d01a0ef --- /dev/null +++ b/database/seeders/DatabaseSeeder.php @@ -0,0 +1,23 @@ +create(); + + User::factory()->create([ + 'name' => 'Test User', + 'email' => 'test@example.com', + ]); + } +} diff --git a/debug-405-error.php b/debug-405-error.php new file mode 100644 index 0000000..b50d3b9 --- /dev/null +++ b/debug-405-error.php @@ -0,0 +1,118 @@ +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"; +?> diff --git a/debug-500-error.php b/debug-500-error.php new file mode 100644 index 0000000..a91d391 --- /dev/null +++ b/debug-500-error.php @@ -0,0 +1,131 @@ + '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"; +?> diff --git a/debug-image-upload.php b/debug-image-upload.php new file mode 100644 index 0000000..01fa643 --- /dev/null +++ b/debug-image-upload.php @@ -0,0 +1,194 @@ + 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"; +?> diff --git a/debug-logout-detailed.php b/debug-logout-detailed.php new file mode 100644 index 0000000..292656f --- /dev/null +++ b/debug-logout-detailed.php @@ -0,0 +1,202 @@ + $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"; +?> diff --git a/debug-logout.php b/debug-logout.php new file mode 100644 index 0000000..1f4bbcb --- /dev/null +++ b/debug-logout.php @@ -0,0 +1,218 @@ + $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"; +?> diff --git a/deploy-manufacturer-feature.sh b/deploy-manufacturer-feature.sh new file mode 100755 index 0000000..754f525 --- /dev/null +++ b/deploy-manufacturer-feature.sh @@ -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!" diff --git a/deploy-sqlite.sh b/deploy-sqlite.sh new file mode 100755 index 0000000..e7ec256 --- /dev/null +++ b/deploy-sqlite.sh @@ -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" diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..ab47a51 --- /dev/null +++ b/deploy.sh @@ -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" diff --git a/deployment-checklist.md b/deployment-checklist.md new file mode 100755 index 0000000..097f175 --- /dev/null +++ b/deployment-checklist.md @@ -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 diff --git a/emergency-apache-fix.sh b/emergency-apache-fix.sh new file mode 100755 index 0000000..c2791cf --- /dev/null +++ b/emergency-apache-fix.sh @@ -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' + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + +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" diff --git a/env-production-example.txt b/env-production-example.txt new file mode 100755 index 0000000..0fe2526 --- /dev/null +++ b/env-production-example.txt @@ -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}" diff --git a/env-sqlite-example.txt b/env-sqlite-example.txt new file mode 100755 index 0000000..27bdb00 --- /dev/null +++ b/env-sqlite-example.txt @@ -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}" diff --git a/fix-405-error.sh b/fix-405-error.sh new file mode 100755 index 0000000..53d3a57 --- /dev/null +++ b/fix-405-error.sh @@ -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" diff --git a/fix-admin-controller-email.php b/fix-admin-controller-email.php new file mode 100644 index 0000000..d40f9ca --- /dev/null +++ b/fix-admin-controller-email.php @@ -0,0 +1,284 @@ +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"; +?> diff --git a/fix-admin-layout.php b/fix-admin-layout.php new file mode 100644 index 0000000..daa8e46 --- /dev/null +++ b/fix-admin-layout.php @@ -0,0 +1,291 @@ + + + + + + + @yield("title", "NeoNail Datenbank") + + + + + + + + + @yield("styles") + + + + +
+
+ @if(session("success")) + + @endif + + @if(session("error")) + + @endif + + @yield("content") +
+
+ + + + + @yield("scripts") + +'; + +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"; +?> diff --git a/fix-admin-role-database.php b/fix-admin-role-database.php new file mode 100644 index 0000000..9f735df --- /dev/null +++ b/fix-admin-role-database.php @@ -0,0 +1,120 @@ +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"; +} +?> diff --git a/fix-admin-role.php b/fix-admin-role.php new file mode 100755 index 0000000..67a864e --- /dev/null +++ b/fix-admin-role.php @@ -0,0 +1,54 @@ +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"; +} +?> diff --git a/fix-admin-routes.php b/fix-admin-routes.php new file mode 100644 index 0000000..5be868b --- /dev/null +++ b/fix-admin-routes.php @@ -0,0 +1,165 @@ + $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"; +?> diff --git a/fix-admin-view.php b/fix-admin-view.php new file mode 100644 index 0000000..08c1415 --- /dev/null +++ b/fix-admin-view.php @@ -0,0 +1,158 @@ +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"; +?> diff --git a/fix-all-405-errors.sh b/fix-all-405-errors.sh new file mode 100644 index 0000000..a503001 --- /dev/null +++ b/fix-all-405-errors.sh @@ -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" diff --git a/fix-all-forms-https.sh b/fix-all-forms-https.sh new file mode 100755 index 0000000..810608d --- /dev/null +++ b/fix-all-forms-https.sh @@ -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' + 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' +"; + }); + } +} +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" diff --git a/fix-all-safari-warnings.sh b/fix-all-safari-warnings.sh new file mode 100755 index 0000000..1e3c663 --- /dev/null +++ b/fix-all-safari-warnings.sh @@ -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' + + 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] + + +# Protect sensitive files + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + +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' + '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)" diff --git a/fix-apache-documentroot.sh b/fix-apache-documentroot.sh new file mode 100755 index 0000000..fe60c76 --- /dev/null +++ b/fix-apache-documentroot.sh @@ -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' + + ServerName 192.168.30.81 + DocumentRoot /var/www/html/public + + + AllowOverride All + Require all granted + Options Indexes FollowSymLinks + + + # Sicherheit für sensible Dateien + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + ErrorLog ${APACHE_LOG_DIR}/neonail_error.log + CustomLog ${APACHE_LOG_DIR}/neonail_access.log combined + +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" diff --git a/fix-apache-headers.sh b/fix-apache-headers.sh new file mode 100755 index 0000000..d3c0aa7 --- /dev/null +++ b/fix-apache-headers.sh @@ -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' + + + Options -MultiViews -Indexes + + + 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] + + +# Protect sensitive files + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + +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" diff --git a/fix-appserviceprovider-syntax.sh b/fix-appserviceprovider-syntax.sh new file mode 100644 index 0000000..52f2a0b --- /dev/null +++ b/fix-appserviceprovider-syntax.sh @@ -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" diff --git a/fix-https-config.sh b/fix-https-config.sh new file mode 100755 index 0000000..3074d27 --- /dev/null +++ b/fix-https-config.sh @@ -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' + [ + '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" diff --git a/fix-https-form-security.sh b/fix-https-form-security.sh new file mode 100755 index 0000000..915a652 --- /dev/null +++ b/fix-https-form-security.sh @@ -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' + [ + 'secure' => true, + 'same_site' => 'lax', + ], +]; +EOF + +# 5. Trusted Proxies konfigurieren +echo "🌐 Konfiguriere Trusted Proxies..." +cat > config/trusted-proxies.php << 'EOF' + [ + '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" diff --git a/fix-image-display.sh b/fix-image-display.sh new file mode 100755 index 0000000..a7d10bb --- /dev/null +++ b/fix-image-display.sh @@ -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" diff --git a/fix-image-upload-fallback.php b/fix-image-upload-fallback.php new file mode 100644 index 0000000..b0fa419 --- /dev/null +++ b/fix-image-upload-fallback.php @@ -0,0 +1,49 @@ +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; +} +?> diff --git a/fix-image-upload-final.php b/fix-image-upload-final.php new file mode 100644 index 0000000..00b52b4 --- /dev/null +++ b/fix-image-upload-final.php @@ -0,0 +1,282 @@ +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"; +?> diff --git a/fix-image-upload-simple.php b/fix-image-upload-simple.php new file mode 100644 index 0000000..dfc9f9b --- /dev/null +++ b/fix-image-upload-simple.php @@ -0,0 +1,222 @@ +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"; +?> diff --git a/fix-image-urls.php b/fix-image-urls.php new file mode 100644 index 0000000..b75346e --- /dev/null +++ b/fix-image-urls.php @@ -0,0 +1,60 @@ +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 ""; + }); +} +*/ + +// Dann in der View: +// @nailPolishImage($nailPolish->image_path) +?> diff --git a/fix-laravel-setup.sh b/fix-laravel-setup.sh new file mode 100755 index 0000000..5dc3db6 --- /dev/null +++ b/fix-laravel-setup.sh @@ -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" diff --git a/fix-logout-final.php b/fix-logout-final.php new file mode 100644 index 0000000..80c7290 --- /dev/null +++ b/fix-logout-final.php @@ -0,0 +1,110 @@ +/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"; +?> diff --git a/fix-logout-route.php b/fix-logout-route.php new file mode 100644 index 0000000..51d989b --- /dev/null +++ b/fix-logout-route.php @@ -0,0 +1,194 @@ +/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 = ' + + + Logout Test + + + +

Logout Test

+
+ @csrf + +
+

Route: {{ route("logout") }}

+ +'; + +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"; +?> diff --git a/fix-logout-simple-2.php b/fix-logout-simple-2.php new file mode 100644 index 0000000..c0908db --- /dev/null +++ b/fix-logout-simple-2.php @@ -0,0 +1,147 @@ +/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"; +?> diff --git a/fix-logout-simple.php b/fix-logout-simple.php new file mode 100644 index 0000000..c39288c --- /dev/null +++ b/fix-logout-simple.php @@ -0,0 +1,81 @@ +/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"; +?> diff --git a/fix-logout.php b/fix-logout.php new file mode 100644 index 0000000..9a30494 --- /dev/null +++ b/fix-logout.php @@ -0,0 +1,277 @@ + + + + + + + @yield("title", "NeoNail Datenbank") + + + + + + + + + @yield("styles") + + + + +
+
+ @if(session("success")) + + @endif + + @if(session("error")) + + @endif + + @yield("content") +
+
+ + + + + @yield("scripts") + +'; + +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"; +?> diff --git a/fix-pail-cache.sh b/fix-pail-cache.sh new file mode 100755 index 0000000..c05ceac --- /dev/null +++ b/fix-pail-cache.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +echo "🧹 Pail Cache Problem lösen" +echo "==========================" + +# 1. Cache-Dateien löschen +echo "🗑️ Lösche Cache-Dateien..." +rm -f bootstrap/cache/packages.php +rm -f bootstrap/cache/services.php +rm -f bootstrap/cache/config.php + +# 2. Composer autoload neu generieren +echo "🔄 Generiere autoload neu..." +if command -v composer &> /dev/null; then + composer dump-autoload --optimize +elif [ -f "composer.phar" ]; then + php composer.phar dump-autoload --optimize +else + echo "⚠️ Composer nicht verfügbar" +fi + +# 3. Laravel Cache leeren +echo "🧹 Leere Laravel Cache..." +php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen" +php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen" +php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen" +php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen" + +# 4. Berechtigungen setzen +echo "🔐 Setze Berechtigungen..." +chmod -R 777 bootstrap/cache/ + +echo "" +echo "✅ Pail Cache Problem behoben!" +echo "📋 Testen Sie: php artisan --version" diff --git a/fix-pail-final.sh b/fix-pail-final.sh new file mode 100755 index 0000000..c7048a5 --- /dev/null +++ b/fix-pail-final.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +echo "🧹 Finale Pail-Problem Lösung" +echo "=============================" + +# 1. Alle Cache-Dateien löschen +echo "🗑️ Lösche alle Cache-Dateien..." +rm -f bootstrap/cache/packages.php +rm -f bootstrap/cache/services.php +rm -f bootstrap/cache/config.php +rm -f bootstrap/cache/routes.php +rm -f bootstrap/cache/views.php + +# 2. Composer autoload neu generieren +echo "🔄 Generiere Composer autoload neu..." +if command -v composer &> /dev/null; then + composer dump-autoload --optimize +elif [ -f "composer.phar" ]; then + php composer.phar dump-autoload --optimize +else + echo "⚠️ Composer nicht verfügbar, überspringe autoload" +fi + +# 3. Laravel Cache komplett leeren +echo "🧹 Leere Laravel Cache komplett..." +php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen" +php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen" +php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen" +php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen" + +# 4. Berechtigungen setzen +echo "🔐 Setze Berechtigungen..." +chmod -R 777 bootstrap/cache/ +chmod -R 777 storage/ + +# 5. Debug deaktivieren (für Produktion) +echo "🔧 Setze Debug-Modus zurück..." +sed -i 's/APP_DEBUG=true/APP_DEBUG=false/' .env + +# 6. Test +echo "🧪 Teste Anwendung..." +curl -I http://192.168.30.81 + +echo "" +echo "✅ Pail-Problem behoben!" +echo "📋 Testen Sie: http://192.168.30.81" diff --git a/fix-permissions.sh b/fix-permissions.sh new file mode 100755 index 0000000..cd9b5f8 --- /dev/null +++ b/fix-permissions.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# NeoNail DB - Berechtigungen korrigieren +echo "🔧 NeoNail DB - Berechtigungen korrigieren..." + +# 1. Storage-Verzeichnisse erstellen (falls nicht vorhanden) +echo "📁 Storage-Verzeichnisse erstellen..." +mkdir -p storage/framework/views +mkdir -p storage/framework/cache +mkdir -p storage/framework/sessions +mkdir -p storage/logs +mkdir -p bootstrap/cache + +# 2. Berechtigungen für Storage setzen +echo "🔐 Storage-Berechtigungen setzen..." +chmod -R 777 storage/ +chmod -R 777 storage/framework/ +chmod -R 777 storage/framework/views/ +chmod -R 777 storage/framework/cache/ +chmod -R 777 storage/framework/sessions/ +chmod -R 777 storage/logs/ + +# 3. Bootstrap/Cache-Berechtigungen +echo "🔐 Bootstrap/Cache-Berechtigungen setzen..." +chmod -R 777 bootstrap/cache/ + +# 4. SQLite-Datenbank erstellen und Berechtigungen setzen +echo "🗄️ SQLite-Datenbank erstellen..." +if [ ! -f database.sqlite ]; then + touch database.sqlite + echo "✅ SQLite-Datenbank erstellt" +else + echo "✅ SQLite-Datenbank bereits vorhanden" +fi +chmod 664 database.sqlite + +# 5. .env Berechtigungen +echo "🔐 .env Berechtigungen setzen..." +if [ -f .env ]; then + chmod 644 .env + echo "✅ .env Berechtigungen gesetzt" +else + echo "⚠️ .env Datei nicht gefunden" +fi + +# 6. Cache leeren +echo "🧹 Cache leeren..." +php artisan config:clear 2>/dev/null || echo "⚠️ php artisan nicht verfügbar" +php artisan cache:clear 2>/dev/null || echo "⚠️ php artisan nicht verfügbar" +php artisan view:clear 2>/dev/null || echo "⚠️ php artisan nicht verfügbar" + +# 7. Storage-Link erstellen +echo "🔗 Storage-Link erstellen..." +php artisan storage:link 2>/dev/null || echo "⚠️ php artisan nicht verfügbar" + +echo "✅ Berechtigungen korrigiert!" +echo "" +echo "📋 Nächste Schritte:" +echo "1. Seite neu laden: http://192.168.30.81/neonail/" +echo "2. Falls immer noch Fehler: Composer install ausführen" +echo "3. Migrationen ausführen: php artisan migrate --force" +echo "4. Admin-User erstellen: php artisan tinker" +echo "" +echo "💡 Falls Probleme bestehen:" +echo "- Hosting-Provider kontaktieren" +echo "- SSH-Zugang anfordern" +echo "- Berechtigungen über Hosting-Panel prüfen" diff --git a/fix-remaining-safari-warnings.sh b/fix-remaining-safari-warnings.sh new file mode 100755 index 0000000..8d1550a --- /dev/null +++ b/fix-remaining-safari-warnings.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +echo "🛡️ Fix: Verbleibende Safari Sicherheitswarnungen" +echo "===============================================" + +# 1. Logout-Formular beheben +echo "1. 🔒 Logout-Formular beheben..." +if [ -f resources/views/layouts/app.blade.php ]; then + sed -i 's|action="{{ route('\''logout'\'') }}"|action="https://neonail.vogt.de.com/logout"|' resources/views/layouts/app.blade.php + echo " ✅ Logout-Formular behoben" +else + echo " ❌ layouts/app.blade.php nicht gefunden" +fi + +# 2. Alle verbleibenden route() Aufrufe finden +echo "2. 🔍 Alle verbleibenden route() Aufrufe finden..." +grep -r "route(" resources/views/ --include="*.blade.php" | grep -E "(action|href)" || echo " ℹ️ Keine verbleibenden route() Aufrufe in action/href gefunden" + +# 3. Alle Formulare mit HTTPS-URLs prüfen +echo "3. 🔒 Alle Formulare mit HTTPS prüfen..." +php test-forms-fixed.php + +# 4. Laravel Cache leeren +echo "4. 🧹 Laravel Cache leeren..." +php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen" +php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen" +php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen" +php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen" + +# 5. Test-Script erstellen +echo "5. 🧪 Test-Script erstellen..." +cat > test-all-forms-final.php << 'EOF' + 'Login-Formular', + 'resources/views/user-nail-polishes/create.blade.php' => 'Create Nail Polish', + 'resources/views/user-nail-polishes/index.blade.php' => 'Remove Nail Polish', + 'resources/views/nail-polishes/index.blade.php' => 'Admin Delete Nail Polish', + 'resources/views/admin/users/create.blade.php' => 'Admin Create User', + 'resources/views/admin/users/edit.blade.php' => 'Admin Edit User', + 'resources/views/admin/users/index.blade.php' => 'Admin Delete User', + 'resources/views/layouts/app.blade.php' => 'Logout-Formular' +]; + +$allFixed = true; + +foreach ($forms as $file => $description) { + if (file_exists($file)) { + $content = file_get_contents($file); + if (strpos($content, 'action="https://neonail.vogt.de.com') !== false) { + echo " ✅ $description: HTTPS-URL gefunden\n"; + } else { + echo " ❌ $description: Keine HTTPS-URL gefunden\n"; + $allFixed = false; + + // Zeige die aktuelle action + if (preg_match('/action="([^"]+)"/', $content, $matches)) { + echo " Aktuelle action: " . $matches[1] . "\n"; + } + } + } else { + echo " ❌ $description: Datei nicht gefunden\n"; + $allFixed = false; + } +} + +echo "\n"; +if ($allFixed) { + echo "🎉 ALLE Formulare sind jetzt mit HTTPS-URLs konfiguriert!\n"; + echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com\n"; + echo "📝 Safari-Sicherheitswarnungen sollten komplett verschwunden sein.\n"; +} else { + echo "⚠️ Einige Formulare müssen noch korrigiert werden.\n"; + echo "🔧 Führen Sie das Fix-Script erneut aus.\n"; +} + +echo "\n✅ Finaler Formular-Test abgeschlossen!\n"; +?> +EOF + +echo " ✅ Test-Script erstellt" + +# 6. Finalen Test ausführen +echo "6. 🧪 Finalen Test ausführen..." +php test-all-forms-final.php + +echo "" +echo "✅ Verbleibende Safari Sicherheitswarnungen behoben!" +echo "" +echo "🔗 Testen Sie jetzt:" +echo "1. Login: https://neonail.vogt.de.com/login" +echo "2. Logout: Klicken Sie auf Ihren Namen → Abmelden" +echo "3. Admin-Panel: https://neonail.vogt.de.com/admin/users" +echo "4. Lack erstellen: https://neonail.vogt.de.com/create-nail-polish" +echo "" +echo "📝 Falls Warnungen bestehen:" +echo "- Führen Sie php test-all-forms-final.php aus" +echo "- Leeren Sie Browser-Cache komplett" +echo "- Prüfen Sie Browser-Entwicklertools (F12)" +echo "- Testen Sie in einem Inkognito-Fenster" diff --git a/fix-safari-form-security.sh b/fix-safari-form-security.sh new file mode 100644 index 0000000..8a7777f --- /dev/null +++ b/fix-safari-form-security.sh @@ -0,0 +1,207 @@ +#!/bin/bash + +echo "🍎 Safari Formular-Sicherheit beheben" +echo "====================================" + +# 1. .env komplett für HTTPS konfigurieren +echo "📝 Konfiguriere .env für HTTPS..." +cat > .env << 'EOF' +APP_NAME="NeoNail DB" +APP_ENV=production +APP_KEY=base64:+LTZYPKjkZ+O3iFTgU2sS+9bNvxxvG8Kw8JSEPiG7Rs= +APP_DEBUG=false +APP_URL=https://neonail.vogt.de.com + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=sqlite +DB_DATABASE=database.sqlite + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +FILESYSTEM_DISK=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 +SESSION_SECURE_COOKIE=true +SESSION_SAME_SITE=lax +SESSION_HTTP_ONLY=true + +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=mailpit +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=mt1 + +VITE_APP_NAME="${APP_NAME}" +VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +VITE_PUSHER_HOST="${PUSHER_HOST}" +VITE_PUSHER_PORT="${PUSHER_PORT}" +VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" +VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" + +# HTTPS-Konfiguration +FORCE_HTTPS=true +SECURE_COOKIES=true +EOF + +# 2. Session-Konfiguration für HTTPS +echo "🔐 Konfiguriere Session für HTTPS..." +cat > config/session.php << 'EOF' + env('SESSION_DRIVER', 'file'), + 'lifetime' => env('SESSION_LIFETIME', 120), + 'expire_on_close' => false, + 'encrypt' => false, + 'files' => storage_path('framework/sessions'), + 'connection' => env('SESSION_CONNECTION'), + 'table' => 'sessions', + 'store' => env('SESSION_STORE'), + 'lottery' => [2, 100], + 'cookie' => env( + 'SESSION_COOKIE', + Str::slug(env('APP_NAME', 'laravel'), '_').'_session' + ), + 'path' => '/', + 'domain' => env('SESSION_DOMAIN'), + 'secure' => true, + 'http_only' => true, + 'same_site' => 'lax', +]; +EOF + +# 3. Laravel Cache komplett leeren +echo "🧹 Leere Laravel Cache komplett..." +php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen" +php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen" +php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen" +php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen" + +# 4. HTTPS-Force in .htaccess +echo "🔒 Füge HTTPS-Force hinzu..." +cat > public/.htaccess << 'EOF' + + + Options -MultiViews -Indexes + + + 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] + + +# Security Headers + + Header always set X-Content-Type-Options nosniff + Header always set X-Frame-Options DENY + Header always set X-XSS-Protection "1; mode=block" + Header always set Referrer-Policy "strict-origin-when-cross-origin" + Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" + Header always set Content-Security-Policy "upgrade-insecure-requests" + Header always set X-Forwarded-Proto https + + +# Protect sensitive files + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + +# Compression + + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/html + AddOutputFilterByType DEFLATE text/xml + AddOutputFilterByType DEFLATE text/css + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE application/xhtml+xml + AddOutputFilterByType DEFLATE application/rss+xml + AddOutputFilterByType DEFLATE application/javascript + AddOutputFilterByType DEFLATE application/x-javascript + + +# Cache Control + + ExpiresActive on + ExpiresByType text/css "access plus 1 year" + ExpiresByType application/javascript "access plus 1 year" + ExpiresByType image/png "access plus 1 year" + ExpiresByType image/jpg "access plus 1 year" + ExpiresByType image/jpeg "access plus 1 year" + ExpiresByType image/gif "access plus 1 year" + ExpiresByType image/svg+xml "access plus 1 year" + +EOF + +# 5. Apache neu laden +echo "🔄 Lade Apache neu..." +systemctl reload apache2 + +# 6. Test +echo "🧪 Teste HTTPS-Konfiguration..." +curl -I https://neonail.vogt.de.com + +echo "" +echo "✅ Safari Formular-Sicherheit behoben!" +echo "📋 Testen Sie: https://neonail.vogt.de.com" +echo "" +echo "📋 Falls Warnung bleibt:" +echo "1. Safari-Cache leeren (Cmd+Shift+R)" +echo "2. Private-Fenster testen" +echo "3. Safari-Einstellungen: Entwickler > Leere Caches" +echo "4. Safari-Einstellungen: Datenschutz > Website-Daten verwalten" diff --git a/fix-safari-https.sh b/fix-safari-https.sh new file mode 100644 index 0000000..a963c34 --- /dev/null +++ b/fix-safari-https.sh @@ -0,0 +1,171 @@ +#!/bin/bash + +echo "🍎 Safari HTTPS-Warnung beheben" +echo "==============================" + +# 1. .env komplett für HTTPS konfigurieren +echo "📝 Konfiguriere .env komplett für HTTPS..." +cat > .env << 'EOF' +APP_NAME="NeoNail DB" +APP_ENV=production +APP_KEY=base64:+LTZYPKjkZ+O3iFTgU2sS+9bNvxxvG8Kw8JSEPiG7Rs= +APP_DEBUG=false +APP_URL=https://neonail.vogt.de.com + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=sqlite +DB_DATABASE=database.sqlite + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +FILESYSTEM_DISK=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 +SESSION_SECURE_COOKIE=true +SESSION_SAME_SITE=lax + +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=mailpit +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=mt1 + +VITE_APP_NAME="${APP_NAME}" +VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +VITE_PUSHER_HOST="${PUSHER_HOST}" +VITE_PUSHER_PORT="${PUSHER_PORT}" +VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" +VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" +EOF + +# 2. Laravel Cache komplett leeren +echo "🧹 Leere Laravel Cache komplett..." +php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen" +php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen" +php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen" +php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen" + +# 3. HTTPS-Header in .htaccess hinzufügen +echo "🔒 Füge HTTPS-Header hinzu..." +cat > public/.htaccess << 'EOF' + + + Options -MultiViews -Indexes + + + 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] + + +# Security Headers + + Header always set X-Content-Type-Options nosniff + Header always set X-Frame-Options DENY + Header always set X-XSS-Protection "1; mode=block" + Header always set Referrer-Policy "strict-origin-when-cross-origin" + Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" + Header always set Content-Security-Policy "upgrade-insecure-requests" + + +# Protect sensitive files + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + +# Compression + + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/html + AddOutputFilterByType DEFLATE text/xml + AddOutputFilterByType DEFLATE text/css + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE application/xhtml+xml + AddOutputFilterByType DEFLATE application/rss+xml + AddOutputFilterByType DEFLATE application/javascript + AddOutputFilterByType DEFLATE application/x-javascript + + +# Cache Control + + ExpiresActive on + ExpiresByType text/css "access plus 1 year" + ExpiresByType application/javascript "access plus 1 year" + ExpiresByType image/png "access plus 1 year" + ExpiresByType image/jpg "access plus 1 year" + ExpiresByType image/jpeg "access plus 1 year" + ExpiresByType image/gif "access plus 1 year" + ExpiresByType image/svg+xml "access plus 1 year" + +EOF + +# 4. Apache neu laden +echo "🔄 Lade Apache neu..." +systemctl reload apache2 + +# 5. Test +echo "🧪 Teste HTTPS-Konfiguration..." +curl -I https://neonail.vogt.de.com + +echo "" +echo "✅ Safari HTTPS-Warnung behoben!" +echo "📋 Testen Sie: https://neonail.vogt.de.com" +echo "" +echo "📋 Falls Warnung bleibt:" +echo "1. Safari-Cache leeren (Cmd+Shift+R)" +echo "2. Private-Fenster testen" +echo "3. Safari-Einstellungen: Entwickler > Leere Caches" diff --git a/fix-safari-security-warnings.sh b/fix-safari-security-warnings.sh new file mode 100755 index 0000000..8b86c27 --- /dev/null +++ b/fix-safari-security-warnings.sh @@ -0,0 +1,166 @@ +#!/bin/bash + +echo "🛡️ Fix: Safari Sicherheitswarnungen" +echo "==================================" + +# 1. .env HTTPS-Einstellungen +echo "1. 🔒 HTTPS-Einstellungen in .env..." +if [ -f .env ]; then + # Setze alle HTTPS-Einstellungen + sed -i 's|APP_URL=.*|APP_URL=https://neonail.vogt.de.com|' .env + sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env + sed -i 's/APP_ENV=production/APP_ENV=local/' .env + + # HTTPS-spezifische Einstellungen + echo "FORCE_HTTPS=true" >> .env + echo "SECURE_COOKIES=true" >> .env + echo "SESSION_SECURE_COOKIE=true" >> .env + echo "SESSION_SAME_SITE=lax" >> .env + echo "SESSION_HTTP_ONLY=true" >> .env + + echo " ✅ .env HTTPS-Einstellungen aktualisiert" +else + echo " ❌ .env Datei nicht gefunden" +fi + +# 2. Session-Konfiguration +echo "2. 🍪 Session-Konfiguration..." +if [ -f config/session.php ]; then + sed -i "s/'secure' => false/'secure' => true/" config/session.php + sed -i "s/'http_only' => false/'http_only' => true/" config/session.php + echo " ✅ Session-Konfiguration aktualisiert" +else + echo " ❌ config/session.php nicht gefunden" +fi + +# 3. CSRF-Konfiguration +echo "3. 🔐 CSRF-Konfiguration..." +if [ -f config/csrf.php ]; then + sed -i "s/'secure' => false/'secure' => true/" config/csrf.php + sed -i "s/'same_site' => 'lax'/'same_site' => 'lax'/" config/csrf.php + echo " ✅ CSRF-Konfiguration aktualisiert" +else + echo " ❌ config/csrf.php nicht gefunden" +fi + +# 4. .htaccess HTTPS-Headers +echo "4. 🌐 .htaccess HTTPS-Headers..." +if [ -f public/.htaccess ]; then + # Füge HTTPS-Headers hinzu + if ! grep -q "Strict-Transport-Security" public/.htaccess; then + sed -i '/# Security Headers/a\ +Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"\ +Header always set Content-Security-Policy "upgrade-insecure-requests"' public/.htaccess + fi + + # Force HTTPS + if ! grep -q "RewriteCond %{HTTPS} off" public/.htaccess; then + sed -i '/RewriteEngine On/a\ +RewriteCond %{HTTPS} off\ +RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]' public/.htaccess + fi + + echo " ✅ .htaccess HTTPS-Headers aktualisiert" +else + echo " ❌ public/.htaccess nicht gefunden" +fi + +# 5. AppServiceProvider HTTPS-Force +echo "5. 🔧 AppServiceProvider HTTPS-Force..." +if [ -f app/Providers/AppServiceProvider.php ]; then + if ! grep -q "URL::forceScheme('https')" app/Providers/AppServiceProvider.php; then + sed -i "/public function boot(): void/a\\ + if (config('app.env') === 'production') {\\ + URL::forceScheme('https');\\ + }" app/Providers/AppServiceProvider.php + fi + echo " ✅ AppServiceProvider HTTPS-Force aktualisiert" +else + echo " ❌ AppServiceProvider nicht gefunden" +fi + +# 6. Laravel Cache leeren +echo "6. 🧹 Laravel Cache leeren..." +php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen" +php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen" +php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen" +php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen" + +# 7. Test-Script erstellen +echo "7. 🧪 Test-Script erstellen..." +cat > test-https-security.php << 'EOF' + true") !== false) { + echo " ✅ Session secure: true\n"; + } else { + echo " ❌ Session secure: false\n"; + } + if (strpos($content, "'http_only' => true") !== false) { + echo " ✅ Session http_only: true\n"; + } else { + echo " ❌ Session http_only: false\n"; + } +} + +// 3. Prüfe CSRF-Konfiguration +echo "\n3. CSRF-Konfiguration:\n"; +if (file_exists('config/csrf.php')) { + $content = file_get_contents('config/csrf.php'); + if (strpos($content, "'secure' => true") !== false) { + echo " ✅ CSRF secure: true\n"; + } else { + echo " ❌ CSRF secure: false\n"; + } +} + +// 4. Prüfe .htaccess +echo "\n4. .htaccess HTTPS-Headers:\n"; +if (file_exists('public/.htaccess')) { + $content = file_get_contents('public/.htaccess'); + if (strpos($content, 'Strict-Transport-Security') !== false) { + echo " ✅ HSTS Header vorhanden\n"; + } else { + echo " ❌ HSTS Header fehlt\n"; + } + if (strpos($content, 'upgrade-insecure-requests') !== false) { + echo " ✅ CSP upgrade-insecure-requests vorhanden\n"; + } else { + echo " ❌ CSP upgrade-insecure-requests fehlt\n"; + } +} + +echo "\n✅ HTTPS-Sicherheit Test abgeschlossen!\n"; +echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/admin/users\n"; +?> +EOF + +echo " ✅ Test-Script erstellt" + +echo "" +echo "✅ Safari Sicherheitswarnungen behoben!" +echo "" +echo "🔗 Testen Sie jetzt:" +echo "1. Admin-Panel: https://neonail.vogt.de.com/admin/users" +echo "2. Lack löschen im Admin-Panel" +echo "3. User bearbeiten/löschen" +echo "" +echo "📝 Falls Warnungen bestehen:" +echo "- Führen Sie php test-https-security.php aus" +echo "- Prüfen Sie Browser-Entwicklertools (F12)" +echo "- Leeren Sie Browser-Cache" diff --git a/fix-sqlite-permissions.sh b/fix-sqlite-permissions.sh new file mode 100755 index 0000000..a49d71b --- /dev/null +++ b/fix-sqlite-permissions.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +echo "🗄️ SQLite-Berechtigungen korrigieren" +echo "===================================" + +# 1. Aktuelle Berechtigungen prüfen +echo "🔍 Aktuelle Berechtigungen:" +ls -la database.sqlite +echo "" + +# 2. Berechtigungen korrigieren +echo "🔐 Setze SQLite-Berechtigungen..." +chown www-data:www-data database.sqlite +chmod 664 database.sqlite + +# 3. Verzeichnis-Berechtigungen +echo "📁 Setze Verzeichnis-Berechtigungen..." +chown -R www-data:www-data /var/www/html +chmod -R 755 /var/www/html +chmod -R 777 storage/ +chmod -R 777 bootstrap/cache/ + +# 4. SQLite-Datei testen +echo "🧪 Teste SQLite-Schreibzugriff..." +if [ -w database.sqlite ]; then + echo "✅ SQLite-Datei ist schreibbar" +else + echo "❌ SQLite-Datei ist NICHT schreibbar" +fi + +# 5. Apache-User prüfen +echo "👤 Apache-User:" +ps aux | grep apache | head -1 + +# 6. Test-Schreibzugriff +echo "📝 Teste Schreibzugriff..." +sqlite3 database.sqlite "CREATE TABLE IF NOT EXISTS test_write (id INTEGER); DROP TABLE test_write;" 2>/dev/null && echo "✅ SQLite-Schreibzugriff funktioniert" || echo "❌ SQLite-Schreibzugriff fehlgeschlagen" + +echo "" +echo "✅ SQLite-Berechtigungen korrigiert!" +echo "📋 Testen Sie jetzt das Erstellen eines Lackes" diff --git a/fix-storage-link.sh b/fix-storage-link.sh new file mode 100755 index 0000000..204c16b --- /dev/null +++ b/fix-storage-link.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +echo "🔗 Storage Link Problem lösen" +echo "============================" + +# 1. Aktuellen Storage-Status prüfen +echo "🔍 Aktueller Storage-Status:" +ls -la public/storage +echo "" + +# 2. Storage-Verzeichnis entfernen (falls es ein Verzeichnis ist) +echo "🗑️ Entferne falsches Storage-Verzeichnis..." +if [ -d "public/storage" ]; then + rm -rf public/storage + echo "✅ Storage-Verzeichnis entfernt" +elif [ -L "public/storage" ]; then + rm public/storage + echo "✅ Storage-Link entfernt" +fi + +# 3. Storage Link neu erstellen +echo "🔗 Erstelle Storage Link neu..." +php artisan storage:link + +# 4. Link prüfen +echo "🔍 Prüfe neuen Storage Link:" +ls -la public/storage +echo "" + +# 5. Ziel-Verzeichnis prüfen +echo "📁 Prüfe Ziel-Verzeichnis:" +ls -la storage/app/public/ +echo "" + +# 6. Bilder-Verzeichnis prüfen +echo "🖼️ Prüfe Bilder-Verzeichnis:" +ls -la storage/app/public/nail_polishes/ 2>/dev/null || echo "⚠️ nail_polishes Verzeichnis nicht gefunden" + +# 7. Test-Bild erstellen +echo "🧪 Erstelle Test-Bild..." +mkdir -p storage/app/public/nail_polishes +echo "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==" | base64 -d > storage/app/public/nail_polishes/test.jpg +chmod 644 storage/app/public/nail_polishes/test.jpg + +# 8. Berechtigungen setzen +echo "🔐 Setze Berechtigungen..." +chmod -R 755 public/storage/ +chmod -R 777 storage/app/public/ + +# 9. Test-URL +echo "🧪 Teste Bild-URL..." +curl -I https://neonail.vogt.de.com/storage/nail_polishes/test.jpg + +# 10. Echte Bilder testen +echo "🖼️ Teste echte Bilder..." +sqlite3 database.sqlite "SELECT image_path FROM nail_polishes WHERE image_path IS NOT NULL LIMIT 1;" | while read image_path; do + if [ ! -z "$image_path" ]; then + echo "Teste: $image_path" + if [ -f "storage/app/public/$image_path" ]; then + echo "✅ Bild existiert: $image_path" + curl -I "https://neonail.vogt.de.com/storage/$image_path" + else + echo "❌ Bild fehlt: $image_path" + fi + fi +done + +echo "" +echo "✅ Storage Link Problem behoben!" +echo "📋 Testen Sie: https://neonail.vogt.de.com" diff --git a/fix-upload-limits.php b/fix-upload-limits.php new file mode 100644 index 0000000..c5fed06 --- /dev/null +++ b/fix-upload-limits.php @@ -0,0 +1,133 @@ + ini_get('upload_max_filesize'), + 'post_max_size' => ini_get('post_max_size'), + 'max_file_uploads' => ini_get('max_file_uploads'), + 'memory_limit' => ini_get('memory_limit'), + 'max_execution_time' => ini_get('max_execution_time'), + 'max_input_time' => ini_get('max_input_time') +]; + +foreach ($limits as $setting => $value) { + echo " - $setting: $value\n"; +} + +// 2. Konvertiere zu Bytes für Vergleich +function convertToBytes($sizeStr) { + $sizeStr = strtolower(trim($sizeStr)); + $last = strtolower($sizeStr[strlen($sizeStr)-1]); + $size = (int)$sizeStr; + + switch($last) { + case 'g': $size *= 1024; + case 'm': $size *= 1024; + case 'k': $size *= 1024; + } + + return $size; +} + +$uploadMaxBytes = convertToBytes($limits['upload_max_filesize']); +$postMaxBytes = convertToBytes($limits['post_max_size']); +$requiredBytes = 10 * 1024 * 1024; // 10MB + +echo "\n2. 📊 Größenvergleich:\n"; +echo " - Upload max filesize: " . number_format($uploadMaxBytes) . " Bytes\n"; +echo " - Post max size: " . number_format($postMaxBytes) . " Bytes\n"; +echo " - Benötigt für 10MB: " . number_format($requiredBytes) . " Bytes\n"; + +if ($uploadMaxBytes < $requiredBytes) { + echo " ⚠️ upload_max_filesize ist zu klein für 10MB Uploads\n"; +} else { + echo " ✅ upload_max_filesize ist ausreichend\n"; +} + +if ($postMaxBytes < $requiredBytes) { + echo " ⚠️ post_max_size ist zu klein für 10MB Uploads\n"; +} else { + echo " ✅ post_max_size ist ausreichend\n"; +} + +// 3. .htaccess für Upload-Limits erstellen +echo "\n3. 🔧 .htaccess Upload-Limits erstellen...\n"; +$htaccessContent = " +# Upload-Limits für Bild-Upload +php_value upload_max_filesize 10M +php_value post_max_size 10M +php_value max_file_uploads 20 +php_value memory_limit 256M +php_value max_execution_time 300 +php_value max_input_time 300 +"; + +if (file_exists('public/.htaccess')) { + $currentHtaccess = file_get_contents('public/.htaccess'); + + // Prüfe ob Upload-Limits bereits vorhanden sind + if (strpos($currentHtaccess, 'upload_max_filesize') === false) { + // Füge Upload-Limits hinzu + $newHtaccess = $currentHtaccess . "\n" . $htaccessContent; + file_put_contents('public/.htaccess', $newHtaccess); + echo " ✅ Upload-Limits zu .htaccess hinzugefügt\n"; + } else { + echo " ℹ️ Upload-Limits bereits in .htaccess vorhanden\n"; + } +} else { + echo " ❌ public/.htaccess nicht gefunden\n"; +} + +// 4. Test-Upload-Funktionalität +echo "\n4. 🧪 Test Upload-Funktionalität...\n"; + +// Prüfe GD Extension +if (extension_loaded('gd')) { + echo " ✅ GD Extension geladen\n"; +} else { + echo " ❌ GD Extension nicht geladen - Bildverarbeitung nicht möglich\n"; +} + +// Prüfe Storage-Verzeichnis +$storagePath = 'storage/app/public/nail_polishes'; +if (is_dir($storagePath)) { + echo " ✅ Storage-Verzeichnis existiert: $storagePath\n"; +} else { + echo " ⚠️ Storage-Verzeichnis existiert nicht: $storagePath\n"; + mkdir($storagePath, 0755, true); + echo " ✅ Storage-Verzeichnis erstellt\n"; +} + +// Prüfe Schreibrechte +if (is_writable($storagePath)) { + echo " ✅ Storage-Verzeichnis beschreibbar\n"; +} else { + echo " ❌ Storage-Verzeichnis nicht beschreibbar\n"; +} + +// 5. Laravel Storage Link prüfen +echo "\n5. 🔗 Laravel Storage Link prüfen...\n"; +$publicStoragePath = 'public/storage'; +if (is_link($publicStoragePath)) { + echo " ✅ Storage Link existiert\n"; +} else { + echo " ⚠️ Storage Link existiert nicht\n"; + if (file_exists('public/storage')) { + echo " ℹ️ public/storage ist ein Verzeichnis, kein Link\n"; + } else { + echo " ℹ️ public/storage existiert nicht\n"; + } +} + +echo "\n✅ Upload-Limits Fix abgeschlossen!\n"; +echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/create-nail-polish\n"; +echo "📝 Versuchen Sie ein Handy-Foto hochzuladen (bis 10MB)\n"; +echo "\n📋 Falls Upload immer noch fehlschlägt:\n"; +echo "- Prüfen Sie die Browser-Entwicklertools (F12) für Details\n"; +echo "- Schauen Sie in storage/logs/laravel.log für Laravel-Fehler\n"; +echo "- Prüfen Sie die Apache-Logs für Server-Fehler\n"; +?> diff --git a/force-upload-fix.sh b/force-upload-fix.sh new file mode 100755 index 0000000..eb12120 --- /dev/null +++ b/force-upload-fix.sh @@ -0,0 +1,158 @@ +#!/bin/bash + +echo "🚨 Force Fix: Upload-Limits erzwingen" +echo "====================================" + +# 1. Laravel Cache komplett leeren +echo "1. 🧹 Laravel Cache komplett leeren..." +php artisan cache:clear 2>/dev/null || echo " ⚠️ cache:clear übersprungen" +php artisan config:clear 2>/dev/null || echo " ⚠️ config:clear übersprungen" +php artisan route:clear 2>/dev/null || echo " ⚠️ route:clear übersprungen" +php artisan view:clear 2>/dev/null || echo " ⚠️ view:clear übersprungen" +php artisan config:cache 2>/dev/null || echo " ⚠️ config:cache übersprungen" + +# 2. Bootstrap Cache leeren +echo "2. 🗂️ Bootstrap Cache leeren..." +rm -f bootstrap/cache/*.php 2>/dev/null || echo " ⚠️ bootstrap/cache/*.php nicht gefunden" + +# 3. .htaccess Upload-Limits erzwingen +echo "3. 🔧 .htaccess Upload-Limits erzwingen..." +cat > public/.htaccess << 'EOF' + + 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] + + +# Upload-Limits für Bild-Upload +php_value upload_max_filesize 10M +php_value post_max_size 10M +php_value max_file_uploads 20 +php_value memory_limit 256M +php_value max_execution_time 300 +php_value max_input_time 300 + +# Protect sensitive files + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + +EOF + +echo " ✅ .htaccess mit Upload-Limits erstellt" + +# 4. PHP-Konfiguration prüfen +echo "4. 🔍 PHP-Konfiguration prüfen..." +php fix-upload-limits.php + +# 5. Apache neu laden +echo "5. 🔄 Apache neu laden..." +systemctl reload apache2 2>/dev/null || service apache2 reload 2>/dev/null || echo " ⚠️ Apache reload fehlgeschlagen" + +# 6. Test-Script erstellen +echo "6. 🧪 Test-Script erstellen..." +cat > test-upload-limits.php << 'EOF' + ini_get('upload_max_filesize'), + 'post_max_size' => ini_get('post_max_size'), + 'max_file_uploads' => ini_get('max_file_uploads'), + 'memory_limit' => ini_get('memory_limit') +]; + +foreach ($limits as $setting => $value) { + echo " - $setting: $value\n"; +} + +// 2. Laravel Validierungsregeln prüfen +echo "\n2. Laravel Validierungsregeln:\n"; +$controllerPath = 'app/Http/Controllers/UserNailPolishController.php'; +if (file_exists($controllerPath)) { + $content = file_get_contents($controllerPath); + if (preg_match('/image.*max:(\d+)/', $content, $matches)) { + $maxKB = $matches[1]; + $maxMB = $maxKB / 1024; + echo " - Bild-Upload-Limit: {$maxKB}KB ({$maxMB}MB)\n"; + + if ($maxMB >= 10) { + echo " ✅ Upload-Limit ist ausreichend (>= 10MB)\n"; + } else { + echo " ❌ Upload-Limit ist zu klein (< 10MB)\n"; + } + } else { + echo " ❌ Keine Bild-Upload-Validierung gefunden\n"; + } +} else { + echo " ❌ Controller nicht gefunden\n"; +} + +// 3. View-Text prüfen +echo "\n3. View-Text:\n"; +$viewPath = 'resources/views/user-nail-polishes/create.blade.php'; +if (file_exists($viewPath)) { + $content = file_get_contents($viewPath); + if (preg_match('/Maximale Größe: (\d+MB)/', $content, $matches)) { + echo " - Angezeigte Größe: {$matches[1]}\n"; + + if ($matches[1] === '10MB') { + echo " ✅ View zeigt korrekte Größe an\n"; + } else { + echo " ❌ View zeigt falsche Größe an\n"; + } + } else { + echo " ❌ Keine Größenangabe in View gefunden\n"; + } +} else { + echo " ❌ View nicht gefunden\n"; +} + +echo "\n✅ Upload-Limits Test abgeschlossen!\n"; +echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/create-nail-polish\n"; +?> +EOF + +echo " ✅ Test-Script erstellt" + +echo "" +echo "✅ Force Upload-Limits Fix abgeschlossen!" +echo "" +echo "🔗 Testen Sie jetzt:" +echo "1. https://neonail.vogt.de.com/create-nail-polish" +echo "2. Versuchen Sie ein Handy-Foto hochzuladen" +echo "" +echo "📝 Falls Problem besteht:" +echo "- Führen Sie php test-upload-limits.php aus" +echo "- Leeren Sie Browser-Cache" +echo "- Testen Sie in einem Inkognito-Fenster" diff --git a/htaccess-root.txt b/htaccess-root.txt new file mode 100755 index 0000000..01f9743 --- /dev/null +++ b/htaccess-root.txt @@ -0,0 +1,24 @@ +# NeoNail DB - Hauptverzeichnis .htaccess +# Umleitung auf public/ Ordner + +# Sicherheit + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + +# Umleitung auf public/ +RewriteEngine On +RewriteRule ^$ public/ [L] +RewriteRule (.*) public/$1 [L] + +# Fallback für direkte PHP-Dateien + + Order allow,deny + Allow from all + diff --git a/index.php b/index.php new file mode 100644 index 0000000..5977fd8 --- /dev/null +++ b/index.php @@ -0,0 +1,18 @@ + /dev/null; then + echo "❌ PHP nicht gefunden!" + exit 1 +fi + +if ! command -v curl &> /dev/null; then + echo "❌ curl nicht gefunden!" + exit 1 +fi + +# 2. Composer herunterladen +echo "⬇️ Lade Composer herunter..." +curl -sS https://getcomposer.org/installer | php + +# 3. Composer global verfügbar machen +echo "🔗 Mache Composer global verfügbar..." +sudo mv composer.phar /usr/local/bin/composer +sudo chmod +x /usr/local/bin/composer + +# 4. Test +echo "✅ Teste Composer..." +composer --version + +echo "" +echo "🎉 Composer erfolgreich installiert!" +echo "📋 Jetzt können Sie ausführen:" +echo " composer install --no-dev" diff --git a/install-gd-extension.sh b/install-gd-extension.sh new file mode 100755 index 0000000..c79a51d --- /dev/null +++ b/install-gd-extension.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +echo "🖼️ GD PHP Extension installieren" +echo "===============================" + +# 1. System-Update +echo "🔄 System-Update..." +apt update + +# 2. GD Extension installieren +echo "📦 Installiere GD Extension..." +apt install -y php-gd + +# 3. Weitere nötige Extensions +echo "📦 Installiere weitere Extensions..." +apt install -y libpng-dev libjpeg-dev libfreetype6-dev + +# 4. PHP-Module neu laden +echo "🔄 Lade PHP-Module neu..." +systemctl reload apache2 2>/dev/null || echo "⚠️ Apache reload übersprungen" +systemctl reload nginx 2>/dev/null || echo "⚠️ Nginx reload übersprungen" + +# 5. GD Extension testen +echo "🧪 Teste GD Extension..." +php -m | grep -i gd + +# 6. PHP-Info für GD +echo "📋 GD PHP-Info:" +php -r "if (extension_loaded('gd')) { echo '✅ GD Extension ist aktiviert\n'; echo 'Version: ' . gd_info()['GD Version'] . '\n'; } else { echo '❌ GD Extension ist NICHT aktiviert\n'; }" + +# 7. Laravel Cache leeren +echo "🧹 Leere Laravel Cache..." +php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen" +php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen" + +echo "" +echo "✅ GD Extension installiert!" +echo "📋 Testen Sie jetzt das Erstellen eines Lackes mit Bild" diff --git a/install-sqlite.sh b/install-sqlite.sh new file mode 100755 index 0000000..c2136a4 --- /dev/null +++ b/install-sqlite.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +echo "🗄️ SQLite-Treiber Installation" +echo "==============================" + +# 1. System-Update +echo "🔄 System-Update..." +apt update + +# 2. SQLite und PHP-SQLite installieren +echo "📦 Installiere SQLite..." +apt install -y sqlite3 php-sqlite3 php-pdo-sqlite + +# 3. PHP-Module neu laden +echo "🔄 Lade PHP-Module neu..." +systemctl reload apache2 2>/dev/null || echo "⚠️ Apache reload übersprungen" +systemctl reload nginx 2>/dev/null || echo "⚠️ Nginx reload übersprungen" + +# 4. PHP-Info prüfen +echo "🔍 Prüfe SQLite-Installation..." +php -m | grep -i sqlite + +echo "" +echo "✅ SQLite-Treiber installiert!" +echo "📋 Testen Sie: php -m | grep sqlite" diff --git a/laravel-test.php b/laravel-test.php new file mode 100755 index 0000000..3e6bb76 --- /dev/null +++ b/laravel-test.php @@ -0,0 +1,114 @@ +Laravel-Test"; + +// 1. Composer autoload testen +echo "

1. Composer Autoload:

"; +if (file_exists('vendor/autoload.php')) { + require_once 'vendor/autoload.php'; + echo "✅ Autoload geladen
"; +} else { + echo "❌ vendor/autoload.php nicht gefunden
"; + echo "Führen Sie 'composer install' aus
"; + exit; +} + +// 2. Laravel Bootstrap testen +echo "

2. Laravel Bootstrap:

"; +if (file_exists('bootstrap/app.php')) { + try { + $app = require_once 'bootstrap/app.php'; + echo "✅ Laravel App geladen
"; + } catch (Exception $e) { + echo "❌ Laravel Bootstrap Fehler: " . $e->getMessage() . "
"; + } +} else { + echo "❌ bootstrap/app.php nicht gefunden
"; +} + +// 3. .env laden testen +echo "

3. .env Konfiguration:

"; +if (file_exists('.env')) { + $env_content = file_get_contents('.env'); + echo "✅ .env Datei gefunden
"; + + // Wichtige Einstellungen prüfen + $checks = [ + 'APP_ENV' => 'production', + 'APP_DEBUG' => 'false', + 'DB_CONNECTION' => 'sqlite', + 'DB_DATABASE' => 'database.sqlite' + ]; + + foreach ($checks as $key => $expected) { + if (preg_match("/^$key=(.*)$/m", $env_content, $matches)) { + $value = trim($matches[1]); + $status = ($value === $expected) ? "✅" : "⚠️"; + echo "$status $key = $value (erwartet: $expected)
"; + } else { + echo "❌ $key nicht gefunden
"; + } + } +} else { + echo "❌ .env Datei nicht gefunden
"; +} + +// 4. SQLite-Verbindung testen +echo "

4. SQLite-Verbindung:

"; +if (file_exists('database.sqlite')) { + try { + $pdo = new PDO('sqlite:database.sqlite'); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + echo "✅ SQLite-Verbindung erfolgreich
"; + + // Tabellen prüfen + $tables = $pdo->query("SELECT name FROM sqlite_master WHERE type='table'")->fetchAll(PDO::FETCH_COLUMN); + echo "Gefundene Tabellen: " . implode(', ', $tables) . "
"; + + } catch (PDOException $e) { + echo "❌ SQLite-Fehler: " . $e->getMessage() . "
"; + } +} else { + echo "❌ database.sqlite nicht gefunden
"; +} + +// 5. Storage-Verzeichnis testen +echo "

5. Storage-Verzeichnis:

"; +if (is_dir('storage')) { + if (is_writable('storage')) { + echo "✅ storage/ ist schreibbar
"; + } else { + echo "❌ storage/ ist nicht schreibbar
"; + } + + // Storage-Link prüfen + if (is_link('public/storage')) { + echo "✅ Storage-Link existiert
"; + } else { + echo "⚠️ Storage-Link fehlt (php artisan storage:link)
"; + } +} else { + echo "❌ storage/ Verzeichnis nicht gefunden
"; +} + +// 6. Cache-Verzeichnis testen +echo "

6. Cache-Verzeichnis:

"; +if (is_dir('bootstrap/cache')) { + if (is_writable('bootstrap/cache')) { + echo "✅ bootstrap/cache/ ist schreibbar
"; + } else { + echo "❌ bootstrap/cache/ ist nicht schreibbar
"; + } +} else { + echo "❌ bootstrap/cache/ Verzeichnis nicht gefunden
"; +} + +echo "
"; +echo "

Empfohlene Aktionen:

"; +echo "1. Falls Composer fehlt: composer install ausführen
"; +echo "2. Falls .env falsch: env-sqlite-example.txt zu .env kopieren
"; +echo "3. Falls Berechtigungen falsch: chmod 755 storage/ bootstrap/cache/
"; +echo "4. Falls SQLite fehlt: touch database.sqlite && chmod 664 database.sqlite
"; +echo "5. Falls Storage-Link fehlt: php artisan storage:link
"; +echo "6. Migrationen ausführen: php artisan migrate --force
"; +?> diff --git a/make-existing-user-admin.php b/make-existing-user-admin.php new file mode 100644 index 0000000..7ac4eac --- /dev/null +++ b/make-existing-user-admin.php @@ -0,0 +1,71 @@ +make('Illuminate\Contracts\Console\Kernel')->bootstrap(); + + echo "

👑 User zum Admin machen

"; + + // Alle User anzeigen + echo "

👥 Alle User:

"; + $allUsers = User::all(); + + if ($allUsers->count() > 0) { + echo ""; + echo ""; + + foreach ($allUsers as $user) { + $isAdmin = ($user->email === 'admin@neonail.com' || $user->email === 'neueradmin@neonail.com'); + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + } + echo "
IDNameEmailErstelltAktion
{$user->id}{$user->name}{$user->email}{$user->created_at}" . ($isAdmin ? "👑 Admin" : "👤 User") . "
"; + + // User zum Admin machen (Beispiel: User mit ID 2) + $userId = 2; // Ändern Sie diese ID + $user = User::find($userId); + + if ($user) { + echo "

🔧 User zum Admin machen:

"; + echo "

User: {$user->name} ({$user->email})

"; + + // Passwort ändern (optional) + $newPassword = 'admin123'; + $user->password = bcrypt($newPassword); + $user->save(); + + echo "

✅ User wurde zum Admin gemacht!

"; + echo "

Neues Passwort: {$newPassword}

"; + echo "

Login: {$user->email} / {$newPassword}

"; + } else { + echo "

❌ User mit ID {$userId} nicht gefunden

"; + } + + } else { + echo "

❌ Keine User gefunden

"; + } + + echo "

🔑 Admin-Login:

"; + echo "

Verwenden Sie eine der Admin-Emails:

"; + echo "
    "; + echo "
  • admin@neonail.com
  • "; + echo "
  • neueradmin@neonail.com
  • "; + echo "
"; + echo "

Passwort: admin123

"; + echo "

🚀 Zur Anwendung

"; + +} catch (Exception $e) { + echo "

❌ Fehler:

"; + echo "

{$e->getMessage()}

"; +} +?> diff --git a/make-user-admin.php b/make-user-admin.php new file mode 100644 index 0000000..54ce959 --- /dev/null +++ b/make-user-admin.php @@ -0,0 +1,65 @@ +make('Illuminate\Contracts\Console\Kernel')->bootstrap(); + + echo "

👑 Neuen Admin-User erstellen

"; + + // Prüfe ob User bereits existiert + $email = 'neueradmin@neonail.com'; + $existingUser = User::where('email', $email)->first(); + + if ($existingUser) { + echo "

✅ User existiert bereits!

"; + echo "

Name: {$existingUser->name}

"; + echo "

Email: {$existingUser->email}

"; + echo "

ID: {$existingUser->id}

"; + echo "

Erstellt: {$existingUser->created_at}

"; + } else { + // Neuen Admin-User erstellen + $newAdmin = User::create([ + 'name' => 'Neuer Admin', + 'email' => $email, + 'password' => bcrypt('admin123') + ]); + + echo "

✅ Neuer Admin-User erstellt!

"; + echo "

Name: {$newAdmin->name}

"; + echo "

Email: {$newAdmin->email}

"; + echo "

Passwort: admin123

"; + echo "

ID: {$newAdmin->id}

"; + } + + // Alle Admin-User anzeigen + echo "

👑 Alle Admin-User:

"; + $allUsers = User::all(); + + echo ""; + echo ""; + + foreach ($allUsers as $user) { + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + } + echo "
IDNameEmailErstellt
{$user->id}{$user->name}{$user->email}{$user->created_at}
"; + + echo "

🔑 Login-Daten:

"; + echo "

Email: neueradmin@neonail.com

"; + echo "

Passwort: admin123

"; + echo "

🚀 Zur Anwendung

"; + +} catch (Exception $e) { + echo "

❌ Fehler:

"; + echo "

{$e->getMessage()}

"; +} +?> diff --git a/monitor-logs.php b/monitor-logs.php new file mode 100644 index 0000000..8b3b10b --- /dev/null +++ b/monitor-logs.php @@ -0,0 +1,137 @@ + diff --git a/package.json b/package.json new file mode 100755 index 0000000..a5707d8 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://json.schemastore.org/package.json", + "private": true, + "type": "module", + "scripts": { + "build": "vite build", + "dev": "vite" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.0.0", + "axios": "^1.11.0", + "concurrently": "^9.0.1", + "laravel-vite-plugin": "^2.0.0", + "tailwindcss": "^4.0.0", + "vite": "^7.0.4" + } +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100755 index 0000000..5fd5bcf --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,34 @@ + + + + + tests/Unit + + + tests/Feature + + + + + app + + + + + + + + + + + + + + + + + diff --git a/public/.htaccess b/public/.htaccess new file mode 100755 index 0000000..ebe59fc --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,76 @@ + + + Options -MultiViews -Indexes + + + RewriteEngine On + + # 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] + + +# Security Headers + + Header always set X-Content-Type-Options nosniff + Header always set X-Frame-Options DENY + Header always set X-XSS-Protection "1; mode=block" + Header always set Referrer-Policy "strict-origin-when-cross-origin" + + +# Protect sensitive files + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + +# Compression + + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/html + AddOutputFilterByType DEFLATE text/xml + AddOutputFilterByType DEFLATE text/css + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE application/xhtml+xml + AddOutputFilterByType DEFLATE application/rss+xml + AddOutputFilterByType DEFLATE application/javascript + AddOutputFilterByType DEFLATE application/x-javascript + + +# Cache Control + + ExpiresActive on + ExpiresByType text/css "access plus 1 year" + ExpiresByType application/javascript "access plus 1 year" + ExpiresByType image/png "access plus 1 year" + ExpiresByType image/jpg "access plus 1 year" + ExpiresByType image/jpeg "access plus 1 year" + ExpiresByType image/gif "access plus 1 year" + ExpiresByType image/svg+xml "access plus 1 year" + + +# Upload-Limits für Bild-Upload +php_value upload_max_filesize 10M +php_value post_max_size 10M +php_value max_file_uploads 20 +php_value memory_limit 256M diff --git a/public/.htaccess.backup b/public/.htaccess.backup new file mode 100755 index 0000000..7ac69b1 --- /dev/null +++ b/public/.htaccess.backup @@ -0,0 +1,70 @@ + + + Options -MultiViews -Indexes + + + RewriteEngine On + + # 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] + + +# Security Headers + + Header always set X-Content-Type-Options nosniff + Header always set X-Frame-Options DENY + Header always set X-XSS-Protection "1; mode=block" + Header always set Referrer-Policy "strict-origin-when-cross-origin" + + +# Protect sensitive files + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + +# Compression + + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/html + AddOutputFilterByType DEFLATE text/xml + AddOutputFilterByType DEFLATE text/css + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE application/xhtml+xml + AddOutputFilterByType DEFLATE application/rss+xml + AddOutputFilterByType DEFLATE application/javascript + AddOutputFilterByType DEFLATE application/x-javascript + + +# Cache Control + + ExpiresActive on + ExpiresByType text/css "access plus 1 year" + ExpiresByType application/javascript "access plus 1 year" + ExpiresByType image/png "access plus 1 year" + ExpiresByType image/jpg "access plus 1 year" + ExpiresByType image/jpeg "access plus 1 year" + ExpiresByType image/gif "access plus 1 year" + ExpiresByType image/svg+xml "access plus 1 year" + diff --git a/public/.htaccess.simple b/public/.htaccess.simple new file mode 100644 index 0000000..93dcc04 --- /dev/null +++ b/public/.htaccess.simple @@ -0,0 +1,41 @@ + + + Options -MultiViews -Indexes + + + 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] + + +# Protect sensitive files + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100755 index 0000000..e69de29 diff --git a/public/index.php b/public/index.php new file mode 100755 index 0000000..ee8f07e --- /dev/null +++ b/public/index.php @@ -0,0 +1,20 @@ +handleRequest(Request::capture()); diff --git a/public/logout-test.blade.php b/public/logout-test.blade.php new file mode 100644 index 0000000..0b99b36 --- /dev/null +++ b/public/logout-test.blade.php @@ -0,0 +1,15 @@ + + + + Logout Test + + + +

Logout Test

+
+ @csrf + +
+

Route: {{ route("logout") }}

+ + \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt new file mode 100755 index 0000000..eb05362 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/quick-500-fix.sh b/quick-500-fix.sh new file mode 100755 index 0000000..ac8a467 --- /dev/null +++ b/quick-500-fix.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +echo "🚨 Quick Fix: HTTP 500 Internal Server Error" +echo "===========================================" + +# 1. Debug aktivieren +echo "1. 🐛 Debug aktivieren..." +if [ -f .env ]; then + sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env + sed -i 's/APP_ENV=production/APP_ENV=local/' .env + echo " ✅ Debug-Modus aktiviert" +else + echo " ❌ .env Datei nicht gefunden" +fi + +# 2. Berechtigungen reparieren +echo "2. 🔐 Berechtigungen reparieren..." +chmod -R 755 storage/ +chmod -R 755 bootstrap/cache/ +chown -R www-data:www-data storage/ +chown -R www-data:www-data bootstrap/cache/ +echo " ✅ Berechtigungen repariert" + +# 3. Cache leeren +echo "3. 🧹 Cache leeren..." +rm -f bootstrap/cache/*.php 2>/dev/null || echo " ⚠️ bootstrap/cache/*.php nicht gefunden" +rm -f storage/framework/cache/* 2>/dev/null || echo " ⚠️ storage/framework/cache/* nicht gefunden" +rm -f storage/framework/views/* 2>/dev/null || echo " ⚠️ storage/framework/views/* nicht gefunden" +echo " ✅ Cache geleert" + +# 4. Log-Dateien erstellen +echo "4. 📝 Log-Dateien erstellen..." +mkdir -p storage/logs/ +touch storage/logs/laravel.log +chmod 666 storage/logs/laravel.log +chown www-data:www-data storage/logs/laravel.log +echo " ✅ Log-Dateien erstellt" + +# 5. Debug-Script ausführen +echo "5. 🔍 Debug-Script ausführen..." +php debug-500-error.php + +echo "" +echo "✅ Quick Fix abgeschlossen!" +echo "" +echo "🔗 Testen Sie jetzt:" +echo "1. https://neonail.vogt.de.com" +echo "2. Falls Fehler bestehen, prüfen Sie die Debug-Ausgabe oben" +echo "3. Schauen Sie in storage/logs/laravel.log für Details" diff --git a/quick-debug.sh b/quick-debug.sh new file mode 100755 index 0000000..2cf2de3 --- /dev/null +++ b/quick-debug.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +echo "🔧 Schnelle Debug-Aktivierung" +echo "============================" + +# 1. Debug aktivieren +echo "📝 Aktiviere Debug-Modus..." +sed -i 's/APP_DEBUG=false/APP_DEBUG=true/' .env +echo "✅ APP_DEBUG=true gesetzt" + +# 2. Cache leeren +echo "🧹 Leere Laravel Cache..." +php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen" +php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen" + +# 3. Berechtigungen prüfen +echo "🔐 Prüfe Berechtigungen..." +chmod -R 777 storage/ 2>/dev/null +chmod -R 777 bootstrap/cache/ 2>/dev/null + +# 4. Test +echo "🧪 Teste Anwendung..." +curl -s http://192.168.30.81 | head -20 + +echo "" +echo "✅ Debug aktiviert!" +echo "📋 Öffnen Sie: http://192.168.30.81" +echo "📋 Fehlermeldung wird jetzt angezeigt" diff --git a/resources/css/app.css b/resources/css/app.css new file mode 100755 index 0000000..3e6abea --- /dev/null +++ b/resources/css/app.css @@ -0,0 +1,11 @@ +@import 'tailwindcss'; + +@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php'; +@source '../../storage/framework/views/*.php'; +@source '../**/*.blade.php'; +@source '../**/*.js'; + +@theme { + --font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', + 'Segoe UI Symbol', 'Noto Color Emoji'; +} diff --git a/resources/js/app.js b/resources/js/app.js new file mode 100755 index 0000000..e59d6a0 --- /dev/null +++ b/resources/js/app.js @@ -0,0 +1 @@ +import './bootstrap'; diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js new file mode 100755 index 0000000..5f1390b --- /dev/null +++ b/resources/js/bootstrap.js @@ -0,0 +1,4 @@ +import axios from 'axios'; +window.axios = axios; + +window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; diff --git a/resources/views/admin/dashboard.blade.php b/resources/views/admin/dashboard.blade.php new file mode 100755 index 0000000..8261e29 --- /dev/null +++ b/resources/views/admin/dashboard.blade.php @@ -0,0 +1,141 @@ +@extends('layouts.app') + +@section('title', 'Admin Dashboard - NeoNail DB') + +@section('content') +
+
+

+ Admin Dashboard +

+
+
+ + +
+
+
+
+ +

{{ $totalUsers }}

+

Benutzer

+
+
+
+
+
+
+ +

{{ $totalNailPolishes }}

+

Nagellacke

+
+
+
+
+
+
+ +

{{ $recentUsers->count() }}

+

Neue Benutzer

+
+
+
+
+
+
+ +

{{ $recentNailPolishes->count() }}

+

Neue Lacke

+
+
+
+
+ + + + + +
+
+
+
+
Neueste Benutzer
+
+
+ @if($recentUsers->count() > 0) +
+ @foreach($recentUsers as $user) +
+
+
{{ $user->name }}
+ {{ $user->email }} +
+ {{ $user->created_at->diffForHumans() }} +
+ @endforeach +
+ @else +

Keine Benutzer vorhanden

+ @endif +
+
+
+ +
+
+
+
Neueste Nagellacke
+
+
+ @if($recentNailPolishes->count() > 0) +
+ @foreach($recentNailPolishes as $nailPolish) +
+
+
{{ $nailPolish->name }}
+ Nr. {{ $nailPolish->number }} +
+ {{ $nailPolish->created_at->diffForHumans() }} +
+ @endforeach +
+ @else +

Keine Nagellacke vorhanden

+ @endif +
+
+
+
+@endsection diff --git a/resources/views/admin/statistics.blade.php b/resources/views/admin/statistics.blade.php new file mode 100755 index 0000000..ab68dbf --- /dev/null +++ b/resources/views/admin/statistics.blade.php @@ -0,0 +1,128 @@ +@extends('layouts.app') + +@section('title', 'Statistiken - NeoNail DB') + +@section('content') +
+
+

+ Statistiken +

+
+
+ + +
+
+
+
+ +

{{ $totalUsers }}

+

Gesamte Benutzer

+
+
+
+
+
+
+ +

{{ $totalNailPolishes }}

+

Gesamte Nagellacke

+
+
+
+
+
+
+ +

{{ $usersWithCollections }}

+

Benutzer mit Sammlung

+
+
+
+
+
+
+ +

{{ round($averageCollectionSize, 1) }}

+

Ø Sammlungsgröße

+
+
+
+
+ + +
+
+
+
+
Top 10 Benutzer nach Sammlungsgröße
+
+
+ @if($topUsers->count() > 0) +
+ + + + + + + + + + + + + @foreach($topUsers as $index => $user) + + + + + + + + + @endforeach + +
RangBenutzerE-MailSammlungRegistriertAktionen
+ @if($index === 0) + + @elseif($index === 1) + + @elseif($index === 2) + + @else + {{ $index + 1 }} + @endif + +
+ +
+ {{ $user->name }} + @if($user->email === 'admin@neonail.com') + Admin + @endif +
+
+
{{ $user->email }} + + {{ $user->nail_polishes_count }} Lacke + + {{ $user->created_at->format('d.m.Y') }} + + Sammlung + +
+
+ @else +
+ +

Noch keine Daten verfügbar

+
+ @endif +
+
+
+
+@endsection diff --git a/resources/views/admin/users/create.blade.php b/resources/views/admin/users/create.blade.php new file mode 100755 index 0000000..be91bbb --- /dev/null +++ b/resources/views/admin/users/create.blade.php @@ -0,0 +1,99 @@ +@extends('layouts.app') + +@section('title', 'Neuen User erstellen - NeoNail DB') + +@section('content') +
+
+
+
+

+ Neuen User erstellen +

+
+
+ @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + +
+ @csrf + +
+ + + @error('name') +
{{ $message }}
+ @enderror +
+ +
+ + + @error('email') +
{{ $message }}
+ @enderror +
+ +
+ + + @error('password') +
{{ $message }}
+ @enderror +
+ + Das Passwort muss mindestens 8 Zeichen lang sein. +
+
+ +
+ + +
+ +
+ + + Abbrechen + +
+
+
+
+ + +
+
+
+ Hinweise +
+
+
+
    +
  • Der neue User kann sich sofort mit der Email-Adresse und dem Passwort anmelden
  • +
  • Der User kann eigene Lacke erstellen und verwalten
  • +
  • Der User kann Lacke aus dem Hauptkatalog zu seiner Sammlung hinzufügen
  • +
  • Sie können den User später bearbeiten oder löschen
  • +
+
+
+
+
+@endsection diff --git a/resources/views/admin/users/edit.blade.php b/resources/views/admin/users/edit.blade.php new file mode 100755 index 0000000..91bb0fa --- /dev/null +++ b/resources/views/admin/users/edit.blade.php @@ -0,0 +1,131 @@ +@extends('layouts.app') + +@section('title', 'User bearbeiten - NeoNail DB') + +@section('content') +
+
+
+
+

+ User bearbeiten: {{ $user->name }} +

+
+
+ @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + +
+ @csrf + @method('PUT') + +
+ + + @error('name') +
{{ $message }}
+ @enderror +
+ +
+ + + @error('email') +
{{ $message }}
+ @enderror +
+ +
+ + + @error('password') +
{{ $message }}
+ @enderror +
+ + Lassen Sie das Feld leer, um das Passwort nicht zu ändern. Mindestens 8 Zeichen. +
+
+ +
+ + +
+ +
+
+ is_admin) ? 'checked' : '' }}> + +
+
+ + Admins haben Zugriff auf alle Admin-Funktionen und können andere User verwalten. +
+
+ +
+ + + Abbrechen + +
+
+
+
+ + +
+
+
+ User-Informationen +
+
+
+
+
+

User-ID: {{ $user->id }}

+

Erstellt: {{ $user->created_at->format('d.m.Y H:i') }}

+

Letzte Änderung: {{ $user->updated_at->format('d.m.Y H:i') }}

+
+
+

Sammlung: {{ $user->nailPolishes()->count() }} Lacke

+

Status: + @if($user->email === 'admin@neonail.com' || $user->email === 'neueradmin@neonail.com') + Admin + @else + User + @endif +

+
+
+ + +
+
+
+
+@endsection diff --git a/resources/views/admin/users/index.blade.php b/resources/views/admin/users/index.blade.php new file mode 100755 index 0000000..0bdd6e5 --- /dev/null +++ b/resources/views/admin/users/index.blade.php @@ -0,0 +1,137 @@ +@extends('layouts.app') + +@section('title', 'User-Verwaltung - NeoNail DB') + +@section('content') +
+
+
+

+ User-Verwaltung +

+

Verwalten Sie alle Benutzer der Anwendung

+
+ +
+ + +
+
+
+ + + @if($search) + + + + @endif +
+
+
+ + {{ $users->total() }} User{{ $users->total() != 1 ? 's' : '' }} gefunden + +
+
+ + @if($users->count() > 0) +
+
+
+ + + + + + + + + + + + + @foreach($users as $user) + + + + + + + + + @endforeach + +
IDNameEmailErstelltSammlungAktionen
{{ $user->id }} + {{ $user->name }} + @if($user->isAdmin()) + Admin + @endif + {{ $user->email }}{{ $user->created_at->format('d.m.Y H:i') }} + @php $collectionCount = $user->nailPolishes()->count(); @endphp + {{ $collectionCount }} Lack{{ $collectionCount != 1 ? 'e' : '' }} + +
+ + + + + + + @if($user->email !== 'admin@neonail.com') +
+ @csrf + @method('DELETE') + +
+ @endif +
+
+
+
+
+ + + @if($users->hasPages()) +
+
+ +
+
+ @endif + @else +
+ +

Keine User gefunden

+

+ @if($search) + Keine User gefunden, die "{{ $search }}" entsprechen. + @else + Es sind noch keine User in der Anwendung registriert. + @endif +

+ + Ersten User erstellen + +
+ @endif +
+@endsection diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php new file mode 100755 index 0000000..e6a5913 --- /dev/null +++ b/resources/views/auth/login.blade.php @@ -0,0 +1,68 @@ +@extends('layouts.app') + +@section('title', 'Anmelden - NeoNail DB') + +@section('content') +
+
+
+
+
+ +

NeoNail DB

+

Anmelden um Ihre Sammlung zu verwalten

+
+ +
+ @csrf + +
+ +
+ + +
+ @error('email') + + {{ $message }} + + @enderror +
+ +
+ +
+ + +
+ @error('password') + + {{ $message }} + + @enderror +
+ +
+
+ + +
+
+ +
+ +
+
+ + +
+
+
+
+@endsection diff --git a/resources/views/emails/welcome-user.blade.php b/resources/views/emails/welcome-user.blade.php new file mode 100644 index 0000000..019d16b --- /dev/null +++ b/resources/views/emails/welcome-user.blade.php @@ -0,0 +1,221 @@ + + + + + Willkommen bei der NeoNail DB + + + +
+
+

🎨 NeoNail DB

+

Willkommen bei Ihrer persönlichen Nagellack-Datenbank

+
+ +
+
+

Hallo {{ $user->name }}!

+

Willkommen bei der NeoNail Datenbank! Ihr Account wurde erfolgreich erstellt.

+
+ + + +
+

⚠️ Wichtig: Passwort ändern

+

Aus Sicherheitsgründen bitten wir Sie, Ihr Passwort nach dem ersten Login zu ändern. Sie können dies in Ihren Account-Einstellungen tun.

+
+ + + +
+

🎯 Was Sie mit der NeoNail DB machen können:

+
    +
  • Ihre persönliche Nagellack-Sammlung verwalten
  • +
  • Neue Lacke hinzufügen und fotografieren
  • +
  • Nach Lacken suchen (Name oder Nummer)
  • +
  • Mobile-optimierte Benutzeroberfläche
  • +
  • Kollaborativer Katalog mit anderen Usern
  • +
+
+ + @if($user->isAdmin()) +
+

👑 Admin-Account

+

Sie haben Admin-Rechte und können andere User verwalten sowie den Nagellack-Katalog administrieren.

+
+ @endif + +

+ Bei Fragen oder Problemen wenden Sie sich bitte an den Administrator. +

+
+ + +
+ + diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php new file mode 100755 index 0000000..49d34a0 --- /dev/null +++ b/resources/views/layouts/app.blade.php @@ -0,0 +1,228 @@ + + + + + + + @yield("title", "NeoNail Datenbank") + + + + + + + + + @yield("styles") + + + + +
+
+ @if(session("success")) + + @endif + + @if(session("error")) + + @endif + + @yield("content") +
+
+ + + + + + + + @yield("scripts") + + \ No newline at end of file diff --git a/resources/views/manufacturers/create.blade.php b/resources/views/manufacturers/create.blade.php new file mode 100644 index 0000000..0d43cd0 --- /dev/null +++ b/resources/views/manufacturers/create.blade.php @@ -0,0 +1,120 @@ +@extends('layouts.app') + +@section('title', 'Neuer Hersteller') + +@section('content') +
+
+
+
+
+

+ + Neuer Hersteller +

+
+ +
+ @if($errors->any()) + + @endif + +
+ @csrf + +
+ + + @error('name') +
{{ $message }}
+ @enderror +
+ Der Name des Herstellers. Dieser muss eindeutig sein. +
+
+ +
+ + + @error('description') +
{{ $message }}
+ @enderror +
+ Optionale Beschreibung des Herstellers. +
+
+ +
+ + + @error('website') +
{{ $message }}
+ @enderror +
+ Die offizielle Website des Herstellers (optional). +
+
+ +
+ + + @error('country') +
{{ $message }}
+ @enderror +
+ Das Herkunftsland des Herstellers (optional). +
+
+ +
+ + Zurück + + +
+
+
+
+
+
+
+@endsection diff --git a/resources/views/manufacturers/edit.blade.php b/resources/views/manufacturers/edit.blade.php new file mode 100644 index 0000000..bd84c20 --- /dev/null +++ b/resources/views/manufacturers/edit.blade.php @@ -0,0 +1,121 @@ +@extends('layouts.app') + +@section('title', 'Hersteller bearbeiten') + +@section('content') +
+
+
+
+
+

+ + Hersteller bearbeiten: {{ $manufacturer->name }} +

+
+ +
+ @if($errors->any()) + + @endif + +
+ @csrf + @method('PUT') + +
+ + + @error('name') +
{{ $message }}
+ @enderror +
+ Der Name des Herstellers. Dieser muss eindeutig sein. +
+
+ +
+ + + @error('description') +
{{ $message }}
+ @enderror +
+ Optionale Beschreibung des Herstellers. +
+
+ +
+ + + @error('website') +
{{ $message }}
+ @enderror +
+ Die offizielle Website des Herstellers (optional). +
+
+ +
+ + + @error('country') +
{{ $message }}
+ @enderror +
+ Das Herkunftsland des Herstellers (optional). +
+
+ +
+ + Zurück + + +
+
+
+
+
+
+
+@endsection diff --git a/resources/views/manufacturers/index.blade.php b/resources/views/manufacturers/index.blade.php new file mode 100644 index 0000000..7784f63 --- /dev/null +++ b/resources/views/manufacturers/index.blade.php @@ -0,0 +1,163 @@ +@extends('layouts.app') + +@section('title', 'Hersteller') + +@section('content') +
+
+
+
+
+

+ + Hersteller +

+ + Neuer Hersteller + +
+ +
+ +
+
+ + + @if($search) + + + + @endif +
+
+ + @if(session('success')) + + @endif + + @if(session('error')) + + @endif + + @if($manufacturers->count() > 0) +
+ + + + + + + + + + + + + @foreach($manufacturers as $manufacturer) + + + + + + + + + @endforeach + +
NameLandWebsiteNagellackeErstelltAktionen
+ {{ $manufacturer->name }} + @if($manufacturer->description) +
+ {{ Str::limit($manufacturer->description, 50) }} + @endif +
+ @if($manufacturer->country) + {{ $manufacturer->country }} + @else + - + @endif + + @if($manufacturer->website) + + + Website + + @else + - + @endif + + {{ $manufacturer->nail_polishes_count }} + + + {{ $manufacturer->created_at->format('d.m.Y') }} + + +
+ + + + + + + @if(!$manufacturer->hasNailPolishes()) +
+ @csrf + @method('DELETE') + +
+ @endif +
+
+
+ + +
+ {{ $manufacturers->appends(['search' => $search])->links() }} +
+ @else +
+ +

Keine Hersteller gefunden

+ @if($search) +

Keine Hersteller für "{{ $search }}" gefunden.

+ + Alle Hersteller anzeigen + + @else +

Erstellen Sie den ersten Hersteller.

+ + Ersten Hersteller erstellen + + @endif +
+ @endif +
+
+
+
+
+@endsection diff --git a/resources/views/manufacturers/show.blade.php b/resources/views/manufacturers/show.blade.php new file mode 100644 index 0000000..7c1ea40 --- /dev/null +++ b/resources/views/manufacturers/show.blade.php @@ -0,0 +1,153 @@ +@extends('layouts.app') + +@section('title', $manufacturer->name) + +@section('content') +
+
+
+
+
+

+ + {{ $manufacturer->name }} +

+ +
+ +
+
+
+
Informationen
+
+
Name:
+
{{ $manufacturer->name }}
+ + @if($manufacturer->country) +
Land:
+
+ {{ $manufacturer->country }} +
+ @endif + + @if($manufacturer->website) +
Website:
+
+ + + {{ $manufacturer->website }} + +
+ @endif + +
Nagellacke:
+
+ {{ $manufacturer->nailPolishes->count() }} +
+ +
Erstellt:
+
{{ $manufacturer->created_at->format('d.m.Y H:i') }}
+ +
Aktualisiert:
+
{{ $manufacturer->updated_at->format('d.m.Y H:i') }}
+
+
+ +
+ @if($manufacturer->description) +
Beschreibung
+

{{ $manufacturer->description }}

+ @endif +
+
+
+
+
+ +
+
+
+
+ + Statistiken +
+
+
+
+
{{ $manufacturer->nailPolishes->count() }}
+

Nagellacke

+
+
+
+
+
+ + @if($manufacturer->nailPolishes->count() > 0) +
+
+
+
+

+ + Nagellacke von {{ $manufacturer->name }} +

+
+
+
+ @foreach($manufacturer->nailPolishes as $nailPolish) +
+
+ @if($nailPolish->image_path) + {{ $nailPolish->name }} + @else +
+ +
+ @endif +
+
{{ $nailPolish->name }}
+

{{ $nailPolish->number }}

+ + Anzeigen + +
+
+
+ @endforeach +
+
+
+
+
+ @else +
+
+
+
+ +

Keine Nagellacke vorhanden

+

Für diesen Hersteller sind noch keine Nagellacke eingetragen.

+ + Ersten Nagellack hinzufügen + +
+
+
+
+ @endif +
+@endsection diff --git a/resources/views/nail-polishes/create.blade.php b/resources/views/nail-polishes/create.blade.php new file mode 100755 index 0000000..d79ced2 --- /dev/null +++ b/resources/views/nail-polishes/create.blade.php @@ -0,0 +1,75 @@ +@extends('layouts.app') + +@section('title', 'Neuen Nagellack hinzufügen - NeoNail DB') + +@section('content') +
+
+
+
+

+ Neuen Nagellack hinzufügen +

+
+
+
+ @csrf + +
+ + + @error('name') +
{{ $message }}
+ @enderror +
+ +
+ + + @error('number') +
{{ $message }}
+ @enderror +
+ +
+ + +
+ + Sie können ein Bild von Ihrer Kamera aufnehmen oder eine Datei auswählen. +
+ @error('image') +
{{ $message }}
+ @enderror +
+ +
+ + + Abbrechen + +
+
+
+
+
+
+@endsection + +@section('scripts') + +@endsection diff --git a/resources/views/nail-polishes/edit.blade.php b/resources/views/nail-polishes/edit.blade.php new file mode 100755 index 0000000..071f88d --- /dev/null +++ b/resources/views/nail-polishes/edit.blade.php @@ -0,0 +1,70 @@ +@extends('layouts.app') + +@section('title', 'Nagellack bearbeiten - NeoNail DB') + +@section('content') +
+
+
+
+

+ Nagellack bearbeiten +

+
+
+
+ @csrf + @method('PUT') + +
+ + + @error('name') +
{{ $message }}
+ @enderror +
+ +
+ + + @error('number') +
{{ $message }}
+ @enderror +
+ +
+ + @if($nailPolish->image_path) +
+ {{ $nailPolish->name }} +

Aktuelles Bild

+
+ @endif + +
+ + Sie können ein neues Bild von Ihrer Kamera aufnehmen oder eine Datei auswählen. +
+ @error('image') +
{{ $message }}
+ @enderror +
+ +
+ + + Abbrechen + +
+
+
+
+
+
+@endsection diff --git a/resources/views/nail-polishes/index.blade.php b/resources/views/nail-polishes/index.blade.php new file mode 100755 index 0000000..ec8b41c --- /dev/null +++ b/resources/views/nail-polishes/index.blade.php @@ -0,0 +1,121 @@ +@extends('layouts.app') + +@section('title', 'Nagellack-Verwaltung - NeoNail DB') + +@section('content') +
+
+
+

+ NeoNail-Lacke verwalten +

+

Verwalten Sie alle verfügbaren NeoNail-Lacke im System

+
+ +
+ + @if(session('success')) + + @endif + + @if(session('error')) + + @endif + + @if($nailPolishes->count() > 0) +
+ @foreach($nailPolishes as $nailPolish) +
+
+ @if($nailPolish->image_path) + {{ $nailPolish->name }} + @else +
+ +
+ @endif + +
+
{{ $nailPolish->name }}
+

Nr. {{ $nailPolish->number }}

+ @if($nailPolish->manufacturer) +

+ {{ $nailPolish->manufacturer->name }} +

+ @endif + + + @php + $userCount = $nailPolish->users()->count(); + @endphp +

+ + {{ $userCount }} User{{ $userCount != 1 ? 's' : '' }} haben diesen Lack +

+ +
+
+ + User anzeigen + + + Bearbeiten + +
+ @csrf + @method('DELETE') + +
+
+
+
+
+
+ @endforeach +
+ + + @if($nailPolishes->hasPages()) +
+
+ +
+
+ @endif + @else +
+ +

Noch keine Lacke vorhanden

+

+ Erstellen Sie den ersten NeoNail-Lack im System! +

+ + Ersten Lack erstellen + +
+ @endif +
+@endsection diff --git a/resources/views/nail-polishes/show-users.blade.php b/resources/views/nail-polishes/show-users.blade.php new file mode 100755 index 0000000..a8fd944 --- /dev/null +++ b/resources/views/nail-polishes/show-users.blade.php @@ -0,0 +1,97 @@ +@extends('layouts.app') + +@section('title', 'User mit diesem Lack - NeoNail DB') + +@section('content') +
+
+
+

+ User mit "{{ $nailPolish->name }}" +

+

Benutzer, die diesen Lack in ihrer Sammlung haben

+
+ +
+ + +
+
+
+
+ @if($nailPolish->image_path) + {{ $nailPolish->name }} + @else +
+ +
+ @endif +
+
+
{{ $nailPolish->name }}
+

Nummer: {{ $nailPolish->number }}

+

+ {{ $users->total() }} User{{ $users->total() != 1 ? 's' : '' }} +

+
+
+
+
+ + @if($users->count() > 0) +
+
+
Benutzer mit diesem Lack
+
+
+
+ + + + + + + + + + + @foreach($users as $user) + + + + + + + @endforeach + +
NameE-MailRegistriert amAktionen
{{ $user->name }}{{ $user->email }}{{ $user->created_at->format('d.m.Y H:i') }} + + Sammlung anzeigen + +
+
+ + + @if($users->hasPages()) +
+ {{ $users->links() }} +
+ @endif +
+
+ @else +
+ +

Keine User gefunden

+

Dieser Lack wird von keinem Benutzer verwendet.

+
+ @endif +
+@endsection diff --git a/resources/views/user-nail-polishes/available.blade.php b/resources/views/user-nail-polishes/available.blade.php new file mode 100755 index 0000000..e8d028f --- /dev/null +++ b/resources/views/user-nail-polishes/available.blade.php @@ -0,0 +1,124 @@ +@extends('layouts.app') + +@section('title', 'Verfügbare Lacke - NeoNail DB') + +@section('content') +
+
+
+

+ Verfügbare NeoNail-Lacke +

+

Lacke, die Sie noch nicht in Ihrer Sammlung haben

+
+ +
+ + +
+ + Hinweis: Diese Lacke sind Teil des gemeinsamen Hauptkatalogs und können nicht gelöscht werden. + Sie können sie nur zu Ihrer persönlichen Sammlung hinzufügen oder entfernen. +
+ + +
+
+
+ + + @if($search) + + + + @endif +
+
+
+ + {{ $nailPolishes->total() }} verfügbare Lack{{ $nailPolishes->total() != 1 ? 'e' : '' }} + +
+
+ + @if($nailPolishes->count() > 0) +
+ @foreach($nailPolishes as $nailPolish) +
+
+ @if($nailPolish->image_path) + {{ $nailPolish->name }} + @else +
+ +
+ @endif + +
+
{{ $nailPolish->name }}
+

Nr. {{ $nailPolish->number }}

+ +
+
+ @csrf + +
+
+
+
+
+ @endforeach +
+ + + @if($nailPolishes->hasPages()) +
+
+ +
+
+ @endif + @else +
+ +

Glückwunsch!

+

+ @if($search) + Keine verfügbaren Lacke gefunden, die "{{ $search }}" entsprechen. + @else + Sie haben bereits alle verfügbaren NeoNail-Lacke in Ihrer Sammlung! + @endif +

+ +
+ @endif +
+@endsection diff --git a/resources/views/user-nail-polishes/create.blade.php b/resources/views/user-nail-polishes/create.blade.php new file mode 100755 index 0000000..eaad505 --- /dev/null +++ b/resources/views/user-nail-polishes/create.blade.php @@ -0,0 +1,175 @@ +@extends('layouts.app') + +@section('title', 'Neuen Lack hinzufügen - NeoNail DB') + +@section('content') +
+
+
+
+

+ Neuen NeoNail-Lack hinzufügen +

+
+
+
+ + Wichtig: Der neue Lack wird automatisch zum Hauptkatalog hinzugefügt und steht dann allen Benutzern zur Verfügung. + Er wird auch automatisch zu Ihrer Sammlung hinzugefügt. +
+ + @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + +
+ @csrf + +
+
+
+ + + @error('name') +
{{ $message }}
+ @enderror +
+
+
+
+ + + @error('number') +
{{ $message }}
+ @enderror +
+
+
+ +
+
+
+ + + @error('manufacturer_id') +
{{ $message }}
+ @enderror + +
+
+
+
+ + +
+ Falls der Hersteller noch nicht existiert, können Sie ihn hier erstellen. +
+
+
+
+ +
+ + +
+ + Sie können ein Bild mit der Handykamera aufnehmen oder eine Datei auswählen. + Maximale Größe: 10MB. Das Bild wird automatisch optimiert. +
+ @error('image') +
{{ $message }}
+ @enderror +
+ +
+ + + Abbrechen + +
+
+
+
+ + +
+
+
+ Hinweise +
+
+
+
    +
  • Der Lack wird automatisch zum Hauptkatalog hinzugefügt
  • +
  • Andere Benutzer können den Lack dann zu ihrer Sammlung hinzufügen
  • +
  • Das Bild wird automatisch auf 400x400 Pixel optimiert
  • +
  • Sie können den Lack später in Ihren Einstellungen bearbeiten
  • +
  • Neue Hersteller werden automatisch erstellt und stehen allen zur Verfügung
  • +
+
+
+
+
+ + +@endsection diff --git a/resources/views/user-nail-polishes/index.blade.php b/resources/views/user-nail-polishes/index.blade.php new file mode 100755 index 0000000..55d67ee --- /dev/null +++ b/resources/views/user-nail-polishes/index.blade.php @@ -0,0 +1,123 @@ +@extends('layouts.app') + +@section('title', 'Meine Sammlung - NeoNail DB') + +@section('content') +
+
+
+

+ Meine NeoNail-Sammlung +

+

Verwalten Sie Ihre persönliche Nagellack-Sammlung

+
+ +
+ + +
+
+
+ + + @if($search) + + + + @endif +
+
+
+ + {{ $nailPolishes->total() }} Lack{{ $nailPolishes->total() != 1 ? 'e' : '' }} in Ihrer Sammlung + +
+
+ + @if($nailPolishes->count() > 0) +
+ @foreach($nailPolishes as $nailPolish) +
+
+ @if($nailPolish->image_path) + {{ $nailPolish->name }} + @else +
+ +
+ @endif + +
+
{{ $nailPolish->name }}
+

Nr. {{ $nailPolish->number }}

+ @if($nailPolish->manufacturer) +

+ {{ $nailPolish->manufacturer->name }} +

+ @endif + +
+
+ @csrf + +
+
+
+
+
+ @endforeach +
+ + + @if($nailPolishes->hasPages()) +
+
+ +
+
+ @endif + @else +
+ +

Ihre Sammlung ist noch leer

+

+ @if($search) + Keine Lacke gefunden, die "{{ $search }}" entsprechen. + @else + Fügen Sie Ihren ersten NeoNail-Lack hinzu! + @endif +

+ +
+ @endif +
+@endsection diff --git a/resources/views/user-nail-polishes/show-user.blade.php b/resources/views/user-nail-polishes/show-user.blade.php new file mode 100755 index 0000000..11e34a3 --- /dev/null +++ b/resources/views/user-nail-polishes/show-user.blade.php @@ -0,0 +1,70 @@ +@extends('layouts.app') + +@section('title', 'Sammlung von ' . $user->name . ' - NeoNail DB') + +@section('content') +
+
+
+

+ Sammlung von {{ $user->name }} +

+ + Zurück zur Benutzerliste + +
+ + +
+
+
+
+
+ +
+

{{ $user->name }}

+

{{ $user->email }}

+ Registriert am {{ $user->created_at->format('d.m.Y') }} +
+
+
+
+
{{ $nailPolishes->count() }}
+

Nagellacke in der Sammlung

+
+
+
+
+ + + @if($nailPolishes->count() > 0) +
+ @foreach($nailPolishes as $nailPolish) +
+
+ @if($nailPolish->image_path) + {{ $nailPolish->name }} + @else +
+ +
+ @endif +
+
{{ $nailPolish->name }}
+

Nr. {{ $nailPolish->number }}

+
+
+
+ @endforeach +
+ @else +
+ +

Keine Nagellacke in der Sammlung

+

{{ $user->name }} hat noch keine NeoNail-Lacke hinzugefügt.

+
+ @endif +
+
+@endsection diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php new file mode 100755 index 0000000..c893b80 --- /dev/null +++ b/resources/views/welcome.blade.php @@ -0,0 +1,277 @@ + + + + + + + Laravel + + + + + + + @if (file_exists(public_path('build/manifest.json')) || file_exists(public_path('hot'))) + @vite(['resources/css/app.css', 'resources/js/app.js']) + @else + + @endif + + +
+ @if (Route::has('login')) + + @endif +
+
+
+
+

Let's get started

+

Laravel has an incredibly rich ecosystem.
We suggest starting with the following.

+ + +
+
+ {{-- Laravel Logo --}} + + + + + + + + + + + {{-- Light Mode 12 SVG --}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{-- Dark Mode 12 SVG --}} + +
+
+
+
+ + @if (Route::has('login')) + + @endif + + diff --git a/routes/console.php b/routes/console.php new file mode 100755 index 0000000..3c9adf1 --- /dev/null +++ b/routes/console.php @@ -0,0 +1,8 @@ +comment(Inspiring::quote()); +})->purpose('Display an inspiring quote'); diff --git a/routes/web.php b/routes/web.php new file mode 100755 index 0000000..5217390 --- /dev/null +++ b/routes/web.php @@ -0,0 +1,64 @@ +route('login'); +}); + +// Authentifizierung (nur für Gäste) +Route::middleware('guest')->group(function () { + Route::get('/login', [LoginController::class, 'showLoginForm'])->name('login'); + Route::post('/login', [LoginController::class, 'login']); +}); + +// Logout (nur für eingeloggte Benutzer) +Route::post('/logout', [LoginController::class, 'logout'])->name('logout')->middleware('auth'); + +// Geschützte Routen +Route::middleware(['auth'])->group(function () { + // Benutzer-Nagellack-Verwaltung + Route::get('/my-collection', [UserNailPolishController::class, 'index'])->name('user-nail-polishes.index'); + Route::get('/available', [UserNailPolishController::class, 'available'])->name('user-nail-polishes.available'); + Route::get('/create-nail-polish', [UserNailPolishController::class, 'create'])->name('user-nail-polishes.create'); + Route::post('/create-nail-polish', [UserNailPolishController::class, 'store'])->name('user-nail-polishes.store'); + Route::post('/add-to-collection/{nailPolish}', [UserNailPolishController::class, 'add'])->name('user-nail-polishes.add'); + Route::post('/remove-from-collection/{nailPolish}', [UserNailPolishController::class, 'remove'])->name('user-nail-polishes.remove'); + + // Admin-Routen + Route::middleware(['admin'])->prefix('admin')->name('admin.')->group(function () { + Route::get('/dashboard', [AdminController::class, 'dashboard'])->name('dashboard'); + Route::get('/users', [AdminController::class, 'users'])->name('users.index'); + Route::get('/users/create', [AdminController::class, 'createUser'])->name('users.create'); + Route::post('/users', [AdminController::class, 'storeUser'])->name('users.store'); + Route::get('/users/{user}/edit', [AdminController::class, 'editUser'])->name('users.edit'); + Route::put('/users/{user}', [AdminController::class, 'updateUser'])->name('users.update'); + Route::delete('/users/{user}', [AdminController::class, 'destroyUser'])->name('users.destroy'); + Route::get('/statistics', [AdminController::class, 'statistics'])->name('statistics'); + Route::get('/users/{user}/collection', [UserNailPolishController::class, 'showUserCollection'])->name('users.collection'); + }); + + // Nagellack-Verwaltung (nur für Admin) + Route::middleware(['admin'])->group(function () { + Route::resource('nail-polishes', NailPolishController::class); + Route::get('/nail-polishes/{nailPolish}/users', [NailPolishController::class, 'showUsers'])->name('nail-polishes.showUsers'); + }); + + // Hersteller-Verwaltung (für alle eingeloggten User) + Route::resource('manufacturers', ManufacturerController::class); + Route::get('/manufacturers-search', [ManufacturerController::class, 'search'])->name('manufacturers.search'); +}); + +// Fallback +Route::fallback(function () { + return redirect()->route('login'); +}); + +// Einfache Logout-Route für Debugging +Route::get('/logout', [App\Http\Controllers\Auth\LoginController::class, 'logout'])->name('logout'); diff --git a/send-mail-to-user.php b/send-mail-to-user.php new file mode 100644 index 0000000..e04f6ef --- /dev/null +++ b/send-mail-to-user.php @@ -0,0 +1,122 @@ +make('Illuminate\Contracts\Console\Kernel')->bootstrap(); + + // User in der Datenbank suchen + $user = \App\Models\User::where('email', $targetEmail)->first(); + + if (!$user) { + echo "❌ User mit E-Mail '$targetEmail' nicht in der Datenbank gefunden!\n"; + echo "\n📋 Verfügbare User:\n"; + $allUsers = \App\Models\User::all(); + foreach ($allUsers as $u) { + $adminBadge = $u->isAdmin() ? ' 👑' : ''; + echo " - {$u->name} ({$u->email}){$adminBadge}\n"; + } + exit; + } + + echo "✅ User gefunden: {$user->name} ({$user->email})\n"; + echo " - Admin-Status: " . ($user->isAdmin() ? 'Ja 👑' : 'Nein') . "\n"; + echo " - Registriert: {$user->created_at->format('d.m.Y H:i')}\n"; + + // E-Mail-Inhalt + $emailContent = "Hallo {$user->name}! + +🎨 Willkommen bei der NeoNail Datenbank! + +Dies ist eine persönliche E-Mail, die speziell an Sie gesendet wurde. + +📋 Ihre Account-Informationen: + - Name: {$user->name} + - E-Mail: {$user->email} + - Registriert: {$user->created_at->format('d.m.Y H:i')} + - Admin-Status: " . ($user->isAdmin() ? 'Ja 👑' : 'Nein') . " + +🎯 Ihre NeoNail DB Features: + - Persönliche Nagellack-Sammlung verwalten + - Neue Lacke hinzufügen und fotografieren + - Nach Lacken suchen (Name oder Nummer) + - Mobile-optimierte Benutzeroberfläche + +🔗 Direkte Links: + - Meine Sammlung: https://neonail.vogt.de.com/my-collection + - Verfügbare Lacke: https://neonail.vogt.de.com/available + - Neuen Lack hinzufügen: https://neonail.vogt.de.com/create-nail-polish + +" . ($user->isAdmin() ? " +👑 Als Admin haben Sie zusätzlichen Zugriff: + - User-Verwaltung: https://neonail.vogt.de.com/admin/users + - Nagellack-Verwaltung: https://neonail.vogt.de.com/nail-polishes + - Dashboard: https://neonail.vogt.de.com/admin/dashboard +" : "") . " +Viele Grüße, +Ihr NeoNail DB Team + +--- +Diese E-Mail wurde automatisch generiert. +Bei Fragen wenden Sie sich an den Administrator."; + + // E-Mail senden + $result = \Illuminate\Support\Facades\Mail::raw($emailContent, function($message) use ($user) { + $message->to($user->email, $user->name) + ->subject('🎨 NeoNail DB - Persönliche Willkommens-E-Mail') + ->from(config('mail.from.address'), config('mail.from.name')); + }); + + echo "\n✅ E-Mail erfolgreich gesendet!\n"; + echo "📧 Empfänger: {$user->email}\n"; + echo "📅 Zeitstempel: " . now() . "\n"; + echo "📋 Betreff: 🎨 NeoNail DB - Persönliche Willkommens-E-Mail\n"; + + // Erfolgs-Bestätigung an Admin + echo "\n📧 Sende Bestätigung an Admin...\n"; + + $adminContent = "Hallo Admin! + +Eine persönliche E-Mail wurde erfolgreich an einen User gesendet. + +📋 Details: + - Empfänger: {$user->name} ({$user->email}) + - Admin-Status: " . ($user->isAdmin() ? 'Ja' : 'Nein') . " + - Zeitstempel: " . now() . " + - E-Mail-Konfiguration: ✅ Funktioniert perfekt + +Die E-Mail-Funktionalität ist vollständig einsatzbereit! + +Viele Grüße, +NeoNail DB System"; + + $adminResult = \Illuminate\Support\Facades\Mail::raw($adminContent, function($message) { + $message->to('oliver@vogt.de.com', 'Admin') + ->subject('✅ NeoNail DB - Persönliche User-E-Mail gesendet') + ->from(config('mail.from.address'), config('mail.from.name')); + }); + + echo " ✅ Admin-Bestätigung gesendet!\n"; + +} catch (Exception $e) { + echo "❌ Fehler beim Senden der E-Mail:\n"; + echo " " . $e->getMessage() . "\n"; +} + +echo "\n✅ Persönliche User-E-Mail abgeschlossen!\n"; +echo "📋 Nächste Schritte:\n"; +echo "1. Prüfen Sie das Postfach von: $targetEmail\n"; +echo "2. Prüfen Sie Ihr Admin-Postfach: oliver@vogt.de.com\n"; +echo "3. Falls keine E-Mails ankommen, prüfen Sie Spam-Ordner\n"; +echo "\n🎯 Die E-Mail-Funktionalität ist jetzt vollständig einsatzbereit!\n"; +?> diff --git a/send-test-mail.php b/send-test-mail.php new file mode 100644 index 0000000..f79df9d --- /dev/null +++ b/send-test-mail.php @@ -0,0 +1,65 @@ +make('Illuminate\Contracts\Console\Kernel')->bootstrap(); + + // Einfache Test-Mail senden + $result = \Illuminate\Support\Facades\Mail::raw('Hallo! + +Dies ist eine Test-Mail von der NeoNail Datenbank. + +✅ E-Mail-Konfiguration funktioniert! +📅 Zeitstempel: ' . now() . ' +🌐 Server: ' . ($_SERVER['SERVER_NAME'] ?? 'Unbekannt') . ' + +Die E-Mail-Funktionalität ist jetzt bereit. + +Viele Grüße, +NeoNail DB System', function($message) use ($testEmail) { + $message->to($testEmail) + ->subject('✅ NeoNail DB - E-Mail-Test erfolgreich!') + ->from(config('mail.from.address'), config('mail.from.name')); + }); + + echo "✅ Test-Mail erfolgreich gesendet!\n"; + echo "📧 Prüfen Sie Ihr Postfach: $testEmail\n"; + echo "📁 Falls keine E-Mail ankommt, prüfen Sie auch den Spam-Ordner\n"; + +} catch (Exception $e) { + echo "❌ Fehler beim Senden der Test-Mail:\n"; + echo " " . $e->getMessage() . "\n\n"; + + echo "🔍 Fehleranalyse:\n"; + if (strpos($e->getMessage(), 'Connection refused') !== false) { + echo " - Problem: Verbindung zum SMTP-Server verweigert\n"; + echo " - Lösung: Prüfen Sie MAIL_HOST und MAIL_PORT\n"; + } elseif (strpos($e->getMessage(), 'Authentication failed') !== false) { + echo " - Problem: Authentifizierung fehlgeschlagen\n"; + echo " - Lösung: Prüfen Sie MAIL_USERNAME und MAIL_PASSWORD\n"; + } elseif (strpos($e->getMessage(), 'SSL') !== false) { + echo " - Problem: SSL/TLS Verbindungsproblem\n"; + echo " - Lösung: Prüfen Sie MAIL_ENCRYPTION (SSL/TLS)\n"; + } else { + echo " - Unbekannter Fehler\n"; + } + + echo "\n📋 Aktuelle E-Mail-Konfiguration:\n"; + echo " - MAIL_HOST: " . config('mail.mailers.smtp.host') . "\n"; + echo " - MAIL_PORT: " . config('mail.mailers.smtp.port') . "\n"; + echo " - MAIL_ENCRYPTION: " . config('mail.mailers.smtp.encryption') . "\n"; + echo " - MAIL_USERNAME: " . config('mail.mailers.smtp.username') . "\n"; + echo " - MAIL_FROM_ADDRESS: " . config('mail.from.address') . "\n"; +} +?> diff --git a/send-user-mail.php b/send-user-mail.php new file mode 100644 index 0000000..0eb89aa --- /dev/null +++ b/send-user-mail.php @@ -0,0 +1,116 @@ +make('Illuminate\Contracts\Console\Kernel')->bootstrap(); + + // Alle User auflisten + echo "1. 👥 Verfügbare User:\n"; + $users = \App\Models\User::all(); + + if ($users->isEmpty()) { + echo " ❌ Keine User in der Datenbank gefunden\n"; + exit; + } + + foreach ($users as $index => $user) { + $adminBadge = $user->isAdmin() ? ' 👑' : ''; + echo " " . ($index + 1) . ". {$user->name} ({$user->email}){$adminBadge}\n"; + } + + // User auswählen (hier können Sie den Index ändern) + $selectedUserIndex = 0; // Erster User (0-basiert) + $selectedUser = $users[$selectedUserIndex]; + + echo "\n2. 📧 Sende E-Mail an: {$selectedUser->name} ({$selectedUser->email})\n"; + + // E-Mail-Inhalt + $emailContent = "Hallo {$selectedUser->name}! + +Willkommen bei der NeoNail Datenbank! 🎨 + +Dies ist eine Test-E-Mail, die an einen registrierten User gesendet wurde. + +📋 Ihre Account-Details: + - Name: {$selectedUser->name} + - E-Mail: {$selectedUser->email} + - Registriert: {$selectedUser->created_at->format('d.m.Y H:i')} + - Admin-Status: " . ($selectedUser->isAdmin() ? 'Ja 👑' : 'Nein') . " + +🎯 Was Sie mit der NeoNail DB machen können: + - Ihre persönliche Nagellack-Sammlung verwalten + - Neue Lacke hinzufügen + - Nach Lacken suchen + - Bilder von Ihren Lacken hochladen + +🔗 Zugriff auf Ihre Sammlung: + https://neonail.vogt.de.com/my-collection + +Viele Grüße, +Ihr NeoNail DB Team + +--- +Diese E-Mail wurde automatisch generiert. +Bei Fragen wenden Sie sich an den Administrator."; + + // E-Mail senden + $result = \Illuminate\Support\Facades\Mail::raw($emailContent, function($message) use ($selectedUser) { + $message->to($selectedUser->email, $selectedUser->name) + ->subject('🎨 Willkommen bei der NeoNail DB - Test-E-Mail') + ->from(config('mail.from.address'), config('mail.from.name')); + }); + + echo " ✅ E-Mail erfolgreich gesendet!\n"; + echo " 📧 Empfänger: {$selectedUser->email}\n"; + echo " 📅 Zeitstempel: " . now() . "\n"; + + // Zusätzliche Info-Mail an Admin + echo "\n3. 📧 Sende Info-Mail an Admin...\n"; + + $adminInfoContent = "Hallo Admin! + +Eine Test-E-Mail wurde erfolgreich an einen User gesendet. + +📋 Details: + - Empfänger: {$selectedUser->name} ({$selectedUser->email}) + - Zeitstempel: " . now() . " + - E-Mail-Konfiguration: ✅ Funktioniert + +Die E-Mail-Funktionalität ist bereit für: + - Passwort-Reset + - Benutzer-Benachrichtigungen + - Admin-Benachrichtigungen + +Viele Grüße, +NeoNail DB System"; + + $adminResult = \Illuminate\Support\Facades\Mail::raw($adminInfoContent, function($message) { + $message->to('oliver@vogt.de.com', 'Admin') + ->subject('📧 NeoNail DB - User-E-Mail erfolgreich gesendet') + ->from(config('mail.from.address'), config('mail.from.name')); + }); + + echo " ✅ Admin-Info-Mail gesendet!\n"; + +} catch (Exception $e) { + echo "❌ Fehler beim Senden der E-Mail:\n"; + echo " " . $e->getMessage() . "\n"; +} + +echo "\n✅ User-E-Mail-Test abgeschlossen!\n"; +echo "📋 Nächste Schritte:\n"; +echo "1. Prüfen Sie das Postfach von: {$selectedUser->email}\n"; +echo "2. Prüfen Sie Ihr Admin-Postfach: oliver@vogt.de.com\n"; +echo "3. Falls keine E-Mails ankommen, prüfen Sie Spam-Ordner\n"; +echo "\n🔗 E-Mail-Funktionen sind jetzt verfügbar für:\n"; +echo "- Passwort-Reset für User\n"; +echo "- Willkommens-E-Mails für neue User\n"; +echo "- Admin-Benachrichtigungen\n"; +echo "- System-Benachrichtigungen\n"; +?> diff --git a/setup-apache.sh b/setup-apache.sh new file mode 100755 index 0000000..f009285 --- /dev/null +++ b/setup-apache.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +echo "🌐 Apache Setup für NeoNail DB" +echo "==============================" + +# 1. .htaccess im Hauptverzeichnis erstellen +echo "📝 Erstelle .htaccess im Hauptverzeichnis..." +cat > .htaccess << 'EOF' +# NeoNail DB - Hauptverzeichnis .htaccess +RewriteEngine On +RewriteRule ^$ public/ [L] +RewriteRule (.*) public/$1 [L] + +# Sicherheit + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + +EOF + +# 2. Apache Virtual Host erstellen +echo "🌐 Erstelle Apache Virtual Host..." +cat > /etc/apache2/sites-available/neonail.conf << 'EOF' + + ServerName 192.168.30.81 + DocumentRoot /var/www/html/public + + + AllowOverride All + Require all granted + + + ErrorLog ${APACHE_LOG_DIR}/neonail_error.log + CustomLog ${APACHE_LOG_DIR}/neonail_access.log combined + +EOF + +# 3. Standard-Site deaktivieren +echo "🔧 Deaktiviere Standard-Site..." +a2dissite 000-default.conf 2>/dev/null || echo "⚠️ Standard-Site bereits deaktiviert" + +# 4. NeoNail-Site aktivieren +echo "✅ Aktiviere NeoNail-Site..." +a2ensite neonail.conf + +# 5. Apache neu laden +echo "🔄 Lade Apache neu..." +systemctl reload apache2 + +# 6. Status prüfen +echo "🔍 Prüfe Apache-Status..." +systemctl status apache2 --no-pager -l + +echo "" +echo "✅ Apache Setup abgeschlossen!" +echo "📋 Testen Sie: http://192.168.30.81" +echo "" +echo "📋 Falls es nicht funktioniert:" +echo "1. Apache-Logs prüfen: tail -f /var/log/apache2/neonail_error.log" +echo "2. Berechtigungen prüfen: ls -la /var/www/html/public/" +echo "3. .htaccess prüfen: cat /var/www/html/public/.htaccess" diff --git a/setup-html-directory.sh b/setup-html-directory.sh new file mode 100755 index 0000000..e05c8d3 --- /dev/null +++ b/setup-html-directory.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +echo "🎨 NeoNail DB - Setup für HTML-Verzeichnis" +echo "==========================================" + +# 1. .env Datei erstellen +echo "📝 Erstelle .env Datei..." +cat > .env << 'EOF' +APP_NAME="NeoNail DB" +APP_ENV=production +APP_KEY=base64:+LTZYPKjkZ+O3iFTgU2sS+9bNvxxvG8Kw8JSEPiG7Rs= +APP_DEBUG=false +APP_URL=http://192.168.30.81 + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=sqlite +DB_DATABASE=database.sqlite + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +FILESYSTEM_DISK=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=mailpit +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=mt1 + +VITE_APP_NAME="${APP_NAME}" +VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +VITE_PUSHER_HOST="${PUSHER_HOST}" +VITE_PUSHER_PORT="${PUSHER_PORT}" +VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" +VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" +EOF + +# 2. Berechtigungen setzen +echo "🔐 Setze Berechtigungen..." +chmod -R 777 storage/ +chmod -R 777 bootstrap/cache/ +chmod 644 .env + +# 3. SQLite-Datenbank erstellen (falls nicht vorhanden) +echo "🗄️ Erstelle SQLite-Datenbank..." +touch database.sqlite +chmod 664 database.sqlite + +# 4. Composer install (falls Composer verfügbar) +if command -v composer &> /dev/null; then + echo "📦 Führe Composer install aus..." + composer install --no-dev --optimize-autoloader +else + echo "⚠️ Composer nicht gefunden. Bitte manuell ausführen: composer install" +fi + +# 5. Laravel Setup +echo "⚙️ Laravel Setup..." +php artisan config:cache +php artisan route:cache +php artisan view:cache + +# 6. Migrationen ausführen +echo "🗃️ Führe Migrationen aus..." +php artisan migrate --force + +# 7. Storage Link erstellen +echo "🔗 Erstelle Storage Link..." +php artisan storage:link + +echo "" +echo "✅ Setup abgeschlossen!" +echo "" +echo "📋 Nächste Schritte:" +echo "1. Admin-User erstellen:" +echo " php artisan tinker" +echo " use App\Models\User;" +echo " User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('ihr_passwort')]);" +echo "" +echo "2. Anwendung testen:" +echo " http://192.168.30.81" +echo "" +echo "3. Bei Problemen Debug aktivieren:" +echo " APP_DEBUG=true in .env setzen" diff --git a/setup-webspace.sh b/setup-webspace.sh new file mode 100755 index 0000000..078f975 --- /dev/null +++ b/setup-webspace.sh @@ -0,0 +1,131 @@ +#!/bin/bash + +# NeoNail DB - Vollständiges Webspace Setup +echo "🚀 NeoNail DB - Vollständiges Webspace Setup..." + +# 1. .env erstellen (falls nicht vorhanden) +echo "📝 .env Datei erstellen..." +if [ ! -f .env ]; then + cat > .env << 'EOF' +APP_NAME="NeoNail DB" +APP_ENV=production +APP_KEY=base64:+LTZYPKjkZ+O3iFTgU2sS+9bNvxxvG8Kw8JSEPiG7Rs= +APP_DEBUG=false +APP_URL=http://192.168.30.81/neonail + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=error + +# SQLite Konfiguration +DB_CONNECTION=sqlite +DB_DATABASE=database.sqlite + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +FILESYSTEM_DISK=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=mailpit +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=mt1 + +VITE_APP_NAME="${APP_NAME}" +VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +VITE_PUSHER_HOST="${PUSHER_HOST}" +VITE_PUSHER_PORT="${PUSHER_PORT}" +VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" +VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" +EOF + echo "✅ .env Datei erstellt" +else + echo "✅ .env Datei bereits vorhanden" +fi + +# 2. Storage-Verzeichnisse erstellen +echo "📁 Storage-Verzeichnisse erstellen..." +mkdir -p storage/framework/views +mkdir -p storage/framework/cache +mkdir -p storage/framework/sessions +mkdir -p storage/logs +mkdir -p bootstrap/cache + +# 3. Berechtigungen setzen +echo "🔐 Berechtigungen setzen..." +chmod -R 777 storage/ +chmod -R 777 bootstrap/cache/ +chmod 644 .env + +# 4. SQLite-Datenbank erstellen +echo "🗄️ SQLite-Datenbank erstellen..." +if [ ! -f database.sqlite ]; then + touch database.sqlite + echo "✅ SQLite-Datenbank erstellt" +else + echo "✅ SQLite-Datenbank bereits vorhanden" +fi +chmod 664 database.sqlite + +# 5. Composer installieren (falls verfügbar) +echo "📦 Composer Dependencies installieren..." +if command -v composer &> /dev/null; then + composer install --optimize-autoloader --no-dev + echo "✅ Composer Dependencies installiert" +else + echo "⚠️ Composer nicht verfügbar" +fi + +# 6. Laravel Setup +echo "🔧 Laravel Setup..." +if command -v php &> /dev/null; then + php artisan config:clear 2>/dev/null || echo "⚠️ php artisan config:clear fehlgeschlagen" + php artisan cache:clear 2>/dev/null || echo "⚠️ php artisan cache:clear fehlgeschlagen" + php artisan view:clear 2>/dev/null || echo "⚠️ php artisan view:clear fehlgeschlagen" + php artisan storage:link 2>/dev/null || echo "⚠️ php artisan storage:link fehlgeschlagen" + php artisan migrate --force 2>/dev/null || echo "⚠️ php artisan migrate fehlgeschlagen" + php artisan config:cache 2>/dev/null || echo "⚠️ php artisan config:cache fehlgeschlagen" + echo "✅ Laravel Setup abgeschlossen" +else + echo "⚠️ PHP nicht verfügbar" +fi + +echo "✅ Setup abgeschlossen!" +echo "" +echo "📋 Nächste Schritte:" +echo "1. Seite testen: http://192.168.30.81/neonail/" +echo "2. Admin-User erstellen (falls php verfügbar):" +echo " php artisan tinker" +echo " use App\Models\User;" +echo " User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('passwort')]);" +echo "" +echo "💡 Falls Probleme bestehen:" +echo "- APP_DEBUG=true in .env setzen für Debug-Informationen" +echo "- Logs prüfen: storage/logs/laravel.log" +echo "- Hosting-Provider kontaktieren" diff --git a/simple-htaccess-fix.sh b/simple-htaccess-fix.sh new file mode 100755 index 0000000..0aacbd9 --- /dev/null +++ b/simple-htaccess-fix.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +echo "📝 Einfache .htaccess Lösung" +echo "===========================" + +# 1. .htaccess im Hauptverzeichnis erstellen +echo "📝 Erstelle .htaccess im Hauptverzeichnis..." +cat > .htaccess << 'EOF' +RewriteEngine On + +# Umleitung auf public/ +RewriteRule ^$ public/ [L] +RewriteRule (.*) public/$1 [L] + +# Sicherheit + + Order allow,deny + Deny from all + + + + Order allow,deny + Deny from all + + +# PHP-Dateien erlauben + + Order allow,deny + Allow from all + +EOF + +# 2. Apache mod_rewrite aktivieren +echo "🔧 Aktiviere mod_rewrite..." +a2enmod rewrite + +# 3. Apache neu laden +echo "🔄 Lade Apache neu..." +systemctl reload apache2 + +# 4. Test +echo "🧪 Teste Anwendung..." +curl -I http://192.168.30.81 + +echo "" +echo "✅ .htaccess Lösung aktiviert!" +echo "📋 Testen Sie: http://192.168.30.81" diff --git a/simple-laravel-setup.sh b/simple-laravel-setup.sh new file mode 100755 index 0000000..e904c8a --- /dev/null +++ b/simple-laravel-setup.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +echo "🎨 NeoNail DB - Einfaches Laravel Setup" +echo "======================================" + +# 1. .env erstellen (falls nicht vorhanden) +if [ ! -f ".env" ]; then + echo "📝 Erstelle .env Datei..." + cp env-production-example.txt .env +fi + +# 2. Berechtigungen setzen +echo "🔐 Setze Berechtigungen..." +chmod -R 777 storage/ +chmod -R 777 bootstrap/cache/ +chmod 644 .env + +# 3. SQLite-Datenbank erstellen +echo "🗄️ Erstelle SQLite-Datenbank..." +touch database.sqlite +chmod 664 database.sqlite + +# 4. Nur grundlegende Laravel-Befehle (ohne problematische Provider) +echo "⚙️ Laravel Grund-Setup..." +php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen" +php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen" + +# 5. Migrationen ausführen (falls möglich) +echo "🗃️ Führe Migrationen aus..." +php artisan migrate --force 2>/dev/null || echo "⚠️ Migrationen übersprungen" + +# 6. Storage Link erstellen +echo "🔗 Erstelle Storage Link..." +php artisan storage:link 2>/dev/null || echo "⚠️ Storage Link übersprungen" + +echo "" +echo "✅ Grund-Setup abgeschlossen!" +echo "" +echo "📋 Nächste Schritte:" +echo "1. Vendor-Ordner hochladen (falls nicht vorhanden)" +echo "2. Admin-User erstellen:" +echo " php artisan tinker" +echo " use App\Models\User;" +echo " User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('ihr_passwort')]);" +echo "" +echo "3. Anwendung testen: http://192.168.30.81" diff --git a/smart-setup.sh b/smart-setup.sh new file mode 100755 index 0000000..a37779a --- /dev/null +++ b/smart-setup.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +echo "🧠 NeoNail DB - Intelligentes Setup" +echo "==================================" + +# 1. .env erstellen (falls nicht vorhanden) +if [ ! -f ".env" ]; then + echo "📝 Erstelle .env Datei..." + cp env-production-example.txt .env +else + echo "✅ .env Datei bereits vorhanden" +fi + +# 2. SQLite-Datenbank erstellen +if [ ! -f "database.sqlite" ]; then + echo "🗄️ Erstelle SQLite-Datenbank..." + touch database.sqlite +else + echo "✅ SQLite-Datenbank bereits vorhanden" +fi +chmod 664 database.sqlite + +# 3. Berechtigungen setzen +echo "🔐 Setze Berechtigungen..." +chmod -R 777 storage/ 2>/dev/null +chmod -R 777 bootstrap/cache/ 2>/dev/null +chmod 644 .env 2>/dev/null + +# 4. Storage Link prüfen +echo "🔗 Prüfe Storage Link..." +if [ ! -L "public/storage" ]; then + echo "📎 Erstelle Storage Link..." + php artisan storage:link 2>/dev/null || echo "⚠️ Storage Link übersprungen" +else + echo "✅ Storage Link bereits vorhanden" +fi + +# 5. Cache leeren (nur wenn nötig) +echo "🧹 Leere Cache..." +php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen" +php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen" + +# 6. Migrationen ausführen +echo "🗃️ Führe Migrationen aus..." +php artisan migrate --force 2>/dev/null || echo "⚠️ Migrationen übersprungen" + +echo "" +echo "✅ Intelligentes Setup abgeschlossen!" +echo "" +echo "📋 Status:" +echo "• .env: $(test -f .env && echo '✅' || echo '❌')" +echo "• database.sqlite: $(test -f database.sqlite && echo '✅' || echo '❌')" +echo "• storage link: $(test -L public/storage && echo '✅' || echo '❌')" +echo "• storage/ schreibbar: $(test -w storage && echo '✅' || echo '❌')" +echo "" +echo "📋 Nächste Schritte:" +echo "1. Admin-User erstellen:" +echo " php artisan tinker" +echo " use App\Models\User;" +echo " User::create(['name' => 'Admin', 'email' => 'admin@neonail.com', 'password' => bcrypt('ihr_passwort')]);" +echo "" +echo "2. Anwendung testen: http://192.168.30.81" diff --git a/storage/app/.gitignore b/storage/app/.gitignore new file mode 100644 index 0000000..fedb287 --- /dev/null +++ b/storage/app/.gitignore @@ -0,0 +1,4 @@ +* +!private/ +!public/ +!.gitignore diff --git a/storage/app/private/.gitignore b/storage/app/private/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/app/private/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/app/public/.gitignore b/storage/app/public/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/app/public/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/.gitignore b/storage/framework/.gitignore new file mode 100644 index 0000000..05c4471 --- /dev/null +++ b/storage/framework/.gitignore @@ -0,0 +1,9 @@ +compiled.php +config.php +down +events.scanned.php +maintenance.php +routes.php +routes.scanned.php +schedule-* +services.json diff --git a/storage/framework/cache/.gitignore b/storage/framework/cache/.gitignore new file mode 100644 index 0000000..01e4a6c --- /dev/null +++ b/storage/framework/cache/.gitignore @@ -0,0 +1,3 @@ +* +!data/ +!.gitignore diff --git a/storage/framework/cache/data/.gitignore b/storage/framework/cache/data/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/cache/data/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/sessions/.gitignore b/storage/framework/sessions/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/sessions/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/testing/.gitignore b/storage/framework/testing/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/testing/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/views/.gitignore b/storage/framework/views/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/views/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/logs/.gitignore b/storage/logs/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/test-admin-access.php b/test-admin-access.php new file mode 100644 index 0000000..0520580 --- /dev/null +++ b/test-admin-access.php @@ -0,0 +1,169 @@ + 'Dashboard', + 'admin/users' => 'Users Index', + 'admin/users/create' => 'Users Create', + 'admin/users/{user}/edit' => 'Users Edit', + 'admin/statistics' => 'Statistics', + 'nail-polishes' => 'Nail Polishes' + ]; + + foreach ($adminRoutes as $route => $description) { + if (strpos($content, $route) !== false) { + echo " ✅ Route gefunden: $route ($description)\n"; + } else { + echo " ❌ Route fehlt: $route ($description)\n"; + } + } + +} else { + echo " ❌ Routes-Datei nicht gefunden\n"; +} + +// 2. AdminController prüfen +echo "\n2. 🎛️ AdminController prüfen:\n"; +$controllerPath = 'app/Http/Controllers/AdminController.php'; +if (file_exists($controllerPath)) { + $content = file_get_contents($controllerPath); + + $methods = [ + 'dashboard' => 'Dashboard', + 'users' => 'Users Index', + 'createUser' => 'Create User', + 'storeUser' => 'Store User', + 'editUser' => 'Edit User', + 'updateUser' => 'Update User', + 'destroyUser' => 'Destroy User', + 'statistics' => 'Statistics' + ]; + + foreach ($methods as $method => $description) { + if (strpos($content, "public function $method") !== false) { + echo " ✅ Methode gefunden: $method ($description)\n"; + } else { + echo " ❌ Methode fehlt: $method ($description)\n"; + } + } + +} else { + echo " ❌ AdminController nicht gefunden\n"; +} + +// 3. AdminMiddleware prüfen +echo "\n3. 🛡️ 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"; + } + + if (strpos($content, 'abort(403') !== false) { + echo " ✅ AdminMiddleware gibt 403 bei fehlenden Rechten\n"; + } else { + echo " ❌ AdminMiddleware gibt keinen 403 Fehler\n"; + } + +} else { + echo " ❌ AdminMiddleware nicht gefunden\n"; +} + +// 4. Layout prüfen +echo "\n4. 🎨 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"; + } + + if (strpos($content, 'Admin-Badge') !== false || strpos($content, 'badge bg-primary') !== false) { + echo " ✅ Layout hat Admin-Badge\n"; + } else { + echo " ❌ Layout hat keinen Admin-Badge\n"; + } + + // Prüfe Admin-Menü Links + $adminLinks = [ + 'admin.dashboard' => 'Dashboard Link', + 'admin.users.index' => 'Users Link', + 'nail-polishes.index' => 'Nail Polishes Link', + 'admin.statistics' => 'Statistics Link' + ]; + + foreach ($adminLinks as $route => $description) { + if (strpos($content, "route(\"$route\")") !== false) { + echo " ✅ Admin-Link gefunden: $route ($description)\n"; + } else { + echo " ❌ Admin-Link fehlt: $route ($description)\n"; + } + } + +} else { + echo " ❌ Layout-Datei nicht gefunden\n"; +} + +// 5. Admin-Views prüfen +echo "\n5. 👁️ Admin-Views prüfen:\n"; +$adminViews = [ + 'resources/views/admin/dashboard.blade.php' => 'Admin Dashboard', + 'resources/views/admin/users/index.blade.php' => 'Users Index', + 'resources/views/admin/users/create.blade.php' => 'Users Create', + 'resources/views/admin/users/edit.blade.php' => 'Users Edit', + 'resources/views/nail-polishes/index.blade.php' => 'Nail Polishes Index', + 'resources/views/nail-polishes/show-users.blade.php' => 'Show Users' +]; + +foreach ($adminViews as $viewPath => $description) { + if (file_exists($viewPath)) { + echo " ✅ View gefunden: $description\n"; + } else { + echo " ❌ View fehlt: $description\n"; + } +} + +// 6. Cache-Status prüfen +echo "\n6. 🧹 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"; + } +} + +echo "\n✅ Admin-Zugriffe Test 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. Prüfen Sie ob Admin-Badge neben dem Namen steht\n"; +echo "5. Versuchen Sie direkt auf /admin/users zuzugreifen\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"; +?> diff --git a/test-admin-checkbox.php b/test-admin-checkbox.php new file mode 100644 index 0000000..3755367 --- /dev/null +++ b/test-admin-checkbox.php @@ -0,0 +1,90 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + echo "🧪 Test der Admin-Checkbox Funktionalität\n"; + echo "========================================\n\n"; + + // 1. Prüfe is_admin Spalte + $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 existiert\n"; + } else { + echo "❌ is_admin Spalte fehlt - führen Sie fix-admin-role.php aus\n"; + exit; + } + + // 2. Zeige alle User mit Admin-Status + echo "\n📋 User mit Admin-Status:\n"; + $stmt = $pdo->query("SELECT id, name, email, is_admin FROM users ORDER BY is_admin DESC, name"); + $users = $stmt->fetchAll(PDO::FETCH_ASSOC); + + if (empty($users)) { + echo "❌ Keine User gefunden\n"; + } else { + foreach ($users as $user) { + $adminStatus = $user['is_admin'] ? '👑 Admin' : '👤 User'; + $checkboxState = $user['is_admin'] ? '☑️ Aktiviert' : '☐ Deaktiviert'; + echo "- {$user['name']} ({$user['email']}) - {$adminStatus} - {$checkboxState}\n"; + } + } + + // 3. Test: Mache einen User zum Admin + echo "\n🧪 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-Checkbox Test erfolgreich!\n"; + echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/admin/users\n"; + +} catch (Exception $e) { + echo "❌ Fehler: " . $e->getMessage() . "\n"; +} +?> diff --git a/test-admin-functionality.php b/test-admin-functionality.php new file mode 100644 index 0000000..f025d2c --- /dev/null +++ b/test-admin-functionality.php @@ -0,0 +1,126 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + echo "1. 🔍 Prüfe is_admin Spalte...\n"; + + // 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; + echo " ✅ is_admin Spalte gefunden\n"; + break; + } + } + + if (!$hasAdminColumn) { + echo " ❌ is_admin Spalte fehlt - führen Sie fix-admin-role-database.php aus\n"; + exit; + } + + echo "\n2. 📋 Zeige alle User...\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); + + if (empty($users)) { + echo " ❌ Keine User gefunden\n"; + } else { + foreach ($users as $user) { + $adminStatus = $user['is_admin'] ? '👑 Admin' : '👤 User'; + echo " - {$user['name']} ({$user['email']}) - {$adminStatus}\n"; + } + } + + echo "\n3. 🧪 Test Admin-Funktionen...\n"; + + // Test: Mache einen User zum Admin + $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 Admin-Erstellung mit User: {$testUser['name']}\n"; + + // Mache User zum Admin + $stmt = $pdo->prepare("UPDATE users SET is_admin = 1 WHERE id = ?"); + $stmt->execute([$testUser['id']]); + + // 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-Erstellung erfolgreich\n"; + } else { + echo " ❌ Admin-Erstellung fehlgeschlagen\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 "\n4. 🔐 Prüfe Admin-Middleware...\n"; + + // Prüfe ob AdminMiddleware existiert + if (file_exists('app/Http/Middleware/AdminMiddleware.php')) { + echo " ✅ AdminMiddleware gefunden\n"; + + $content = file_get_contents('app/Http/Middleware/AdminMiddleware.php'); + if (strpos($content, 'isAdmin()') !== false) { + echo " ✅ AdminMiddleware verwendet isAdmin() Methode\n"; + } else { + echo " ⚠️ AdminMiddleware verwendet möglicherweise alte Email-Prüfung\n"; + } + } else { + echo " ❌ AdminMiddleware nicht gefunden\n"; + } + + echo "\n5. 👤 Prüfe User Model...\n"; + + // Prüfe ob User Model isAdmin() Methode hat + if (file_exists('app/Models/User.php')) { + echo " ✅ User Model gefunden\n"; + + $content = file_get_contents('app/Models/User.php'); + if (strpos($content, 'isAdmin()') !== false) { + echo " ✅ User Model hat isAdmin() Methode\n"; + } else { + echo " ❌ User Model hat keine isAdmin() Methode\n"; + } + + if (strpos($content, 'is_admin') !== false) { + echo " ✅ User Model hat is_admin in fillable\n"; + } else { + echo " ❌ User Model hat is_admin nicht in fillable\n"; + } + } else { + echo " ❌ User Model nicht gefunden\n"; + } + + echo "\n✅ Admin-Funktionalität Test abgeschlossen!\n"; + echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/admin/users\n"; + echo "📝 Versuchen Sie einen User zum Admin zu machen\n"; + +} catch (Exception $e) { + echo "❌ Fehler: " . $e->getMessage() . "\n"; + echo "📍 Datei: " . $e->getFile() . ":" . $e->getLine() . "\n"; +} +?> diff --git a/test-admin-user-management.sh b/test-admin-user-management.sh new file mode 100755 index 0000000..655b207 --- /dev/null +++ b/test-admin-user-management.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +echo "👑 Admin-User-Verwaltung testen" +echo "==============================" + +# 1. Laravel Cache leeren +echo "🧹 Leere Laravel Cache..." +php artisan config:clear 2>/dev/null || echo "⚠️ config:clear übersprungen" +php artisan cache:clear 2>/dev/null || echo "⚠️ cache:clear übersprungen" +php artisan route:clear 2>/dev/null || echo "⚠️ route:clear übersprungen" +php artisan view:clear 2>/dev/null || echo "⚠️ view:clear übersprungen" + +# 2. Routes prüfen +echo "🔍 Prüfe Admin-Routes..." +php artisan route:list | grep admin + +# 3. Views prüfen +echo "📁 Prüfe Admin-Views..." +if [ -f "resources/views/admin/users/index.blade.php" ]; then + echo "✅ User-Index-View gefunden" +else + echo "❌ User-Index-View fehlt" +fi + +if [ -f "resources/views/admin/users/create.blade.php" ]; then + echo "✅ User-Create-View gefunden" +else + echo "❌ User-Create-View fehlt" +fi + +if [ -f "resources/views/admin/users/edit.blade.php" ]; then + echo "✅ User-Edit-View gefunden" +else + echo "❌ User-Edit-View fehlt" +fi + +# 4. Controller prüfen +echo "🎮 Prüfe AdminController..." +if [ -f "app/Http/Controllers/AdminController.php" ]; then + echo "✅ AdminController gefunden" + grep -n "function.*User" app/Http/Controllers/AdminController.php +else + echo "❌ AdminController fehlt" +fi + +# 5. Test-URLs +echo "🧪 Teste Admin-URLs..." +echo "Admin-Dashboard: https://neonail.vogt.de.com/admin/dashboard" +echo "User-Verwaltung: https://neonail.vogt.de.com/admin/users" +echo "User erstellen: https://neonail.vogt.de.com/admin/users/create" + +# 6. Admin-User prüfen +echo "👤 Prüfe Admin-User..." +sqlite3 database.sqlite "SELECT id, name, email FROM users WHERE email LIKE '%admin%';" 2>/dev/null || echo "⚠️ Keine Admin-User gefunden" + +echo "" +echo "✅ Admin-User-Verwaltung getestet!" +echo "" +echo "📋 Admin-Funktionen:" +echo "1. User erstellen: https://neonail.vogt.de.com/admin/users/create" +echo "2. User verwalten: https://neonail.vogt.de.com/admin/users" +echo "3. User bearbeiten: Klicken Sie auf den Bearbeiten-Button" +echo "4. User löschen: Klicken Sie auf den Löschen-Button" +echo "" +echo "🔑 Admin-Login:" +echo "Email: admin@neonail.com" +echo "Passwort: admin123" diff --git a/test-all-forms-final.php b/test-all-forms-final.php new file mode 100644 index 0000000..b6f971d --- /dev/null +++ b/test-all-forms-final.php @@ -0,0 +1,50 @@ + 'Login-Formular', + 'resources/views/user-nail-polishes/create.blade.php' => 'Create Nail Polish', + 'resources/views/user-nail-polishes/index.blade.php' => 'Remove Nail Polish', + 'resources/views/nail-polishes/index.blade.php' => 'Admin Delete Nail Polish', + 'resources/views/admin/users/create.blade.php' => 'Admin Create User', + 'resources/views/admin/users/edit.blade.php' => 'Admin Edit User', + 'resources/views/admin/users/index.blade.php' => 'Admin Delete User', + 'resources/views/layouts/app.blade.php' => 'Logout-Formular' +]; + +$allFixed = true; + +foreach ($forms as $file => $description) { + if (file_exists($file)) { + $content = file_get_contents($file); + if (strpos($content, 'action="https://neonail.vogt.de.com') !== false) { + echo " ✅ $description: HTTPS-URL gefunden\n"; + } else { + echo " ❌ $description: Keine HTTPS-URL gefunden\n"; + $allFixed = false; + + // Zeige die aktuelle action + if (preg_match('/action="([^"]+)"/', $content, $matches)) { + echo " Aktuelle action: " . $matches[1] . "\n"; + } + } + } else { + echo " ❌ $description: Datei nicht gefunden\n"; + $allFixed = false; + } +} + +echo "\n"; +if ($allFixed) { + echo "🎉 ALLE Formulare sind jetzt mit HTTPS-URLs konfiguriert!\n"; + echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com\n"; + echo "📝 Safari-Sicherheitswarnungen sollten komplett verschwunden sein.\n"; +} else { + echo "⚠️ Einige Formulare müssen noch korrigiert werden.\n"; + echo "🔧 Führen Sie das Fix-Script erneut aus.\n"; +} + +echo "\n✅ Finaler Formular-Test abgeschlossen!\n"; +?> diff --git a/test-all-forms.php b/test-all-forms.php new file mode 100644 index 0000000..6ff3c01 --- /dev/null +++ b/test-all-forms.php @@ -0,0 +1,31 @@ + '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"; +?> diff --git a/test-apache-status.php b/test-apache-status.php new file mode 100644 index 0000000..4261c17 --- /dev/null +++ b/test-apache-status.php @@ -0,0 +1,87 @@ + [ + 'timeout' => 5, + 'method' => 'GET' + ] +]); + +$result = @file_get_contents('http://localhost/', false, $context); +if ($result !== false) { + echo " ✅ HTTP-Request erfolgreich\n"; +} else { + echo " ❌ HTTP-Request fehlgeschlagen\n"; + $error = error_get_last(); + if ($error) { + echo " Fehler: " . $error['message'] . "\n"; + } +} + +echo "\n✅ Apache-Status Test abgeschlossen!\n"; +?> diff --git a/test-forms-fixed.php b/test-forms-fixed.php new file mode 100644 index 0000000..17f5fd7 --- /dev/null +++ b/test-forms-fixed.php @@ -0,0 +1,49 @@ + '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' +]; + +$allFixed = true; + +foreach ($forms as $file => $description) { + if (file_exists($file)) { + $content = file_get_contents($file); + if (strpos($content, 'action="https://neonail.vogt.de.com') !== false) { + echo " ✅ $description: HTTPS-URL gefunden\n"; + } else { + echo " ❌ $description: Keine HTTPS-URL gefunden\n"; + $allFixed = false; + + // Zeige die aktuelle action + if (preg_match('/action="([^"]+)"/', $content, $matches)) { + echo " Aktuelle action: " . $matches[1] . "\n"; + } + } + } else { + echo " ❌ $description: Datei nicht gefunden\n"; + $allFixed = false; + } +} + +echo "\n"; +if ($allFixed) { + echo "🎉 Alle Formulare sind jetzt mit HTTPS-URLs konfiguriert!\n"; + echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com\n"; + echo "📝 Safari-Sicherheitswarnungen sollten verschwunden sein.\n"; +} else { + echo "⚠️ Einige Formulare müssen noch korrigiert werden.\n"; + echo "🔧 Führen Sie das Fix-Script erneut aus.\n"; +} + +echo "\n✅ Formular-Test abgeschlossen!\n"; +?> diff --git a/test-https-security.php b/test-https-security.php new file mode 100644 index 0000000..72e2bad --- /dev/null +++ b/test-https-security.php @@ -0,0 +1,59 @@ + true") !== false) { + echo " ✅ Session secure: true\n"; + } else { + echo " ❌ Session secure: false\n"; + } + if (strpos($content, "'http_only' => true") !== false) { + echo " ✅ Session http_only: true\n"; + } else { + echo " ❌ Session http_only: false\n"; + } +} + +// 3. Prüfe CSRF-Konfiguration +echo "\n3. CSRF-Konfiguration:\n"; +if (file_exists('config/csrf.php')) { + $content = file_get_contents('config/csrf.php'); + if (strpos($content, "'secure' => true") !== false) { + echo " ✅ CSRF secure: true\n"; + } else { + echo " ❌ CSRF secure: false\n"; + } +} + +// 4. Prüfe .htaccess +echo "\n4. .htaccess HTTPS-Headers:\n"; +if (file_exists('public/.htaccess')) { + $content = file_get_contents('public/.htaccess'); + if (strpos($content, 'Strict-Transport-Security') !== false) { + echo " ✅ HSTS Header vorhanden\n"; + } else { + echo " ❌ HSTS Header fehlt\n"; + } + if (strpos($content, 'upgrade-insecure-requests') !== false) { + echo " ✅ CSP upgrade-insecure-requests vorhanden\n"; + } else { + echo " ❌ CSP upgrade-insecure-requests fehlt\n"; + } +} + +echo "\n✅ HTTPS-Sicherheit Test abgeschlossen!\n"; +echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/admin/users\n"; +?> diff --git a/test-mail.php b/test-mail.php new file mode 100644 index 0000000..6c75c4a --- /dev/null +++ b/test-mail.php @@ -0,0 +1,233 @@ + 'Mailer', + 'MAIL_HOST' => 'Host', + 'MAIL_PORT' => 'Port', + 'MAIL_USERNAME' => 'Username', + 'MAIL_PASSWORD' => 'Password', + 'MAIL_ENCRYPTION' => 'Encryption', + 'MAIL_FROM_ADDRESS' => 'From Address', + 'MAIL_FROM_NAME' => 'From Name' + ]; + + foreach ($mailSettings as $setting => $description) { + if (preg_match("/$setting=(.*)/", $envContent, $matches)) { + $value = trim($matches[1]); + if ($setting === 'MAIL_PASSWORD') { + $value = str_repeat('*', min(strlen($value), 4)) . '...'; + } + echo " ✅ $description: $value\n"; + } else { + echo " ❌ $description: Nicht gesetzt\n"; + } + } + +} else { + echo " ❌ .env Datei nicht gefunden\n"; +} + +// 2. Laravel Mail-Konfiguration testen +echo "\n2. 🐘 Laravel Mail-Konfiguration testen:\n"; +try { + require_once 'vendor/autoload.php'; + + // Laravel Bootstrap + $app = require_once 'bootstrap/app.php'; + $app->make('Illuminate\Contracts\Console\Kernel')->bootstrap(); + + // Mail-Konfiguration abrufen + $mailConfig = config('mail'); + + echo " 📋 Mail-Konfiguration:\n"; + echo " - Default: " . ($mailConfig['default'] ?? 'nicht gesetzt') . "\n"; + echo " - Mailers: " . implode(', ', array_keys($mailConfig['mailers'] ?? [])) . "\n"; + + if (isset($mailConfig['mailers']['smtp'])) { + $smtpConfig = $mailConfig['mailers']['smtp']; + echo " - SMTP Host: " . ($smtpConfig['host'] ?? 'nicht gesetzt') . "\n"; + echo " - SMTP Port: " . ($smtpConfig['port'] ?? 'nicht gesetzt') . "\n"; + echo " - SMTP Encryption: " . ($smtpConfig['encryption'] ?? 'nicht gesetzt') . "\n"; + echo " - SMTP Username: " . ($smtpConfig['username'] ?? 'nicht gesetzt') . "\n"; + echo " - SMTP Password: " . (isset($smtpConfig['password']) ? '***' : 'nicht gesetzt') . "\n"; + } + +} catch (Exception $e) { + echo " ❌ Fehler beim Laden der Mail-Konfiguration: " . $e->getMessage() . "\n"; +} + +// 3. Test-Mail senden +echo "\n3. 📤 Test-Mail senden...\n"; +try { + // Test-E-Mail-Adresse (kann angepasst werden) + $testEmail = 'test@example.com'; + + echo " 📧 Sende Test-Mail an: $testEmail\n"; + + // Mail senden + $result = \Illuminate\Support\Facades\Mail::raw('Dies ist eine Test-Mail von der NeoNail Datenbank. + +Zeitstempel: ' . now() . ' +Server: ' . $_SERVER['SERVER_NAME'] ?? 'Unbekannt' . ' + +Diese E-Mail wurde automatisch generiert, um die E-Mail-Konfiguration zu testen. + +Viele Grüße, +NeoNail DB System', function($message) use ($testEmail) { + $message->to($testEmail) + ->subject('Test-Mail: NeoNail DB E-Mail-Konfiguration') + ->from(config('mail.from.address'), config('mail.from.name')); + }); + + echo " ✅ Test-Mail erfolgreich gesendet!\n"; + +} catch (Exception $e) { + echo " ❌ Fehler beim Senden der Test-Mail: " . $e->getMessage() . "\n"; + + // Detaillierte Fehleranalyse + echo " 🔍 Fehleranalyse:\n"; + if (strpos($e->getMessage(), 'Connection refused') !== false) { + echo " - Problem: Verbindung zum SMTP-Server verweigert\n"; + echo " - Lösung: Prüfen Sie MAIL_HOST und MAIL_PORT\n"; + } elseif (strpos($e->getMessage(), 'Authentication failed') !== false) { + echo " - Problem: Authentifizierung fehlgeschlagen\n"; + echo " - Lösung: Prüfen Sie MAIL_USERNAME und MAIL_PASSWORD\n"; + } elseif (strpos($e->getMessage(), 'SSL') !== false) { + echo " - Problem: SSL/TLS Verbindungsproblem\n"; + echo " - Lösung: Prüfen Sie MAIL_ENCRYPTION (SSL/TLS)\n"; + } else { + echo " - Unbekannter Fehler: " . $e->getMessage() . "\n"; + } +} + +// 4. Alternative Test-Mail mit SwiftMailer +echo "\n4. 📤 Alternative Test-Mail (SwiftMailer)...\n"; +try { + // SwiftMailer direkt testen + $transport = new \Swift_SmtpTransport( + config('mail.mailers.smtp.host'), + config('mail.mailers.smtp.port'), + config('mail.mailers.smtp.encryption') + ); + + $transport->setUsername(config('mail.mailers.smtp.username')); + $transport->setPassword(config('mail.mailers.smtp.password')); + + $mailer = new \Swift_Mailer($transport); + + $message = new \Swift_Message('SwiftMailer Test: NeoNail DB'); + $message->setFrom([config('mail.from.address') => config('mail.from.name')]); + $message->setTo(['test@example.com' => 'Test User']); + $message->setBody('Dies ist eine SwiftMailer Test-Mail von der NeoNail Datenbank. + +Zeitstempel: ' . now() . ' + +Viele Grüße, +NeoNail DB System'); + + $result = $mailer->send($message); + + if ($result) { + echo " ✅ SwiftMailer Test-Mail erfolgreich gesendet!\n"; + } else { + echo " ❌ SwiftMailer Test-Mail fehlgeschlagen\n"; + } + +} catch (Exception $e) { + echo " ❌ SwiftMailer Fehler: " . $e->getMessage() . "\n"; +} + +// 5. E-Mail-Template erstellen +echo "\n5. 📝 E-Mail-Template erstellen...\n"; +$emailTemplatePath = 'resources/views/emails/test.blade.php'; +$emailTemplateContent = ' + + + + NeoNail DB Test-Mail + + + +
+
+

🎨 NeoNail DB

+

E-Mail-Konfiguration Test

+
+ +
+

✅ E-Mail-Konfiguration erfolgreich!

+ +

Hallo,

+ +

dies ist eine Test-Mail von der NeoNail Datenbank. Die E-Mail-Konfiguration funktioniert korrekt!

+ +

📋 Test-Details:

+
    +
  • Zeitstempel: {{ now() }}
  • +
  • Server: {{ $_SERVER["SERVER_NAME"] ?? "Unbekannt" }}
  • +
  • Mailer: {{ config("mail.default") }}
  • +
  • Host: {{ config("mail.mailers.smtp.host") }}
  • +
+ +

Die E-Mail-Funktionalität ist jetzt bereit für Benachrichtigungen und Passwort-Reset.

+
+ + +
+ +'; + +// Template-Verzeichnis erstellen +$emailDir = 'resources/views/emails'; +if (!is_dir($emailDir)) { + mkdir($emailDir, 0755, true); + echo " ✅ E-Mail-Verzeichnis erstellt: $emailDir\n"; +} + +file_put_contents($emailTemplatePath, $emailTemplateContent); +echo " ✅ E-Mail-Template erstellt: $emailTemplatePath\n"; + +// 6. Template-Mail senden +echo "\n6. 📤 Template-Mail senden...\n"; +try { + $result = \Illuminate\Support\Facades\Mail::send('emails.test', [], function($message) { + $message->to('test@example.com') + ->subject('Template Test: NeoNail DB') + ->from(config('mail.from.address'), config('mail.from.name')); + }); + + echo " ✅ Template-Mail erfolgreich gesendet!\n"; + +} catch (Exception $e) { + echo " ❌ Template-Mail Fehler: " . $e->getMessage() . "\n"; +} + +echo "\n✅ E-Mail-Test abgeschlossen!\n"; +echo "📋 Nächste Schritte:\n"; +echo "1. Prüfen Sie Ihr E-Mail-Postfach (test@example.com)\n"; +echo "2. Falls keine E-Mail ankommt, prüfen Sie Spam-Ordner\n"; +echo "3. Falls Fehler auftreten, prüfen Sie die SMTP-Einstellungen\n"; +echo "4. Für echte Tests, ändern Sie die E-Mail-Adresse im Script\n"; +echo "\n🔗 E-Mail-Funktionen sind jetzt verfügbar für:\n"; +echo "- Passwort-Reset\n"; +echo "- Benutzer-Benachrichtigungen\n"; +echo "- Admin-Benachrichtigungen\n"; +?> diff --git a/test-remove-fix.php b/test-remove-fix.php new file mode 100644 index 0000000..421d667 --- /dev/null +++ b/test-remove-fix.php @@ -0,0 +1,99 @@ +make('Illuminate\Contracts\Console\Kernel')->bootstrap(); + + $router = $app->make('router'); + $routes = $router->getRoutes(); + + $foundRemoveRoute = false; + + foreach ($routes as $route) { + if (strpos($route->uri(), 'remove-from-collection') !== false) { + echo " ✅ Route 'remove-from-collection' gefunden\n"; + echo " - URI: " . $route->uri() . "\n"; + echo " - Method: " . implode('|', $route->methods()) . "\n"; + echo " - Name: " . $route->getName() . "\n"; + $foundRemoveRoute = true; + } + } + + if (!$foundRemoveRoute) { + echo " ❌ Route 'remove-from-collection' nicht gefunden\n"; + } + +} catch (Exception $e) { + echo " ❌ Laravel-Fehler: " . $e->getMessage() . "\n"; +} + +// 2. Prüfe Form-Action in Index-View +echo "\n2. Form-Action in Index-View prüfen:\n"; +$indexViewPath = 'resources/views/user-nail-polishes/index.blade.php'; +if (file_exists($indexViewPath)) { + $content = file_get_contents($indexViewPath); + if (strpos($content, 'action="/remove-from-collection/') !== false) { + echo " ✅ Form-Action korrekt: /remove-from-collection/{id}\n"; + } else { + echo " ❌ Form-Action nicht korrekt\n"; + echo " Gefunden: " . preg_match('/action="([^"]+)"/', $content, $matches) ? $matches[1] : 'nichts'; + } + + // Prüfe @method('DELETE') + if (strpos($content, '@method(\'DELETE\')') !== false) { + echo " ⚠️ @method('DELETE') noch vorhanden - sollte entfernt werden\n"; + } else { + echo " ✅ @method('DELETE') entfernt\n"; + } +} else { + echo " ❌ Index-View nicht gefunden\n"; +} + +// 3. Prüfe CSRF-Token +echo "\n3. CSRF-Token prüfen:\n"; +if (strpos($content, '@csrf') !== false) { + echo " ✅ CSRF-Token in Form vorhanden\n"; +} else { + echo " ❌ CSRF-Token fehlt\n"; +} + +// 4. Prüfe Method +echo "\n4. HTTP-Method prüfen:\n"; +if (strpos($content, 'method="POST"') !== false) { + echo " ✅ HTTP-Method: POST\n"; +} else { + echo " ❌ HTTP-Method nicht POST\n"; +} + +// 5. Prüfe Datenbank +echo "\n5. Datenbank prüfen:\n"; +try { + $pdo = new PDO('sqlite:database.sqlite'); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // Prüfe nail_polishes Tabelle + $stmt = $pdo->query("SELECT COUNT(*) FROM nail_polishes"); + $polishCount = $stmt->fetchColumn(); + echo " - Lacke in Datenbank: $polishCount\n"; + + // Prüfe user_nail_polishes Tabelle + $stmt = $pdo->query("SELECT COUNT(*) FROM user_nail_polishes"); + $userPolishCount = $stmt->fetchColumn(); + echo " - User-Lack-Verbindungen: $userPolishCount\n"; + +} catch (Exception $e) { + echo " ❌ Datenbankfehler: " . $e->getMessage() . "\n"; +} + +echo "\n✅ Remove-Test abgeschlossen!\n"; +echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/my-collection\n"; +echo "📝 Versuchen Sie einen Lack aus Ihrer Sammlung zu entfernen\n"; +?> diff --git a/test-route-fix.php b/test-route-fix.php new file mode 100644 index 0000000..45f6fa0 --- /dev/null +++ b/test-route-fix.php @@ -0,0 +1,83 @@ +make('Illuminate\Contracts\Console\Kernel')->bootstrap(); + + $router = $app->make('router'); + $routes = $router->getRoutes(); + + $foundStoreRoute = false; + $foundCreateRoute = 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"; + $foundStoreRoute = true; + } + + if ($route->uri() === 'create-nail-polish') { + echo " ✅ Route '/create-nail-polish' gefunden\n"; + echo " - Method: " . implode('|', $route->methods()) . "\n"; + echo " - Name: " . $route->getName() . "\n"; + $foundCreateRoute = true; + } + } + + if (!$foundStoreRoute) { + echo " ❌ Route 'user-nail-polishes.store' nicht gefunden\n"; + } + + if (!$foundCreateRoute) { + echo " ❌ Route '/create-nail-polish' nicht gefunden\n"; + } + +} catch (Exception $e) { + echo " ❌ Laravel-Fehler: " . $e->getMessage() . "\n"; +} + +// 2. Prüfe Form-Action +echo "\n2. Form-Action prüfen:\n"; +$createViewPath = 'resources/views/user-nail-polishes/create.blade.php'; +if (file_exists($createViewPath)) { + $content = file_get_contents($createViewPath); + if (strpos($content, 'action="/create-nail-polish"') !== false) { + echo " ✅ Form-Action korrekt: /create-nail-polish\n"; + } else { + echo " ❌ Form-Action nicht korrekt\n"; + echo " Gefunden: " . preg_match('/action="([^"]+)"/', $content, $matches) ? $matches[1] : 'nichts'; + } +} else { + echo " ❌ Create-View nicht gefunden\n"; +} + +// 3. Prüfe CSRF-Token +echo "\n3. CSRF-Token prüfen:\n"; +if (strpos($content, '@csrf') !== false) { + echo " ✅ CSRF-Token in Form vorhanden\n"; +} else { + echo " ❌ CSRF-Token fehlt\n"; +} + +// 4. Prüfe Method +echo "\n4. HTTP-Method prüfen:\n"; +if (strpos($content, 'method="POST"') !== false) { + echo " ✅ HTTP-Method: POST\n"; +} else { + echo " ❌ HTTP-Method nicht POST\n"; +} + +echo "\n✅ Route-Test abgeschlossen!\n"; +echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/create-nail-polish\n"; +echo "📝 Versuchen Sie einen neuen Lack zu erstellen\n"; +?> diff --git a/test-upload-limits.php b/test-upload-limits.php new file mode 100644 index 0000000..c0ef60e --- /dev/null +++ b/test-upload-limits.php @@ -0,0 +1,63 @@ + ini_get('upload_max_filesize'), + 'post_max_size' => ini_get('post_max_size'), + 'max_file_uploads' => ini_get('max_file_uploads'), + 'memory_limit' => ini_get('memory_limit') +]; + +foreach ($limits as $setting => $value) { + echo " - $setting: $value\n"; +} + +// 2. Laravel Validierungsregeln prüfen +echo "\n2. Laravel Validierungsregeln:\n"; +$controllerPath = 'app/Http/Controllers/UserNailPolishController.php'; +if (file_exists($controllerPath)) { + $content = file_get_contents($controllerPath); + if (preg_match('/image.*max:(\d+)/', $content, $matches)) { + $maxKB = $matches[1]; + $maxMB = $maxKB / 1024; + echo " - Bild-Upload-Limit: {$maxKB}KB ({$maxMB}MB)\n"; + + if ($maxMB >= 10) { + echo " ✅ Upload-Limit ist ausreichend (>= 10MB)\n"; + } else { + echo " ❌ Upload-Limit ist zu klein (< 10MB)\n"; + } + } else { + echo " ❌ Keine Bild-Upload-Validierung gefunden\n"; + } +} else { + echo " ❌ Controller nicht gefunden\n"; +} + +// 3. View-Text prüfen +echo "\n3. View-Text:\n"; +$viewPath = 'resources/views/user-nail-polishes/create.blade.php'; +if (file_exists($viewPath)) { + $content = file_get_contents($viewPath); + if (preg_match('/Maximale Größe: (\d+MB)/', $content, $matches)) { + echo " - Angezeigte Größe: {$matches[1]}\n"; + + if ($matches[1] === '10MB') { + echo " ✅ View zeigt korrekte Größe an\n"; + } else { + echo " ❌ View zeigt falsche Größe an\n"; + } + } else { + echo " ❌ Keine Größenangabe in View gefunden\n"; + } +} else { + echo " ❌ View nicht gefunden\n"; +} + +echo "\n✅ Upload-Limits Test abgeschlossen!\n"; +echo "🔗 Testen Sie jetzt: https://neonail.vogt.de.com/create-nail-polish\n"; +?> diff --git a/test.php b/test.php new file mode 100755 index 0000000..fa1488e --- /dev/null +++ b/test.php @@ -0,0 +1,109 @@ +PHP-Test"; + +// PHP-Version prüfen +echo "

PHP-Version:

"; +echo "PHP Version: " . phpversion() . "
"; + +// Erforderliche Extensions prüfen +echo "

Erforderliche Extensions:

"; +$required_extensions = [ + 'pdo', + 'pdo_sqlite', + 'sqlite3', + 'bcmath', + 'ctype', + 'json', + 'mbstring', + 'openssl', + 'tokenizer', + 'xml', + 'gd', + 'fileinfo' +]; + +foreach ($required_extensions as $ext) { + $status = extension_loaded($ext) ? "✅" : "❌"; + echo "$status $ext
"; +} + +// Verzeichnis-Struktur prüfen +echo "

Verzeichnis-Struktur:

"; +$required_dirs = [ + 'public', + 'app', + 'bootstrap', + 'config', + 'database', + 'resources', + 'routes', + 'storage' +]; + +foreach ($required_dirs as $dir) { + $status = is_dir($dir) ? "✅" : "❌"; + echo "$status $dir/
"; +} + +// .env Datei prüfen +echo "

.env Datei:

"; +if (file_exists('.env')) { + echo "✅ .env Datei gefunden
"; + $env_content = file_get_contents('.env'); + if (strpos($env_content, 'DB_CONNECTION=sqlite') !== false) { + echo "✅ SQLite konfiguriert
"; + } else { + echo "❌ SQLite nicht konfiguriert
"; + } +} else { + echo "❌ .env Datei nicht gefunden
"; +} + +// SQLite-Datenbank prüfen +echo "

SQLite-Datenbank:

"; +if (file_exists('database.sqlite')) { + echo "✅ database.sqlite gefunden
"; + echo "Größe: " . filesize('database.sqlite') . " Bytes
"; +} else { + echo "❌ database.sqlite nicht gefunden
"; +} + +// Berechtigungen prüfen +echo "

Berechtigungen:

"; +$writable_dirs = [ + 'storage', + 'bootstrap/cache' +]; + +foreach ($writable_dirs as $dir) { + if (is_dir($dir)) { + $status = is_writable($dir) ? "✅" : "❌"; + echo "$status $dir/ schreibbar
"; + } +} + +// Laravel index.php prüfen +echo "

Laravel index.php:

"; +if (file_exists('public/index.php')) { + echo "✅ public/index.php gefunden
"; +} else { + echo "❌ public/index.php nicht gefunden
"; +} + +// Composer autoload prüfen +echo "

Composer autoload:

"; +if (file_exists('vendor/autoload.php')) { + echo "✅ vendor/autoload.php gefunden
"; +} else { + echo "❌ vendor/autoload.php nicht gefunden
"; + echo "Hinweis: Composer install ausführen
"; +} + +echo "
"; +echo "

Nächste Schritte:

"; +echo "1. Falls Extensions fehlen: Hosting-Provider kontaktieren
"; +echo "2. Falls .env fehlt: env-sqlite-example.txt zu .env kopieren
"; +echo "3. Falls vendor/ fehlt: composer install ausführen
"; +echo "4. Falls Berechtigungen falsch: chmod 755 storage/ bootstrap/cache/
"; +?> diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php new file mode 100755 index 0000000..8364a84 --- /dev/null +++ b/tests/Feature/ExampleTest.php @@ -0,0 +1,19 @@ +get('/'); + + $response->assertStatus(200); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100755 index 0000000..fe1ffc2 --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,10 @@ +assertTrue(true); + } +} diff --git a/upload-vendor-instructions.md b/upload-vendor-instructions.md new file mode 100755 index 0000000..28bca42 --- /dev/null +++ b/upload-vendor-instructions.md @@ -0,0 +1,40 @@ +# 📦 Vendor-Ordner hochladen (Alternative zu Composer) + +## 🎯 Einfachste Lösung + +Da Composer auf dem Webspace nicht verfügbar ist, können Sie den `vendor/` Ordner von Ihrem lokalen System hochladen. + +## 📋 Schritte: + +### 1. Lokal Composer ausführen +```bash +# In Ihrem lokalen Projekt-Verzeichnis +composer install --no-dev --optimize-autoloader +``` + +### 2. Vendor-Ordner hochladen +- Laden Sie den kompletten `vendor/` Ordner auf den Webspace hoch +- Ziel: `/var/www/html/vendor/` + +### 3. Berechtigungen setzen +```bash +chmod -R 755 vendor/ +``` + +### 4. Laravel Setup +```bash +php artisan config:cache +php artisan route:cache +php artisan view:cache +php artisan migrate --force +``` + +## ✅ Vorteile: +- Keine Composer-Installation nötig +- Schnell und einfach +- Funktioniert auf allen Webspaces + +## ⚠️ Hinweise: +- Stellen Sie sicher, dass Sie `--no-dev` verwenden +- Der vendor-Ordner kann groß sein (ca. 50-100 MB) +- Verwenden Sie FTP/SFTP für den Upload diff --git a/vite.config.js b/vite.config.js new file mode 100755 index 0000000..29fbfe9 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,13 @@ +import { defineConfig } from 'vite'; +import laravel from 'laravel-vite-plugin'; +import tailwindcss from '@tailwindcss/vite'; + +export default defineConfig({ + plugins: [ + laravel({ + input: ['resources/css/app.css', 'resources/js/app.js'], + refresh: true, + }), + tailwindcss(), + ], +});