feat(admin): Abgleich zwischen Platte und Datenbank
Aether fuehrt zwei Buecher: die Bytes auf der Platte und die Eintraege in
der Datenbank. Wer Dateien von aussen hineinlegt -- per SFTP oder aus
einer Sicherung zurueckgeholt --, erzeugt nur das eine. Die Datei liegt
da, Aether weiss nichts von ihr, und der GC haelt sie nach 24 Stunden
fuer einen Rest und loescht sie.
Neu deshalb internal/rescan, die Gegenrichtung zum GC, und ein Knopf
unter Admin -> Audit. Drei Faelle:
Datei da, kein Eintrag Eintrag anlegen, samt Ordnerkette,
Pruefsumme und Dateityp
Eintrag da, Datei fort Eintrag entfernen, dazu Vorschaubild und
fruehere Fassungen
von aussen ersetzt Groesse und Pruefsumme uebernehmen
Zwei Schritte, nie einer: Check liest nur, Apply aendert. Ein Knopf, der
beides in einem taete, gaebe niemandem die Gelegenheit, vorher
hinzusehen -- und was hier geloescht wird, ist nicht der Papierkorb.
Nicht angefasst werden .trash/ und .versions/. Beide liegen im selben
Baum, gehoeren aber dem System: Wuerden sie uebernommen, tauchten
geloeschte Dateien wieder auf und jede fruehere Fassung wuerde zu einer
eigenen Datei.
Zwei Fallen, die erst der Praxistest zeigte:
- Der Dateityp muss aus Endung *oder Inhalt* kommen. Beim Hochladen
schickt der Browser ihn mit; eine per SFTP abgelegte Datei bringt
niemanden mit, der ihn kennt. Dazu hat das Alpine-Abbild keine
/etc/mime.types, und Gos eingebaute Liste kennt nicht einmal .txt --
jede Textdatei waere als application/octet-stream gelandet.
- COALESCE($1, $2) ohne Cast: Postgres haelt die Parameter dann fuer
Text und bricht mit "operator does not exist: uuid = text" ab. Die
Ordnerkette wurde nie angelegt.
Die Pruefsumme wird trotz des vollstaendigen Lesevorgangs berechnet. Ein
Eintrag ohne sie waere ein Eintrag, dessen Beschaedigung beim
Herunterladen niemand bemerkt -- genau die Zusage, die Aether sonst
ueberall einhaelt.
scripts/rescan-selbsttest.py mit 20 Pruefungen in fuenf Gruppen, darunter
"Pruefen aendert nichts" und "Papierkorb bleibt unangetastet". Nebenbei
raeumt der Freigabe-Selbsttest jetzt auch seinen Papierkorb und nimmt
einen eindeutigen Kontonamen je Lauf -- ein abgebrochener Lauf blockierte
sonst jeden weiteren mit 409.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fce8053d09
commit
55dcf517f2
12 files changed
+1029
-4
No files matched your search
+40
@@ -135,6 +135,46 @@ diesem Bereich sucht:
|
||||
Freigabepfad lag außerhalb jeder Ratenbegrenzung; jeder Versuch rechnet
|
||||
Argon2, war also zugleich ein billiger Weg, den Server zu beschäftigen.
|
||||
|
||||
## Abgleich Platte ↔ Datenbank: Selbsttest per Skript
|
||||
|
||||
Der Abgleich (Admin → Audit → **Rescan storage**) übernimmt Dateien, die von
|
||||
außen dazugekommen sind – aus einer Sicherung zurückgeholt oder per SFTP
|
||||
abgelegt – und **entfernt Einträge**, deren Datei fort ist. Das zweite ist der
|
||||
Grund für diesen Test: Ein Fehler darin löscht Daten, die niemand vermisst,
|
||||
bis er sie braucht.
|
||||
|
||||
python3 scripts/rescan-selbsttest.py [BASIS-URL] [DATENPFAD]
|
||||
|
||||
Der Test schreibt selbst Dateien ins Datenverzeichnis – er muss also auf dem
|
||||
Rechner laufen, auf dem die Daten liegen (Vorgabe `~/aether-data`).
|
||||
|
||||
20 Prüfungen in fünf Gruppen: **Prüfen ändert nichts** (zweimal geprüft
|
||||
liefert dasselbe, nichts wird sichtbar), **Übernehmen** (Ordnerkette angelegt,
|
||||
Prüfsumme und Größe stimmen, Dateityp erkannt, Herunterladen liefert die
|
||||
Datei), **von außen ersetzt** (Größe und Prüfsumme werden berichtigt),
|
||||
**Datei ist fort** (verwaister Eintrag wird gefunden, bleibt beim Prüfen
|
||||
stehen, verschwindet erst beim Anwenden), **nicht anfassen** (Papierkorb und
|
||||
frühere Fassungen liegen im selben Baum und dürfen nicht übernommen werden –
|
||||
sonst tauchten gelöschte Dateien wieder auf und jede frühere Fassung würde zu
|
||||
einer eigenen Datei), und **nur für Verwalter**.
|
||||
|
||||
### Warum es das überhaupt gibt
|
||||
|
||||
Der GC räumt Dateien weg, zu denen es keinen Eintrag gibt. Für Reste
|
||||
gelöschter Dateien ist das richtig – für eine per SFTP abgelegte Datei ist es
|
||||
falsch: Sie ist in Aether unsichtbar und nach 24 Stunden weg. Der Abgleich ist
|
||||
die Gegenrichtung und macht aus solchen Dateien richtige Einträge.
|
||||
|
||||
Zwei Fallen, die beim Bauen auffielen und die ein Test hier abdecken muss:
|
||||
|
||||
- **Der Dateityp muss aus Endung oder Inhalt kommen.** Beim Hochladen schickt
|
||||
der Browser ihn mit; eine per SFTP abgelegte Datei bringt niemanden mit, der
|
||||
ihn kennt. Dazu kommt: Das Alpine-Abbild hat keine `/etc/mime.types`, und
|
||||
Gos eingebaute Liste kennt nicht einmal `.txt`.
|
||||
- **Prüfsumme nicht überspringen.** Sie kostet einen vollständigen Lesevorgang
|
||||
je Datei, aber ein Eintrag ohne sie ist ein Eintrag, dessen Beschädigung
|
||||
beim Herunterladen niemand bemerkt.
|
||||
|
||||
## Notfall: Migration hängt fest ("Dirty database version")
|
||||
|
||||
Betrifft jede künftige Migration, nicht nur eine bestimmte. Nachgestellt und
|
||||
|
||||
Reference in new issue
Block a user