Files
KantSites/templates/install/database.html.twig
T
kantarciandClaude Opus 5 e34b4dca67
CMS quality / php (8.2) (push) Canceled after 0s
CMS quality / php (8.4) (push) Canceled after 0s
CMS quality / browser (push) Canceled after 0s
CMS quality / mysql (push) Canceled after 0s
Installer: sechs Bildschirme, und eine Datei davor
/install fuehrt von einer leeren Installation zu einer Website:
Systempruefung, Datenbank (SQLite oder MySQL, Verbindung sofort geprueft),
Migration im Prozess ohne Konsole, Website mit Startseite, Bereichen, Menue
sowie Impressum und Datenschutzgeruest, erstes Konto, Abschlussliste.

Jeder Schritt schreibt sein Ergebnis sofort, damit ein Neuladen nichts
verliert. Gesperrt wird ueber den Zustand der Datenbank - gibt es ein
Konto, antwortet /install mit 404. Eine Datei koennte jemand loeschen.

Solange nichts installiert ist, fuehrt jede Adresse zum Installer statt zu
einem 500 aus einer fehlenden Tabelle. Und weil ohne APP_SECRET nicht
einmal die Seite bootet, die das erklaeren wuerde, erzeugt der erste Start
das Geheimnis selbst.

scripts/install.php ist die einzelne Datei davor: Adresse und SHA-256
stehen darin (vom Buildskript eingetragen), ohne passende Pruefsumme wird
nicht entpackt, jeder Archiveintrag wird gegen das Zielverzeichnis
geprueft, und danach loescht sie sich selbst.

Geprueft: 379 Tests unter PHP 8.2 und 8.4, darunter der ganze Ablauf durch
die HTTP-Schicht, neun ZIP-Slip-Varianten, axe ohne Verstoss auf allen
Installationsbildschirmen, und das entpackte Releasearchiv startet in den
Installer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 23:11:50 +02:00

44 lines
2.8 KiB
Twig
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends 'install/base.html.twig' %}
{% block heading %}Wohin mit den Inhalten?{% endblock %}
{% block lead %}
<p class="muted">SQLite ist eine Datei auf diesem Server – nichts einzurichten, gut für eine Website mit überschaubarem Verkehr. MySQL brauchst du, wenn der Hoster es vorgibt oder mehrere Websites dieselbe Datenbank nutzen sollen. Die Verbindung wird sofort geprüft, nicht erst beim Speichern.</p>
{% endblock %}
{% block content %}
<form method="post" action="{{ path('install_database') }}">
<input type="hidden" name="issued" value="{{ issued }}">
<input type="hidden" name="signature" value="{{ signature }}">
<fieldset class="field-set">
<legend>Art der Datenbank</legend>
<label class="check-label">
<input type="radio" name="driver" value="sqlite" {{ driver != 'mysql' ? 'checked' : '' }} {{ sqlite ? '' : 'disabled' }}>
<span><strong>SQLite</strong> – eine Datei unter <code>var/</code>. Empfohlen, wenn nichts dagegen spricht.{% if not sqlite %} <em>Auf diesem Server nicht verfügbar.</em>{% endif %}</span>
</label>
<label class="check-label">
<input type="radio" name="driver" value="mysql" {{ driver == 'mysql' ? 'checked' : '' }} {{ mysql ? '' : 'disabled' }}>
<span><strong>MySQL / MariaDB</strong> – mit den Zugangsdaten aus dem Kundenmenü deines Hosters.{% if not mysql %} <em>Auf diesem Server nicht verfügbar.</em>{% endif %}</span>
</label>
</fieldset>
<label for="name">Name der Datenbank <span class="muted">(bei SQLite der Dateiname, ohne Endung)</span></label>
<input id="name" name="name" value="{{ values.name|default('cms') }}" required maxlength="64">
<details class="install-details" {{ driver == 'mysql' ? 'open' : '' }}>
<summary>Zugangsdaten für MySQL</summary>
<label for="host">Host</label>
<input id="host" name="host" value="{{ values.host|default('127.0.0.1') }}" maxlength="120" autocomplete="off">
<label for="port">Port</label>
<input id="port" name="port" value="{{ values.port|default('3306') }}" inputmode="numeric" maxlength="5" autocomplete="off">
<label for="user">Benutzer</label>
<input id="user" name="user" value="{{ values.user|default('') }}" maxlength="120" autocomplete="off">
<label for="password">Passwort</label>
<input id="password" name="password" type="password" maxlength="200" autocomplete="off">
<p class="muted">Diese Angaben landen in <code>.env.local</code> im Projektstamm – nicht in der Datenbank und in keinem Protokoll. Die Datei liegt außerhalb von <code>public/</code> und ist über das Netz nicht erreichbar.</p>
</details>
<div class="sheet-actions">
<button class="primary" type="submit">Verbindung prüfen und weiter <span aria-hidden="true">→</span></button>
</div>
</form>
{% endblock %}