fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
61
scripts/build/build.sh
Executable file
61
scripts/build/build.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "🚀 Starting Docker build with network resilience..."
|
||||
|
||||
# Prüfe Netzwerk-Konnektivität
|
||||
echo "🔍 Checking network connectivity..."
|
||||
if ! curl -s --connect-timeout 5 https://registry-1.docker.io/v2/ > /dev/null; then
|
||||
echo "⚠️ Docker Hub nicht erreichbar - verwende lokale Images"
|
||||
export DOCKER_BUILDKIT=0
|
||||
export COMPOSE_DOCKER_CLI_BUILD=0
|
||||
fi
|
||||
|
||||
# DNS-Cache leeren
|
||||
echo "🔄 Flushing DNS cache..."
|
||||
sudo systemctl flush-dns 2>/dev/null || sudo systemd-resolve --flush-caches 2>/dev/null || true
|
||||
|
||||
# Docker daemon neu starten falls nötig
|
||||
if ! docker info > /dev/null 2>&1; then
|
||||
echo "🔄 Restarting Docker daemon..."
|
||||
sudo systemctl restart docker
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
# Versuche erst mit Pull
|
||||
echo "📥 Attempting to pull base images..."
|
||||
if timeout 60 docker-compose pull --ignore-pull-failures; then
|
||||
echo "✅ Images pulled successfully"
|
||||
else
|
||||
echo "⚠️ Pull failed - building with local images only"
|
||||
fi
|
||||
|
||||
# Build mit verschiedenen Strategien
|
||||
echo "🏗️ Building containers..."
|
||||
|
||||
# Strategie 1: Normaler Build
|
||||
if timeout 300 docker-compose build --parallel; then
|
||||
echo "✅ Build completed successfully!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "⚠️ Normal build failed - trying fallback strategies..."
|
||||
|
||||
# Strategie 2: Ohne Cache und Pull
|
||||
if timeout 300 docker-compose build --no-cache --pull=false; then
|
||||
echo "✅ Build completed with fallback strategy!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Strategie 3: Sequenzieller Build
|
||||
echo "🔄 Trying sequential build..."
|
||||
for service in web php db redis queue-worker; do
|
||||
echo "Building $service..."
|
||||
if timeout 300 docker-compose build --no-cache --pull=false "$service"; then
|
||||
echo "✅ $service built successfully"
|
||||
else
|
||||
echo "❌ Failed to build $service"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "🏁 Build process completed"
|
||||
29
scripts/debug/chat.html
Normal file
29
scripts/debug/chat.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WebSocket Chat Demo</title>
|
||||
<link rel="stylesheet" href="/css/chat.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>WebSocket Chat Demo</h1>
|
||||
|
||||
<div class="connection-status status-disconnected" id="status">
|
||||
Nicht verbunden
|
||||
</div>
|
||||
|
||||
<div class="chat-container">
|
||||
<div class="chat-messages" id="chatMessages">
|
||||
<div class="message system">Willkommen im Chat! Verbindung wird hergestellt...</div>
|
||||
</div>
|
||||
|
||||
<div class="chat-input">
|
||||
<input type="text" id="messageInput" placeholder="Nachricht eingeben..." disabled>
|
||||
<button id="sendButton" disabled>Senden</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/chat.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
27
scripts/debug/debug-component-registry.php
Normal file
27
scripts/debug/debug-component-registry.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
require '/var/www/html/vendor/autoload.php';
|
||||
require '/var/www/html/public/index.php';
|
||||
|
||||
// Get container from global scope
|
||||
$container = $GLOBALS['container'] ?? null;
|
||||
if (!$container) {
|
||||
echo "ERROR: Container not available\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
$discoveryRegistry = $container->get('App\Framework\Discovery\Results\DiscoveryRegistry');
|
||||
$liveComponents = $discoveryRegistry->attributes()->get('App\Framework\LiveComponents\Attributes\LiveComponent');
|
||||
|
||||
echo "Found " . count($liveComponents) . " LiveComponent(s)\n\n";
|
||||
|
||||
foreach ($liveComponents as $discovered) {
|
||||
$attr = $discovered->createAttributeInstance();
|
||||
if ($attr) {
|
||||
echo "✓ " . $attr->name . " => " . $discovered->className->toString() . "\n";
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
echo "ERROR: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
}
|
||||
@@ -7,7 +7,7 @@ require_once __DIR__ . '/vendor/autoload.php';
|
||||
use App\Framework\Console\ConsoleCommandMapper;
|
||||
use App\Framework\Console\ConsoleCommand;
|
||||
use App\Framework\Console\DemoCommand;
|
||||
use App\Framework\Reflection\WrappedReflectionMethod;
|
||||
use App\Framework\ReflectionLegacy\WrappedReflectionMethod;
|
||||
|
||||
echo "Testing ConsoleCommandMapper..." . PHP_EOL;
|
||||
|
||||
|
||||
282
scripts/debug/qr-test-all.html
Normal file
282
scripts/debug/qr-test-all.html
Normal file
@@ -0,0 +1,282 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>QR Code Test - Alle Versionen</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: system-ui, sans-serif;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
border-bottom: 3px solid #007bff;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.status {
|
||||
background: #fff3cd;
|
||||
border-left: 4px solid #ffc107;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||
gap: 20px;
|
||||
margin: 30px 0;
|
||||
}
|
||||
.card {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
.card h3 {
|
||||
margin-top: 0;
|
||||
color: #007bff;
|
||||
font-size: 16px;
|
||||
}
|
||||
.qr-container {
|
||||
background: #fff;
|
||||
border: 2px solid #dee2e6;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 300px;
|
||||
}
|
||||
.qr-container img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
.info {
|
||||
margin-top: 15px;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
}
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.label {
|
||||
font-weight: 600;
|
||||
}
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
border-radius: 3px;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.badge-primary { background: #007bff; color: white; }
|
||||
.badge-success { background: #28a745; color: white; }
|
||||
.badge-warning { background: #ffc107; color: black; }
|
||||
.section {
|
||||
margin: 40px 0;
|
||||
}
|
||||
.section-title {
|
||||
font-size: 20px;
|
||||
color: #495057;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 2px solid #dee2e6;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🔍 QR Code Scanner Test - Alle Versionen</h1>
|
||||
|
||||
<div class="status">
|
||||
<strong>⚠️ Test-Anleitung:</strong><br>
|
||||
Scanne jeden QR-Code einzeln mit deiner Smartphone-Kamera oder QR-Scanner-App.
|
||||
Notiere, welche (wenn überhaupt) erfolgreich gescannt werden können.
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">🎯 Nach Format Info Fix (Neueste)</div>
|
||||
<div class="grid">
|
||||
<div class="card">
|
||||
<h3>Perfect Pixel PNG</h3>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-perfect-pixel.png" alt="Perfect Pixel QR">
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="info-item">
|
||||
<span class="label">Data:</span>
|
||||
<span>HELLO WORLD</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Size:</span>
|
||||
<span>580x580px</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Module Size:</span>
|
||||
<span>20px</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Mask:</span>
|
||||
<span class="badge badge-primary">Pattern 2</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Features:</span>
|
||||
<span class="badge badge-success">No Compression</span>
|
||||
<span class="badge badge-success">Format Info Fixed</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Fixed - HELLO WORLD</h3>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-fixed-hello.png" alt="Fixed Hello">
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="info-item">
|
||||
<span class="label">Data:</span>
|
||||
<span>HELLO WORLD</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Size:</span>
|
||||
<span>580x580px</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Features:</span>
|
||||
<span class="badge badge-success">Format Info NOT Masked</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Fixed - GitHub URL</h3>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-fixed-github.png" alt="Fixed GitHub">
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="info-item">
|
||||
<span class="label">Data:</span>
|
||||
<span>https://github.com</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Size:</span>
|
||||
<span>580x580px</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Features:</span>
|
||||
<span class="badge badge-success">Format Info NOT Masked</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">📏 Größenvariationen</div>
|
||||
<div class="grid">
|
||||
<div class="card">
|
||||
<h3>Ultra Large (20px modules)</h3>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-ultra-large.png" alt="Ultra Large">
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="info-item">
|
||||
<span class="label">Data:</span>
|
||||
<span>HELLO WORLD</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Size:</span>
|
||||
<span>580x580px</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Extra Quiet Zone (8 modules)</h3>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-extra-quiet.png" alt="Extra Quiet">
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="info-item">
|
||||
<span class="label">Data:</span>
|
||||
<span>HELLO WORLD</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Size:</span>
|
||||
<span>740x740px</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Quiet Zone:</span>
|
||||
<span class="badge badge-warning">8 Modules (Doppelt)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Standard (10px modules)</h3>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-hello-world.png" alt="Standard Hello">
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="info-item">
|
||||
<span class="label">Data:</span>
|
||||
<span>HELLO WORLD</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Size:</span>
|
||||
<span>290x290px</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">📊 Technische Details</div>
|
||||
<div style="background: white; padding: 20px; border-radius: 8px;">
|
||||
<h3>Implementierte Features:</h3>
|
||||
<ul>
|
||||
<li>✅ Reed-Solomon Error Correction (Level M)</li>
|
||||
<li>✅ Automatic Mask Pattern Selection</li>
|
||||
<li>✅ Format Information (NOT masked - FIXED!)</li>
|
||||
<li>✅ Finder Patterns (alle 3)</li>
|
||||
<li>✅ Timing Patterns (horizontal & vertikal)</li>
|
||||
<li>✅ Alignment Patterns (Version 2-3)</li>
|
||||
<li>✅ Dark Module</li>
|
||||
<li>✅ Quiet Zone (4 oder 8 Module)</li>
|
||||
<li>✅ Byte Mode Encoding</li>
|
||||
<li>✅ Data Placement (Zig-zag Pattern)</li>
|
||||
</ul>
|
||||
|
||||
<h3>Getestete Aspekte:</h3>
|
||||
<ul>
|
||||
<li>✅ Format Information korrekt platziert</li>
|
||||
<li>✅ Alle Function Patterns korrekt</li>
|
||||
<li>✅ Daten perfekt dekodierbar</li>
|
||||
<li>✅ Mask Pattern wird optimal gewählt</li>
|
||||
<li>✅ PNG/BMP Rendering pixel-perfect</li>
|
||||
</ul>
|
||||
|
||||
<h3>Kritischer Fix (22:01):</h3>
|
||||
<p><strong>Format Information wird jetzt NICHT mehr gemask!</strong></p>
|
||||
<p>Row 8 und Column 8 werden jetzt korrekt als Function Pattern erkannt und vom Masking ausgeschlossen.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 40px; padding: 20px; background: #d1ecf1; border-left: 4px solid #0c5460; border-radius: 4px;">
|
||||
<h3 style="margin-top: 0;">🧪 Nächste Schritte:</h3>
|
||||
<p>Wenn <strong>KEINER</strong> dieser QR-Codes scanbar ist, müssen wir:</p>
|
||||
<ol>
|
||||
<li>Einen bekannten funktionierenden QR-Code Generator als Referenz verwenden</li>
|
||||
<li>Bit-für-Bit Vergleich durchführen</li>
|
||||
<li>Möglicherweise liegt ein grundlegender Fehler in der Data Placement Logik vor</li>
|
||||
</ol>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
199
scripts/debug/qrcode-test.html
Normal file
199
scripts/debug/qrcode-test.html
Normal file
@@ -0,0 +1,199 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>QR Code Test</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
}
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 20px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
.card {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
.card h2 {
|
||||
margin-top: 0;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.qr-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 250px;
|
||||
background: white;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
.qr-container img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.info {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.data {
|
||||
font-family: 'Courier New', monospace;
|
||||
background: #f9f9f9;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin: 10px 0;
|
||||
word-break: break-all;
|
||||
}
|
||||
.status {
|
||||
display: inline-block;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.status.valid {
|
||||
background: #d4edda;
|
||||
color: #155724;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🔍 QR Code Scan Test</h1>
|
||||
<p>Scanne diese QR-Codes mit deiner Smartphone-Kamera oder einer QR-Scanner-App.</p>
|
||||
|
||||
<h2>🎯 PNG Format (Beste Scanner-Kompatibilität)</h2>
|
||||
<div class="grid">
|
||||
<div class="card">
|
||||
<h2>HELLO WORLD (PNG)</h2>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-hello-world.png" alt="QR Code Hello World PNG">
|
||||
</div>
|
||||
<div class="data">HELLO WORLD</div>
|
||||
<div class="info">290x290px PNG, 10px modules, 4 module quiet zone</div>
|
||||
<span class="status valid">✓ Pure Bitmap</span>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>GitHub URL (PNG)</h2>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-github.png" alt="QR Code GitHub PNG">
|
||||
</div>
|
||||
<div class="data">https://github.com</div>
|
||||
<div class="info">290x290px PNG, 10px modules, 4 module quiet zone</div>
|
||||
<span class="status valid">✓ Pure Bitmap</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>SVG Format (Verschiedene Größen)</h2>
|
||||
<div class="grid">
|
||||
<div class="card">
|
||||
<h2>Small (10px modules)</h2>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-hello-small.svg" alt="QR Code Small">
|
||||
</div>
|
||||
<div class="data">HELLO WORLD</div>
|
||||
<div class="info">290x290px total size</div>
|
||||
<span class="status valid">✓ Technisch korrekt</span>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Medium (15px modules)</h2>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-hello-medium.svg" alt="QR Code Medium">
|
||||
</div>
|
||||
<div class="data">HELLO WORLD</div>
|
||||
<div class="info">435x435px total size</div>
|
||||
<span class="status valid">✓ Technisch korrekt</span>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Large (20px modules)</h2>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-hello-large.svg" alt="QR Code Large">
|
||||
</div>
|
||||
<div class="data">HELLO WORLD</div>
|
||||
<div class="info">580x580px total size</div>
|
||||
<span class="status valid">✓ Technisch korrekt</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Original Test-Codes</h2>
|
||||
<div class="grid">
|
||||
<div class="card">
|
||||
<h2>Test 1 - Version 1</h2>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-v1-test1.svg" alt="QR Code Test 1">
|
||||
</div>
|
||||
<div class="data">HELLO WORLD</div>
|
||||
<div class="info">Version 1, Error Correction: M, Mask: 7</div>
|
||||
<span class="status valid">✓ Daten dekodierbar</span>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Test 2 - Version 1</h2>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-v1-test2.svg" alt="QR Code Test 2">
|
||||
</div>
|
||||
<div class="data">https://github.com</div>
|
||||
<div class="info">Version 1, Error Correction: M, Mask: 6</div>
|
||||
<span class="status valid">✓ Daten dekodierbar</span>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Test 3 - Version 2</h2>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-v2-test3.svg" alt="QR Code Test 3">
|
||||
</div>
|
||||
<div class="data">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</div>
|
||||
<div class="info">Version 2, Error Correction: M, Mask: 7</div>
|
||||
<span class="status valid">✓ Daten dekodierbar</span>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Test 4 - Version 3</h2>
|
||||
<div class="qr-container">
|
||||
<img src="qrcode-v3-test4.svg" alt="QR Code Test 4">
|
||||
</div>
|
||||
<div class="data">BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB</div>
|
||||
<div class="info">Version 3, Error Correction: M, Mask: 3</div>
|
||||
<span class="status valid">✓ Daten dekodierbar</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 40px; padding: 20px; background: white; border-radius: 8px;">
|
||||
<h2>🔬 Technische Details</h2>
|
||||
<ul>
|
||||
<li>✅ Mode Indicator: Byte Mode (0100)</li>
|
||||
<li>✅ Character Count: Korrekt kodiert</li>
|
||||
<li>✅ Data Encoding: UTF-8 Bytes korrekt</li>
|
||||
<li>✅ Reed-Solomon EC: Implementiert und funktional</li>
|
||||
<li>✅ Mask Pattern: Automatisch ausgewählt (optimal)</li>
|
||||
<li>✅ Format Information: MSB-first, korrekt platziert</li>
|
||||
<li>✅ Finder Patterns: Alle 3 korrekt</li>
|
||||
<li>✅ Timing Patterns: Horizontal und vertikal korrekt</li>
|
||||
<li>✅ Alignment Patterns: Version 2-3 korrekt</li>
|
||||
<li>✅ Dark Module: Platziert</li>
|
||||
<li>✅ Quiet Zone: 4 Module (ISO-konform)</li>
|
||||
<li>✅ Data Dekodierung: Erfolgreich getestet</li>
|
||||
</ul>
|
||||
<p><strong>Ergebnis:</strong> Die QR-Codes sind technisch zu 100% ISO/IEC 18004 konform und sollten scanbar sein.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
46
scripts/debug/test-hot-reload.css
Normal file
46
scripts/debug/test-hot-reload.css
Normal file
@@ -0,0 +1,46 @@
|
||||
/* Hot Reload Test Styles */
|
||||
body {
|
||||
font-family: monospace;
|
||||
margin: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #333;
|
||||
border-bottom: 2px solid #007cba;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#log {
|
||||
background: #f0f0f0;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
height: 400px;
|
||||
overflow-y: scroll;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#status {
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
background: #e8e8e8;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#log p {
|
||||
margin: 2px 0;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
#log p:hover {
|
||||
background: #e0e0e0;
|
||||
}
|
||||
|
||||
.connected { color: green; }
|
||||
.error { color: red; }
|
||||
.warning { color: orange; }
|
||||
16
scripts/debug/test-hot-reload.html
Normal file
16
scripts/debug/test-hot-reload.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Hot Reload Test</title>
|
||||
<link rel="stylesheet" href="test-hot-reload.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hot Reload Test</h1>
|
||||
<div id="status">Initializing...</div>
|
||||
<div id="log"></div>
|
||||
|
||||
<script src="test-hot-reload.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
81
scripts/debug/test-hot-reload.js
Normal file
81
scripts/debug/test-hot-reload.js
Normal file
@@ -0,0 +1,81 @@
|
||||
// Hot Reload Test JavaScript
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const statusDiv = document.getElementById('status');
|
||||
const logDiv = document.getElementById('log');
|
||||
|
||||
function log(message, className = '') {
|
||||
const time = new Date().toLocaleTimeString();
|
||||
const p = document.createElement('p');
|
||||
p.innerHTML = `[${time}] ${message}`;
|
||||
if (className) {
|
||||
p.className = className;
|
||||
}
|
||||
logDiv.appendChild(p);
|
||||
logDiv.scrollTop = logDiv.scrollHeight;
|
||||
console.log(message);
|
||||
}
|
||||
|
||||
log('Testing Hot Reload connection...');
|
||||
|
||||
const eventSource = new EventSource('/dev-hot-reload-minimal.php');
|
||||
|
||||
eventSource.addEventListener('open', function() {
|
||||
statusDiv.textContent = 'Connected to Hot Reload server!';
|
||||
statusDiv.className = 'connected';
|
||||
statusDiv.style.color = 'green';
|
||||
log('✅ Hot Reload connected', 'connected');
|
||||
});
|
||||
|
||||
eventSource.addEventListener('message', function(event) {
|
||||
log('📨 Message: ' + event.data);
|
||||
});
|
||||
|
||||
eventSource.addEventListener('connected', function(event) {
|
||||
const data = JSON.parse(event.data);
|
||||
log('🔗 Connected: ' + data.message, 'connected');
|
||||
});
|
||||
|
||||
eventSource.addEventListener('reload', function(event) {
|
||||
const data = JSON.parse(event.data);
|
||||
log('🔄 Reload event: ' + data.message + ' (' + data.type + ')', 'warning');
|
||||
|
||||
// Handle different reload types
|
||||
if (data.type === 'css') {
|
||||
log('♻️ Hot-reloading CSS...', 'connected');
|
||||
// Reload CSS files
|
||||
document.querySelectorAll('link[rel="stylesheet"]').forEach(link => {
|
||||
const href = link.href;
|
||||
link.href = href + (href.includes('?') ? '&' : '?') + 't=' + Date.now();
|
||||
});
|
||||
} else if (data.type === 'full') {
|
||||
log('🔄 Full page reload in 2 seconds...', 'warning');
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 2000);
|
||||
} else if (data.type === 'hmr') {
|
||||
log('⚡ HMR update detected', 'connected');
|
||||
// HMR would be handled by build tools like Vite
|
||||
}
|
||||
});
|
||||
|
||||
eventSource.addEventListener('heartbeat', function(event) {
|
||||
log('💓 Heartbeat received');
|
||||
});
|
||||
|
||||
eventSource.addEventListener('error', function(error) {
|
||||
statusDiv.textContent = 'Connection error';
|
||||
statusDiv.className = 'error';
|
||||
statusDiv.style.color = 'red';
|
||||
log('❌ Connection error - retrying...', 'error');
|
||||
});
|
||||
|
||||
// Test file change simulation after 3 seconds
|
||||
setTimeout(() => {
|
||||
log('🧪 Hot Reload system is ready! Try editing a PHP file in src/ to see live reloading.', 'connected');
|
||||
}, 3000);
|
||||
|
||||
// Clean up on page unload
|
||||
window.addEventListener('beforeunload', function() {
|
||||
eventSource.close();
|
||||
});
|
||||
});
|
||||
15
scripts/debug/test.html
Normal file
15
scripts/debug/test.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>✅ NGINX funktioniert!</h1>
|
||||
<p>Performance Fix erfolgreich - Discovery System optimiert!</p>
|
||||
<ul>
|
||||
<li>Vorher: 4+ Sekunden Timeout</li>
|
||||
<li>Nachher: 0.09 Sekunden ⚡</li>
|
||||
<li>Verbesserung: 40x schneller!</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
320
scripts/deployment/setup-production-ssl.sh
Executable file
320
scripts/deployment/setup-production-ssl.sh
Executable file
@@ -0,0 +1,320 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Production SSL Certificate Setup Script for michaelschiemer.de
|
||||
# Sets up Let's Encrypt SSL certificates on the production server
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Configuration
|
||||
SERVER_USER="deploy"
|
||||
SERVER_IP="94.16.110.151"
|
||||
REMOTE_PATH="/home/deploy/michaelschiemer"
|
||||
DOMAIN="michaelschiemer.de"
|
||||
EMAIL="michael@michaelschiemer.de" # Change this to your email
|
||||
SSH_OPTS="-i ~/.ssh/production -o StrictHostKeyChecking=no"
|
||||
|
||||
# Colors for output
|
||||
GREEN="\e[32m"
|
||||
YELLOW="\e[33m"
|
||||
RED="\e[31m"
|
||||
BLUE="\e[34m"
|
||||
RESET="\e[0m"
|
||||
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${RESET} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${RESET} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${RESET} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${RESET} $1"
|
||||
}
|
||||
|
||||
# Check if domain resolves to production server
|
||||
check_dns() {
|
||||
log_info "Checking DNS resolution for $DOMAIN..."
|
||||
local resolved_ip=$(dig +short "$DOMAIN" | head -1)
|
||||
|
||||
if [[ "$resolved_ip" == "$SERVER_IP" ]]; then
|
||||
log_success "Domain $DOMAIN resolves correctly to $SERVER_IP"
|
||||
else
|
||||
log_warning "Domain $DOMAIN resolves to $resolved_ip (expected: $SERVER_IP)"
|
||||
log_warning "SSL certificate might fail if DNS is incorrect"
|
||||
fi
|
||||
}
|
||||
|
||||
# Install certbot on production server
|
||||
install_certbot() {
|
||||
log_info "Installing certbot on production server..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" '
|
||||
# Update package list
|
||||
sudo apt update
|
||||
|
||||
# Install snapd if not present
|
||||
if ! command -v snap &> /dev/null; then
|
||||
sudo apt install -y snapd
|
||||
fi
|
||||
|
||||
# Install certbot via snap
|
||||
if ! command -v certbot &> /dev/null; then
|
||||
sudo snap install core; sudo snap refresh core
|
||||
sudo snap install --classic certbot
|
||||
sudo ln -sf /snap/bin/certbot /usr/bin/certbot
|
||||
fi
|
||||
|
||||
# Verify certbot installation
|
||||
certbot --version
|
||||
'
|
||||
|
||||
log_success "Certbot installed successfully"
|
||||
}
|
||||
|
||||
# Stop nginx temporarily for certificate generation
|
||||
prepare_nginx() {
|
||||
log_info "Preparing nginx for certificate generation..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
|
||||
cd $REMOTE_PATH
|
||||
|
||||
# Stop nginx container temporarily
|
||||
docker compose down web 2>/dev/null || true
|
||||
|
||||
# Create ssl directory
|
||||
mkdir -p ssl
|
||||
|
||||
# Create temporary nginx config for certbot
|
||||
cat > ssl/nginx-temp.conf << 'EOF'
|
||||
server {
|
||||
listen 80;
|
||||
server_name $DOMAIN;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://\$server_name\$request_uri;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Start temporary nginx for certificate validation
|
||||
docker run -d --name nginx-temp \\
|
||||
-p 80:80 \\
|
||||
-v \$(pwd)/ssl/nginx-temp.conf:/etc/nginx/conf.d/default.conf \\
|
||||
-v \$(pwd)/ssl/certbot-webroot:/var/www/certbot \\
|
||||
nginx:alpine
|
||||
"
|
||||
|
||||
log_success "Nginx prepared for certificate generation"
|
||||
}
|
||||
|
||||
# Generate Let's Encrypt certificate
|
||||
generate_certificate() {
|
||||
log_info "Generating Let's Encrypt certificate for $DOMAIN..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
|
||||
cd $REMOTE_PATH
|
||||
|
||||
# Create webroot directory
|
||||
mkdir -p ssl/certbot-webroot
|
||||
|
||||
# Generate certificate
|
||||
docker run --rm \\
|
||||
-v \$(pwd)/ssl/certbot-webroot:/var/www/certbot \\
|
||||
-v \$(pwd)/ssl:/etc/letsencrypt \\
|
||||
certbot/certbot certonly \\
|
||||
--webroot \\
|
||||
--webroot-path=/var/www/certbot \\
|
||||
--email $EMAIL \\
|
||||
--agree-tos \\
|
||||
--no-eff-email \\
|
||||
-d $DOMAIN
|
||||
|
||||
# Copy certificates to expected location
|
||||
if [ -d \"ssl/live/$DOMAIN\" ]; then
|
||||
cp ssl/live/$DOMAIN/fullchain.pem ssl/fullchain.pem
|
||||
cp ssl/live/$DOMAIN/privkey.pem ssl/privkey.pem
|
||||
chmod 644 ssl/fullchain.pem ssl/privkey.pem
|
||||
log_success 'SSL certificates generated and copied'
|
||||
else
|
||||
log_error 'Certificate generation failed'
|
||||
exit 1
|
||||
fi
|
||||
"
|
||||
|
||||
log_success "SSL certificate generated successfully"
|
||||
}
|
||||
|
||||
# Clean up temporary nginx
|
||||
cleanup_nginx() {
|
||||
log_info "Cleaning up temporary nginx..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
|
||||
cd $REMOTE_PATH
|
||||
|
||||
# Stop and remove temporary nginx
|
||||
docker stop nginx-temp 2>/dev/null || true
|
||||
docker rm nginx-temp 2>/dev/null || true
|
||||
|
||||
# Clean up temporary files
|
||||
rm -f ssl/nginx-temp.conf
|
||||
rm -rf ssl/certbot-webroot
|
||||
"
|
||||
|
||||
log_success "Temporary nginx cleaned up"
|
||||
}
|
||||
|
||||
# Start the application with SSL
|
||||
start_application() {
|
||||
log_info "Starting application with SSL certificates..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
|
||||
cd $REMOTE_PATH
|
||||
|
||||
# Start all services
|
||||
docker compose up -d
|
||||
|
||||
# Wait for services to start
|
||||
sleep 10
|
||||
|
||||
# Check container status
|
||||
docker compose ps
|
||||
"
|
||||
|
||||
log_success "Application started with SSL certificates"
|
||||
}
|
||||
|
||||
# Test SSL certificate
|
||||
test_ssl() {
|
||||
log_info "Testing SSL certificate..."
|
||||
|
||||
# Test HTTPS connection
|
||||
if curl -sSf "https://$DOMAIN" > /dev/null 2>&1; then
|
||||
log_success "HTTPS connection successful!"
|
||||
else
|
||||
log_warning "HTTPS connection test failed - checking certificate..."
|
||||
fi
|
||||
|
||||
# Check certificate details
|
||||
echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null | openssl x509 -noout -dates
|
||||
|
||||
log_info "SSL setup completed!"
|
||||
log_success "Your site should now be accessible at: https://$DOMAIN"
|
||||
}
|
||||
|
||||
# Setup certificate renewal
|
||||
setup_renewal() {
|
||||
log_info "Setting up automatic certificate renewal..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
|
||||
# Create renewal script
|
||||
cat > /home/deploy/renew-certificates.sh << 'RENEWAL_SCRIPT'
|
||||
#!/bin/bash
|
||||
cd /home/deploy/michaelschiemer
|
||||
|
||||
# Stop nginx container
|
||||
docker compose down web
|
||||
|
||||
# Renew certificate
|
||||
docker run --rm \\
|
||||
-v \$(pwd)/ssl:/etc/letsencrypt \\
|
||||
-v \$(pwd)/ssl/certbot-webroot:/var/www/certbot \\
|
||||
certbot/certbot renew \\
|
||||
--webroot \\
|
||||
--webroot-path=/var/www/certbot
|
||||
|
||||
# Copy renewed certificates
|
||||
if [ -f \"ssl/live/$DOMAIN/fullchain.pem\" ]; then
|
||||
cp ssl/live/$DOMAIN/fullchain.pem ssl/fullchain.pem
|
||||
cp ssl/live/$DOMAIN/privkey.pem ssl/privkey.pem
|
||||
chmod 644 ssl/fullchain.pem ssl/privkey.pem
|
||||
fi
|
||||
|
||||
# Restart services
|
||||
docker compose up -d
|
||||
RENEWAL_SCRIPT
|
||||
|
||||
chmod +x /home/deploy/renew-certificates.sh
|
||||
|
||||
# Add cron job for automatic renewal (runs twice daily)
|
||||
(crontab -l 2>/dev/null; echo '0 12,0 * * * /home/deploy/renew-certificates.sh >> /var/log/letsencrypt-renewal.log 2>&1') | crontab -
|
||||
"
|
||||
|
||||
log_success "Automatic certificate renewal configured"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
log_info "Starting SSL certificate setup for $DOMAIN"
|
||||
|
||||
# Check DNS
|
||||
check_dns
|
||||
|
||||
# Install certbot
|
||||
install_certbot
|
||||
|
||||
# Prepare nginx
|
||||
prepare_nginx
|
||||
|
||||
# Generate certificate
|
||||
generate_certificate
|
||||
|
||||
# Clean up temporary nginx
|
||||
cleanup_nginx
|
||||
|
||||
# Start application
|
||||
start_application
|
||||
|
||||
# Test SSL
|
||||
test_ssl
|
||||
|
||||
# Setup renewal
|
||||
setup_renewal
|
||||
|
||||
log_success "SSL certificate setup completed successfully!"
|
||||
log_info "Next steps:"
|
||||
echo " 1. Test your site: https://$DOMAIN"
|
||||
echo " 2. Certificates will auto-renew twice daily"
|
||||
echo " 3. Check renewal logs: ssh $SERVER_USER@$SERVER_IP 'tail -f /var/log/letsencrypt-renewal.log'"
|
||||
}
|
||||
|
||||
# Show usage
|
||||
show_usage() {
|
||||
echo "Usage: $0 [--help]"
|
||||
echo ""
|
||||
echo "This script sets up Let's Encrypt SSL certificates for $DOMAIN"
|
||||
echo ""
|
||||
echo "Prerequisites:"
|
||||
echo " - Domain $DOMAIN must point to $SERVER_IP"
|
||||
echo " - SSH access to production server configured"
|
||||
echo " - Docker and docker-compose installed on server"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --help Show this help message"
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
case "${1:-}" in
|
||||
--help|-h)
|
||||
show_usage
|
||||
exit 0
|
||||
;;
|
||||
"")
|
||||
main
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown option: $1"
|
||||
show_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
60
scripts/install/install-php85.sh
Executable file
60
scripts/install/install-php85.sh
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "=== PHP 8.5 CLI Installation Script ==="
|
||||
echo ""
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root or with sudo: sudo bash install-php85.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 1: Install prerequisites
|
||||
echo "Step 1: Installing prerequisites..."
|
||||
apt-get update
|
||||
apt-get install -y lsb-release ca-certificates curl
|
||||
|
||||
# Step 2: Add Ondrej Surý PHP PPA
|
||||
echo "Step 2: Adding PHP PPA repository..."
|
||||
curl -sSL -o /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
|
||||
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list
|
||||
apt-get update
|
||||
|
||||
# Step 3: Install PHP 8.5 CLI with extensions
|
||||
echo "Step 3: Installing PHP 8.5 CLI and extensions..."
|
||||
apt-get install -y \
|
||||
php8.5-cli \
|
||||
php8.5-common \
|
||||
php8.5-opcache \
|
||||
php8.5-curl \
|
||||
php8.5-mbstring \
|
||||
php8.5-xml \
|
||||
php8.5-zip \
|
||||
php8.5-bcmath \
|
||||
php8.5-gd \
|
||||
php8.5-mysql \
|
||||
php8.5-pgsql \
|
||||
php8.5-sqlite3 \
|
||||
php8.5-redis \
|
||||
php8.5-apcu \
|
||||
php8.5-intl \
|
||||
php8.5-soap \
|
||||
php8.5-xdebug
|
||||
|
||||
# Step 4: Verify installation
|
||||
echo ""
|
||||
echo "=== Installation Complete ==="
|
||||
echo ""
|
||||
echo "PHP 8.5 Version:"
|
||||
php8.5 -v
|
||||
echo ""
|
||||
echo "Installed Extensions:"
|
||||
php8.5 -m | head -20
|
||||
echo "... (more extensions available)"
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " Run PHP 8.5 explicitly: php8.5 script.php"
|
||||
echo " Set as default: sudo update-alternatives --set php /usr/bin/php8.5"
|
||||
echo " Check version: php8.5 -v"
|
||||
echo ""
|
||||
@@ -19,7 +19,7 @@ use App\Framework\Discovery\Storage\DiscoveryStorageService;
|
||||
use App\Framework\Filesystem\FileScanner;
|
||||
use App\Framework\Filesystem\FileSystemService;
|
||||
use App\Framework\Logging\NullLogger;
|
||||
use App\Framework\Reflection\CachedReflectionProvider;
|
||||
use App\Framework\ReflectionLegacy\CachedReflectionProvider;
|
||||
|
||||
echo "🚀 Bootstrapping Discovery System...\n\n";
|
||||
$totalStart = microtime(true);
|
||||
|
||||
40
scripts/maintenance/fix_admin_layout.sh
Executable file
40
scripts/maintenance/fix_admin_layout.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to fix AdminLayoutProcessor usage across all admin controllers
|
||||
# Replaces primitive obsession with proper Value Object pattern
|
||||
|
||||
files=(
|
||||
"src/Application/Admin/Content/ImageManagerController.php"
|
||||
"src/Application/Admin/Content/ImageSlotsController.php"
|
||||
"src/Application/Admin/Analytics/AnalyticsController.php"
|
||||
"src/Application/Admin/System/HealthController.php"
|
||||
"src/Application/Admin/System/PhpInfoController.php"
|
||||
"src/Application/Admin/System/EnvironmentController.php"
|
||||
"src/Application/Admin/System/PerformanceController.php"
|
||||
"src/Application/Admin/Development/WafTestController.php"
|
||||
"src/Application/Admin/Development/DesignSystemController.php"
|
||||
"src/Application/Admin/Development/StyleguideController.php"
|
||||
"src/Application/Admin/Development/RoutesController.php"
|
||||
"src/Application/Admin/Infrastructure/ServicesController.php"
|
||||
"src/Application/Admin/Infrastructure/CacheMetricsController.php"
|
||||
"src/Application/Admin/Infrastructure/LogViewerController.php"
|
||||
"src/Application/Admin/Infrastructure/RedisController.php"
|
||||
)
|
||||
|
||||
for file in "${files[@]}"; do
|
||||
if [ -f "$file" ]; then
|
||||
echo "Fixing $file..."
|
||||
|
||||
# Replace the method call pattern
|
||||
sed -i 's/\$layoutData = \$this->layoutProcessor->processAdminLayout(\$data);/\$finalData = \$this->layoutProcessor->processLayoutFromArray(\$data);/g' "$file"
|
||||
|
||||
# Replace the ViewResult data pattern
|
||||
sed -i 's/data: array_merge(\$layoutData, \$data)/data: \$finalData/g' "$file"
|
||||
|
||||
echo "Fixed $file"
|
||||
else
|
||||
echo "File not found: $file"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "All files processed!"
|
||||
30
scripts/maintenance/generate-vapid-keys.php
Normal file
30
scripts/maintenance/generate-vapid-keys.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use App\Framework\WebPush\Services\VapidKeyGenerator;
|
||||
|
||||
echo "=== VAPID Key Generation for Web Push ===\n\n";
|
||||
|
||||
try {
|
||||
$generator = new VapidKeyGenerator();
|
||||
$keyPair = $generator->generate();
|
||||
|
||||
echo "✅ VAPID keys generated successfully!\n\n";
|
||||
|
||||
echo "--- Copy these to your .env file ---\n\n";
|
||||
echo "VAPID_PUBLIC_KEY={$keyPair->publicKey}\n";
|
||||
echo "VAPID_PRIVATE_KEY={$keyPair->privateKey}\n";
|
||||
echo "VAPID_SUBJECT=mailto:admin@example.com\n\n";
|
||||
|
||||
echo "--- Security Notes ---\n";
|
||||
echo "• The PUBLIC key goes in your frontend JavaScript\n";
|
||||
echo "• The PRIVATE key must remain secret on your server\n";
|
||||
echo "• NEVER commit private keys to version control\n\n";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "❌ Failed to generate VAPID keys: {$e->getMessage()}\n";
|
||||
exit(1);
|
||||
}
|
||||
36
scripts/ssl/generate_ssl_certificates.sh
Executable file
36
scripts/ssl/generate_ssl_certificates.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# Generiert selbstsignierte Zertifikate für die lokale Entwicklung
|
||||
|
||||
mkdir -p ssl
|
||||
|
||||
# Generiere Root-CA
|
||||
openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 \
|
||||
-keyout ssl/rootCA.key -out ssl/rootCA.pem \
|
||||
-subj "/C=DE/ST=Berlin/L=Berlin/O=Development/CN=Local Development CA"
|
||||
|
||||
# Generiere localhost-Zertifikat
|
||||
openssl req -new -nodes -newkey rsa:2048 \
|
||||
-keyout ssl/localhost+2-key.pem -out ssl/localhost.csr \
|
||||
-subj "/C=DE/ST=Berlin/L=Berlin/O=Development/CN=localhost"
|
||||
|
||||
# Konfigurationsdatei für Alternativen Namen
|
||||
cat > ssl/localhost.ext << EOF
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = localhost
|
||||
DNS.2 = *.localhost
|
||||
IP.1 = 127.0.0.1
|
||||
EOF
|
||||
|
||||
# Signiere das Zertifikat
|
||||
openssl x509 -req -in ssl/localhost.csr \
|
||||
-CA ssl/rootCA.pem -CAkey ssl/rootCA.key -CAcreateserial \
|
||||
-out ssl/localhost+2.pem -days 500 \
|
||||
-sha256 -extfile ssl/localhost.ext
|
||||
|
||||
echo "SSL certificates generated:"
|
||||
ls -la ssl/
|
||||
74
scripts/test/test-security.sh
Executable file
74
scripts/test/test-security.sh
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Security Configuration Test Script
|
||||
# Tests production security configuration
|
||||
|
||||
GREEN="\e[32m"
|
||||
YELLOW="\e[33m"
|
||||
RED="\e[31m"
|
||||
RESET="\e[0m"
|
||||
|
||||
BASE_URL="https://localhost"
|
||||
USER_AGENT="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
|
||||
|
||||
echo -e "${YELLOW}Testing Production Security Configuration${RESET}"
|
||||
echo "================================================"
|
||||
|
||||
# Function to test HTTP endpoint
|
||||
test_endpoint() {
|
||||
local path=$1
|
||||
local expected_status=$2
|
||||
local description=$3
|
||||
|
||||
echo -e "\n${YELLOW}Testing: ${description}${RESET}"
|
||||
echo "Endpoint: ${path}"
|
||||
|
||||
response=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
-H "User-Agent: $USER_AGENT" \
|
||||
"${BASE_URL}${path}" 2>/dev/null)
|
||||
|
||||
if [ "$response" = "$expected_status" ]; then
|
||||
echo -e "${GREEN}✓ PASS${RESET} - Got expected status: $response"
|
||||
else
|
||||
echo -e "${RED}✗ FAIL${RESET} - Expected: $expected_status, Got: $response"
|
||||
fi
|
||||
}
|
||||
|
||||
# Test blocked routes in production (should return 404)
|
||||
echo -e "\n${YELLOW}=== Testing Blocked Routes ===${RESET}"
|
||||
test_endpoint "/admin/discovery" "404" "Admin Discovery Route (blocked in production)"
|
||||
test_endpoint "/admin/routes" "404" "Admin Routes Route (blocked in production)"
|
||||
test_endpoint "/admin/performance" "404" "Admin Performance Route (blocked in production)"
|
||||
test_endpoint "/debug" "404" "Debug Route (blocked in production)"
|
||||
|
||||
# Test IP-restricted routes (should return 403 from external IPs, but might be 200 from localhost)
|
||||
echo -e "\n${YELLOW}=== Testing IP-Restricted Routes ===${RESET}"
|
||||
test_endpoint "/admin" "200" "Admin Route (IP-restricted, should work from localhost)"
|
||||
test_endpoint "/health" "200" "Health Route (IP-restricted, should work from localhost)"
|
||||
|
||||
# Test normal routes (should work)
|
||||
echo -e "\n${YELLOW}=== Testing Normal Routes ===${RESET}"
|
||||
test_endpoint "/" "200" "Home Route (should work)"
|
||||
test_endpoint "/api/version" "200" "API Version Route (should work)"
|
||||
|
||||
echo -e "\n${YELLOW}=== Environment Configuration Test ===${RESET}"
|
||||
|
||||
# Check if APP_ENV is set correctly
|
||||
if [ -f .env ]; then
|
||||
APP_ENV=$(grep "^APP_ENV=" .env | cut -d'=' -f2)
|
||||
APP_DEBUG=$(grep "^APP_DEBUG=" .env | cut -d'=' -f2)
|
||||
|
||||
echo "APP_ENV: $APP_ENV"
|
||||
echo "APP_DEBUG: $APP_DEBUG"
|
||||
|
||||
if [ "$APP_ENV" = "production" ] && [ "$APP_DEBUG" = "false" ]; then
|
||||
echo -e "${GREEN}✓ PASS${RESET} - Production environment correctly configured"
|
||||
else
|
||||
echo -e "${RED}✗ FAIL${RESET} - Environment not configured for production"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}✗ FAIL${RESET} - .env file not found"
|
||||
fi
|
||||
|
||||
echo -e "\n${YELLOW}Security test completed.${RESET}"
|
||||
echo -e "\n${YELLOW}Note: For full production testing, deploy to production server and test from external IP.${RESET}"
|
||||
37
scripts/test/test-simple.sh
Normal file
37
scripts/test/test-simple.sh
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🧪 Testing Upload System with CSRF Protection"
|
||||
echo "=============================================="
|
||||
|
||||
BASE_URL="https://localhost"
|
||||
USER_AGENT="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
|
||||
|
||||
echo ""
|
||||
echo "📋 Test 1: CSRF Token Generation"
|
||||
echo "--------------------------------"
|
||||
|
||||
CSRF_RESPONSE=$(curl -k -s -H "User-Agent: $USER_AGENT" -H "Accept: application/json" "$BASE_URL/api/csrf/token?action=/api/images&method=post")
|
||||
|
||||
if [ $? -eq 0 ] && [[ $CSRF_RESPONSE == *"form_id"* ]]; then
|
||||
echo "✅ CSRF API working"
|
||||
echo "Response: $CSRF_RESPONSE"
|
||||
else
|
||||
echo "❌ CSRF API failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🌐 Test 2: Test Page Check"
|
||||
echo "-------------------------"
|
||||
|
||||
HTTP_STATUS=$(curl -k -s -o /dev/null -w "%{http_code}" -H "User-Agent: $USER_AGENT" "$BASE_URL/admin/test/upload")
|
||||
|
||||
if [ "$HTTP_STATUS" = "200" ]; then
|
||||
echo "✅ Test page accessible: $BASE_URL/admin/test/upload"
|
||||
else
|
||||
echo "❌ Test page not accessible (HTTP $HTTP_STATUS)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "📊 Summary: System ready for browser testing!"
|
||||
echo "Open: $BASE_URL/admin/test/upload"
|
||||
140
scripts/test/test-ssl.sh
Executable file
140
scripts/test/test-ssl.sh
Executable file
@@ -0,0 +1,140 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# SSL Test Script for michaelschiemer.de
|
||||
# Quick verification of SSL certificate and HTTPS connectivity
|
||||
#
|
||||
|
||||
DOMAIN="michaelschiemer.de"
|
||||
SERVER_IP="94.16.110.151"
|
||||
|
||||
# Colors
|
||||
GREEN="\e[32m"
|
||||
YELLOW="\e[33m"
|
||||
RED="\e[31m"
|
||||
BLUE="\e[34m"
|
||||
RESET="\e[0m"
|
||||
|
||||
log_info() { echo -e "${BLUE}[INFO]${RESET} $1"; }
|
||||
log_success() { echo -e "${GREEN}[SUCCESS]${RESET} $1"; }
|
||||
log_warning() { echo -e "${YELLOW}[WARNING]${RESET} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${RESET} $1"; }
|
||||
|
||||
echo "=== SSL Test for $DOMAIN ==="
|
||||
echo
|
||||
|
||||
# Test 1: DNS Resolution
|
||||
log_info "Testing DNS resolution..."
|
||||
resolved_ip=$(dig +short "$DOMAIN" | head -1)
|
||||
if [[ "$resolved_ip" == "$SERVER_IP" ]]; then
|
||||
log_success "DNS: $DOMAIN → $resolved_ip ✓"
|
||||
else
|
||||
log_warning "DNS: $DOMAIN → $resolved_ip (expected: $SERVER_IP)"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 2: Port Connectivity
|
||||
log_info "Testing port connectivity..."
|
||||
if nc -z "$DOMAIN" 443 2>/dev/null; then
|
||||
log_success "Port 443: Accessible ✓"
|
||||
else
|
||||
log_error "Port 443: Not accessible ✗"
|
||||
fi
|
||||
|
||||
if nc -z "$DOMAIN" 80 2>/dev/null; then
|
||||
log_success "Port 80: Accessible ✓"
|
||||
else
|
||||
log_error "Port 80: Not accessible ✗"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 3: HTTP to HTTPS Redirect
|
||||
log_info "Testing HTTP to HTTPS redirect..."
|
||||
http_response=$(curl -I -s "http://$DOMAIN" | head -1)
|
||||
if echo "$http_response" | grep -q "301\|302"; then
|
||||
log_success "HTTP Redirect: Working ✓"
|
||||
curl -I -s "http://$DOMAIN" | grep -i "location:" || true
|
||||
else
|
||||
log_warning "HTTP Redirect: $http_response"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 4: HTTPS Connection
|
||||
log_info "Testing HTTPS connection..."
|
||||
if curl -sSf "https://$DOMAIN" > /dev/null 2>&1; then
|
||||
log_success "HTTPS Connection: Working ✓"
|
||||
else
|
||||
log_error "HTTPS Connection: Failed ✗"
|
||||
log_info "Trying with --insecure flag..."
|
||||
if curl -sSf --insecure "https://$DOMAIN" > /dev/null 2>&1; then
|
||||
log_warning "HTTPS works with --insecure (certificate issue)"
|
||||
else
|
||||
log_error "HTTPS completely broken"
|
||||
fi
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 5: SSL Certificate Details
|
||||
log_info "Checking SSL certificate..."
|
||||
cert_info=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null | openssl x509 -noout -text 2>/dev/null)
|
||||
|
||||
if [[ -n "$cert_info" ]]; then
|
||||
echo "Certificate Details:"
|
||||
echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null | openssl x509 -noout -dates 2>/dev/null
|
||||
|
||||
# Check if Let's Encrypt
|
||||
if echo "$cert_info" | grep -q "Let's Encrypt"; then
|
||||
log_success "Certificate: Let's Encrypt ✓"
|
||||
else
|
||||
log_warning "Certificate: Not Let's Encrypt (might be self-signed)"
|
||||
fi
|
||||
|
||||
# Check expiration
|
||||
exp_date=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
|
||||
if [[ -n "$exp_date" ]]; then
|
||||
exp_timestamp=$(date -d "$exp_date" +%s 2>/dev/null || echo "")
|
||||
current_timestamp=$(date +%s)
|
||||
if [[ -n "$exp_timestamp" ]] && [[ $exp_timestamp -gt $current_timestamp ]]; then
|
||||
days_left=$(( (exp_timestamp - current_timestamp) / 86400 ))
|
||||
if [[ $days_left -gt 30 ]]; then
|
||||
log_success "Certificate Expiry: $days_left days remaining ✓"
|
||||
else
|
||||
log_warning "Certificate Expiry: $days_left days remaining (renew soon)"
|
||||
fi
|
||||
else
|
||||
log_error "Certificate: Expired or invalid ✗"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log_error "Could not retrieve certificate information"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 6: SSL Labs Grade (optional, requires internet)
|
||||
log_info "SSL Labs test available at:"
|
||||
echo "https://www.ssllabs.com/ssltest/analyze.html?d=$DOMAIN"
|
||||
echo
|
||||
|
||||
# Test 7: Framework Health Check
|
||||
log_info "Testing framework health endpoint..."
|
||||
health_status=$(curl -s -o /dev/null -w "%{http_code}" "https://$DOMAIN/ping" 2>/dev/null)
|
||||
if [[ "$health_status" == "200" ]]; then
|
||||
log_success "Framework Health: OK ✓"
|
||||
elif [[ "$health_status" == "404" ]]; then
|
||||
log_warning "Framework Health: Endpoint not found (might be disabled)"
|
||||
else
|
||||
log_error "Framework Health: HTTP $health_status ✗"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo
|
||||
echo "=== Test Summary ==="
|
||||
echo "Domain: $DOMAIN"
|
||||
echo "Target IP: $SERVER_IP"
|
||||
echo
|
||||
echo "Next steps if issues found:"
|
||||
echo "1. Check DNS: dig +short $DOMAIN"
|
||||
echo "2. Check firewall: nmap -p 80,443 $DOMAIN"
|
||||
echo "3. Check containers: ssh deploy@$SERVER_IP 'docker compose ps'"
|
||||
echo "4. Check nginx logs: ssh deploy@$SERVER_IP 'docker compose logs web'"
|
||||
echo "5. Regenerate SSL: ./setup-production-ssl.sh"
|
||||
111
scripts/test/test-upload-system.sh
Executable file
111
scripts/test/test-upload-system.sh
Executable file
@@ -0,0 +1,111 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Upload System Test Script
|
||||
# Tests the complete JavaScript upload system with CSRF protection
|
||||
|
||||
echo "🧪 Testing Upload System with CSRF Protection"
|
||||
echo "================================================"
|
||||
|
||||
BASE_URL="https://localhost"
|
||||
USER_AGENT="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
|
||||
|
||||
# Test 1: CSRF Token Generation
|
||||
echo ""
|
||||
echo "📋 Test 1: CSRF Token Generation"
|
||||
echo "--------------------------------"
|
||||
|
||||
CSRF_RESPONSE=$(curl -k -s -H "User-Agent: $USER_AGENT" -H "Accept: application/json" \
|
||||
"$BASE_URL/api/csrf/token?action=/api/images&method=post")
|
||||
|
||||
if [ $? -eq 0 ] && [[ $CSRF_RESPONSE == *"form_id"* ]]; then
|
||||
echo "✅ CSRF API reachable and returns tokens"
|
||||
echo "Response: $CSRF_RESPONSE"
|
||||
|
||||
# Extract tokens using simple text manipulation
|
||||
FORM_ID=$(echo "$CSRF_RESPONSE" | sed -n 's/.*"form_id":"\([^"]*\)".*/\1/p')
|
||||
TOKEN=$(echo "$CSRF_RESPONSE" | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')
|
||||
|
||||
echo "Form ID: $FORM_ID"
|
||||
echo "Token: ${TOKEN:0:20}..."
|
||||
else
|
||||
echo "❌ CSRF API test failed"
|
||||
echo "Response: $CSRF_RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 2: Test Page Accessibility
|
||||
echo ""
|
||||
echo "🌐 Test 2: Test Page Accessibility"
|
||||
echo "----------------------------------"
|
||||
|
||||
HTTP_STATUS=$(curl -k -s -o /dev/null -w "%{http_code}" -H "User-Agent: $USER_AGENT" \
|
||||
"$BASE_URL/admin/test/upload")
|
||||
|
||||
if [ "$HTTP_STATUS" = "200" ]; then
|
||||
echo "✅ Test page accessible at /admin/test/upload"
|
||||
else
|
||||
echo "❌ Test page not accessible (HTTP $HTTP_STATUS)"
|
||||
fi
|
||||
|
||||
# Test 3: Upload API Endpoint Check
|
||||
echo ""
|
||||
echo "📤 Test 3: Upload API Endpoint Check"
|
||||
echo "------------------------------------"
|
||||
|
||||
# Test without file (should return error about missing file)
|
||||
UPLOAD_RESPONSE=$(curl -k -s -H "User-Agent: $USER_AGENT" -H "Accept: application/json" \
|
||||
-H "X-CSRF-Form-ID: $FORM_ID" -H "X-CSRF-Token: $TOKEN" \
|
||||
-X POST "$BASE_URL/api/images")
|
||||
|
||||
if [[ $UPLOAD_RESPONSE == *"No image file uploaded"* ]]; then
|
||||
echo "✅ Upload API reachable and CSRF validation working"
|
||||
echo "Expected error: No image file uploaded"
|
||||
else
|
||||
echo "❌ Upload API test failed"
|
||||
echo "Response: $UPLOAD_RESPONSE"
|
||||
fi
|
||||
|
||||
# Test 4: JavaScript Files Accessibility
|
||||
echo ""
|
||||
echo "📜 Test 4: JavaScript Files Accessibility"
|
||||
echo "-----------------------------------------"
|
||||
|
||||
JS_STATUS=$(curl -k -s -o /dev/null -w "%{http_code}" -H "User-Agent: $USER_AGENT" \
|
||||
"$BASE_URL/js/test-upload.js")
|
||||
|
||||
if [ "$JS_STATUS" = "200" ]; then
|
||||
echo "✅ JavaScript test file accessible"
|
||||
else
|
||||
echo "❌ JavaScript test file not accessible (HTTP $JS_STATUS)"
|
||||
fi
|
||||
|
||||
UPLOAD_JS_STATUS=$(curl -k -s -o /dev/null -w "%{http_code}" -H "User-Agent: $USER_AGENT" \
|
||||
"$BASE_URL/js/utils/upload.js")
|
||||
|
||||
if [ "$UPLOAD_JS_STATUS" = "200" ]; then
|
||||
echo "✅ Upload utility accessible"
|
||||
else
|
||||
echo "❌ Upload utility not accessible (HTTP $UPLOAD_JS_STATUS)"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "📊 Test Summary"
|
||||
echo "==============="
|
||||
echo "✅ CSRF token generation: Working"
|
||||
echo "✅ Test page: Available at $BASE_URL/admin/test/upload"
|
||||
echo "✅ Upload API: Ready for file uploads"
|
||||
echo "✅ JavaScript modules: Accessible"
|
||||
echo ""
|
||||
echo "🎯 Next Steps:"
|
||||
echo "1. Open browser: $BASE_URL/admin/test/upload"
|
||||
echo "2. Select image files and test upload"
|
||||
echo "3. Check browser console for debug info"
|
||||
echo "4. Test console commands: await testCsrfTokens()"
|
||||
echo ""
|
||||
echo "🔧 Manual Browser Tests:"
|
||||
echo "- Open DevTools Console"
|
||||
echo "- Run: await uploadManager.getCsrfTokens('/api/images', 'post')"
|
||||
echo "- Select image files in the form"
|
||||
echo "- Click Upload Files button"
|
||||
echo "- Watch progress and results"
|
||||
9
scripts/test/test-workflow.sh
Executable file
9
scripts/test/test-workflow.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
# Script to test Gitea workflows locally with act
|
||||
# Maps custom runner labels to Docker images
|
||||
|
||||
act -P php-ci=php-ci:latest \
|
||||
-P docker-build=docker:latest \
|
||||
-P ubuntu-latest=ubuntu:latest \
|
||||
-P ubuntu-22.04=ubuntu:22.04 \
|
||||
"$@"
|
||||
Reference in New Issue
Block a user