/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>
27 lines
1.5 KiB
Twig
27 lines
1.5 KiB
Twig
{% extends 'install/base.html.twig' %}
|
||
{% block heading %}Die Tabellen anlegen{% endblock %}
|
||
{% block lead %}
|
||
<p class="muted">Die Verbindung steht. Jetzt werden die Migrationen ausgeführt – dieselben, die später ein Update einspielt, und in derselben Reihenfolge. Das läuft in diesem Prozess, ohne Konsole.</p>
|
||
{% endblock %}
|
||
{% block content %}
|
||
{% if pending is not empty %}
|
||
<p><strong>{{ pending|length }}</strong> Migration{{ pending|length == 1 ? '' : 'en' }} stehen an:</p>
|
||
<ul class="check-list">
|
||
{% for name in pending|slice(0, 40) %}
|
||
<li class="check-ok"><span class="check-mark" aria-hidden="true">·</span><span><code>{{ name|split('\\')|last }}</code></span></li>
|
||
{% endfor %}
|
||
</ul>
|
||
{% else %}
|
||
<p class="muted">Es steht nichts an – entweder ist die Datenbank schon eingerichtet, oder die Liste ließ sich nicht lesen. Der Knopf unten schadet in beiden Fällen nicht: eine bereits angewandte Migration wird nicht wiederholt.</p>
|
||
{% endif %}
|
||
|
||
<form method="post" action="{{ path('install_migration') }}">
|
||
<input type="hidden" name="issued" value="{{ issued }}">
|
||
<input type="hidden" name="signature" value="{{ signature }}">
|
||
<div class="sheet-actions">
|
||
<button class="primary" type="submit">Migrationen ausführen <span aria-hidden="true">→</span></button>
|
||
</div>
|
||
</form>
|
||
<p class="muted">Dauert das zu lange und bricht der Browser ab, ist das kein Schaden: angewandte Migrationen sind vermerkt, ein erneuter Aufruf macht dort weiter.</p>
|
||
{% endblock %}
|