DogFather konnte einen zweiten DogFather nicht mehr herabstufen
Gefunden beim Durchsehen der schnellen Pruefungen: pruef-haus-trennung stand auf 60 ok / 6 Fehler. Drei Ursachen, eine davon ein echter Rueckschritt von gestern. --- 1. DER RUECKSCHRITT --------------------------------------------- In darfRolleAendern stand seit gestern: if (person.rolle === "admin") return ziel.rolle !== "admin"; Das macht aus "DogFather ist nicht mehr VERGEBBAR" ein "an einem DogFather ist nichts mehr zu aendern". Ein zweiter Zugang liess sich damit nie wieder zuruecksetzen -- er waere fuer immer DogFather geblieben. Die Pruefung sagte es woertlich: "solange es zwei gibt, darf einer wechseln (403)". Die beiden echten Gefahren haengen woanders und bleiben unberuehrt: Niemand KANN 'admin' vergeben, und der LETZTE DogFather laesst sich nicht herabstufen. --- 2. ZWEI SCHLOESSER FUER DIESELBE TUER --------------------------- Ich hatte gestern `rollenZumAendern` mit 403 VOR die vorhandene Pruefung gesetzt, die mit 400 "Unbekannte Rolle." antwortet. Damit war die Luecke wieder offen, vor der der Kommentar vom 17.09. direkt daneben warnt: Zwei verschiedene Antworten -- "gibt es nicht" gegen "darfst du nicht" -- verraten beim Durchprobieren, WELCHE Rollen existieren. Jetzt eine Regel an einer Stelle. `darfAnlegen` ist dort raus, weil Vergeben und Anlegen seit gestern verschiedene Dinge sind. Gemessen: admin anlegen = aendern (sieben Rollen) spicy anlegen = aendern (vier) hand anlegen = — aendern = modi, gast manager anlegen = creator aendern = — Und die eigene Zeile bekommt jetzt 400 mit einem Satz statt 403: Es ist keine Rechtefrage, sondern eine unsinnige Bitte. --- 3. DREI ERWARTUNGEN, DIE AELTER WAREN ALS DIE REGEL -------------- Die Pruefung verlangte 403, wo seit dem 17.09. 400 richtig ist -- ihre Zeile stammt vom 10.09., sieben Tage aelter als die Regel. Und sie verlangte 404 fuer "die rechte Hand vergibt keine Rolle", was bis vorgestern stimmte. Dabei fiel auf, dass NICHTS geprueft hat, ob die rechte Hand ihre neue Faehigkeit ueberhaupt ausueben kann -- nur, dass sie es nicht darf. Eine Pruefung, die nur das Verbotene misst, laesst offen, ob das Erlaubte geht. Jetzt beide Richtungen: an einer anderen rechten Hand aendert sie nichts (403) und an DogFather erst recht nicht (403) einen Modi macht sie sehr wohl zur Community (200) und es steht so in der Datenbank (gast) eine zweite rechte Hand ernennt sie nicht (400) Nebenbei: `unbekannte_kachel` (gestern eingefuehrt) hatte keinen Satz in meldung.js -- die Kennung waere woertlich auf dem Bildschirm gelandet. pruef-meldungen hatte es gemeldet. Und ein Absturz beim Bauen: `const anlegen = await hole(...)` weiter unten im selben Block verdeckt die gleichnamige Funktion im GANZEN Block, auch oberhalb seiner eigenen Zeile. pruef-haus-trennung: 70 ok, 0 Fehler (vorher 60/6). Dazu gruen: rollen-anlegen 11/0, personen-loeschen 40/0, rechte-umstellen 46/0, verteilen 11/0, meldungen 8/0. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -420,7 +420,13 @@ console.log("=== Personen & Zugaenge ===");
|
||||
const neuCrew = await hole("/workspace/api/verwaltung/personen", { host: CREW,
|
||||
methode: "POST", keks: dogi.keks,
|
||||
rumpf: JSON.stringify({ name: "Testcreator", rolle: "creator" }) });
|
||||
ok(neuCrew.status === 403,
|
||||
/* 400, NICHT 403 (berichtigt 20.09.2026). Diese Erwartung stammt vom
|
||||
10.09.; am 17.09. wurde entschieden, dass eine abgelehnte Rolle
|
||||
IMMER "Unbekannte Rolle." mit 400 bekommt -- egal ob es sie nicht
|
||||
gibt oder ob sie hier nur nicht erlaubt ist. Zwei verschiedene
|
||||
Antworten verraten beim Durchprobieren, WELCHE Rollen existieren.
|
||||
Die Pruefung war sieben Tage aelter als die Regel. */
|
||||
ok(neuCrew.status === 400,
|
||||
`ein Creator laesst sich auf crew. nicht anlegen (${neuCrew.status})`);
|
||||
/* GEGENPROBE: Auf der Agenturadresse geht genau das. Ohne sie hiesse
|
||||
die 403 oben auch dann gruen, wenn Anlegen ueberhaupt kaputt waere. */
|
||||
@@ -499,7 +505,8 @@ console.log("=== Die Rolle aendern ===");
|
||||
Rollen kommen aus derselben Auskunft wie beim Anlegen. */
|
||||
const fremd = await hole(`${weg}/${idModi}/rolle`, { host: CREW, methode: "PUT",
|
||||
keks: dogi.keks, rumpf: JSON.stringify({ rolle: "creator" }) });
|
||||
ok(fremd.status === 403, `auf crew. auch nicht zum Creator (${fremd.status})`);
|
||||
/* Auch hier 400 statt 403 -- gleiche Begruendung wie oben. */
|
||||
ok(fremd.status === 400, `auf crew. auch nicht zum Creator (${fremd.status})`);
|
||||
|
||||
/* SEIT DEM 11.09.2026 LAESST SICH DIE ROLLE NICHT MEHR VERGEBEN.
|
||||
|
||||
@@ -624,9 +631,59 @@ console.log("=== Alle Kategorien ===");
|
||||
const codeVersuch = await hole(`/workspace/api/verwaltung/personen/${idModi}/code`,
|
||||
{ host: CREW, methode: "POST", keks: hand.keks, rumpf: "{}" });
|
||||
ok(codeVersuch.status === 404, `sie kann keinen Code neu setzen (${codeVersuch.status})`);
|
||||
const rolleVersuch = await hole(`/workspace/api/verwaltung/personen/${idModi}/rolle`,
|
||||
/* ROLLEN WECHSELN DARF SIE SEIT DEM 20.09. -- aber nicht alles.
|
||||
|
||||
Filipe: "ich will dass ich da auch die rollen der leute wechseln
|
||||
kann ohne dass ich denen einen neuen account machen muss ...
|
||||
perfektionier das fuer die rolle dogfather und rechte hand. nur
|
||||
die sollen das machen koennen."
|
||||
|
||||
Hier stand `=== 404` ("sie kann gar nichts"). Das war bis zum
|
||||
19.09. richtig. Jetzt werden BEIDE Richtungen gemessen -- eine
|
||||
Pruefung, die nur das Verbotene misst, laesst den Fall offen, dass
|
||||
auch das Erlaubte nicht geht, und genau das faellt niemandem auf,
|
||||
bis sich jemand beschwert.
|
||||
|
||||
Ayla ist an dieser Stelle laengst zur rechten Hand befoerdert
|
||||
(Abschnitt weiter oben) -- deshalb ist sie der Fall "nicht unter
|
||||
sich". */
|
||||
const anEinerHand = await hole(`/workspace/api/verwaltung/personen/${idModi}/rolle`,
|
||||
{ host: CREW, methode: "PUT", keks: hand.keks, rumpf: JSON.stringify({ rolle: "modi" }) });
|
||||
ok(rolleVersuch.status === 404, `und keine Rolle vergeben (${rolleVersuch.status})`);
|
||||
ok(anEinerHand.status === 403,
|
||||
`an einer anderen rechten Hand aendert sie nichts (${anEinerHand.status})`);
|
||||
|
||||
const anDogFather = await hole(`/workspace/api/verwaltung/personen/${idDogi}/rolle`,
|
||||
{ host: CREW, methode: "PUT", keks: hand.keks, rumpf: JSON.stringify({ rolle: "modi" }) });
|
||||
ok(anDogFather.status === 403,
|
||||
`und an DogFather erst recht nicht (${anDogFather.status})`);
|
||||
|
||||
/* UND DIE ANDERE RICHTUNG: Was sie DARF, muss auch gehen. Ohne diese
|
||||
Zeile waere die Sperre oben auch dann gruen, wenn ihr Weg voellig
|
||||
zu waere. */
|
||||
/* DIREKT IN DIE DATENBANK statt ueber `anlegen()`: In diesem Block
|
||||
steht weiter unten ein `const anlegen = await hole(...)`, und das
|
||||
verdeckt die gleichnamige Funktion im ganzen Block -- auch OBERHALB
|
||||
seiner eigenen Zeile. JavaScript nennt das die tote Zone, und sie
|
||||
kostete hier einen Absturz mit der Meldung "Cannot access
|
||||
'anlegen' before initialization". */
|
||||
const frischerModi = (() => {
|
||||
d.prepare("INSERT INTO personen (name, rolle, code_hash, code_salt, code_n, aktiv, erstellt)"
|
||||
+ " VALUES ('Probe-Modi','modi','x','y',1,1,?)").run(jetzt);
|
||||
return d.prepare("SELECT last_insert_rowid() AS id").get().id;
|
||||
})();
|
||||
const anEinemModi = await hole(`/workspace/api/verwaltung/personen/${frischerModi}/rolle`,
|
||||
{ host: CREW, methode: "PUT", keks: hand.keks, rumpf: JSON.stringify({ rolle: "gast" }) });
|
||||
ok(anEinemModi.status === 200,
|
||||
`einen Modi macht sie sehr wohl zur Community (${anEinemModi.status})`);
|
||||
const nachher = d.prepare("SELECT rolle FROM personen WHERE id = ?").get(frischerModi)?.rolle;
|
||||
ok(nachher === "gast", `und es steht so in der Datenbank (${nachher})`);
|
||||
|
||||
/* Eine Rolle, die sie nicht vergeben darf, bleibt zu -- sonst waere
|
||||
"sie darf wechseln" ein Freibrief. */
|
||||
const zuHoch = await hole(`/workspace/api/verwaltung/personen/${frischerModi}/rolle`,
|
||||
{ host: CREW, methode: "PUT", keks: hand.keks, rumpf: JSON.stringify({ rolle: "hand" }) });
|
||||
ok(zuHoch.status === 400,
|
||||
`eine zweite rechte Hand ernennt sie nicht (${zuHoch.status})`);
|
||||
const anlegen = await hole("/workspace/api/verwaltung/personen",
|
||||
{ host: CREW, methode: "POST", keks: hand.keks,
|
||||
rumpf: JSON.stringify({ name: "Nochwer", rolle: "modi" }) });
|
||||
|
||||
@@ -896,12 +896,21 @@ personenRouter.put("/workspace/api/verwaltung/personen/:id/rolle", gleicheHerkun
|
||||
Sie beantwortet drei Fragen auf einmal: nicht die eigene Rolle,
|
||||
nicht DogFather, und fuer die rechte Hand auch keine zweite
|
||||
rechte Hand. */
|
||||
/* DIE EIGENE ZEILE ZUERST -- und mit 400, nicht 403.
|
||||
|
||||
Sie ist keine Rechtefrage, sondern eine unsinnige Bitte: Es
|
||||
gibt niemanden, der sie duerfte. Eine 403 haette hier
|
||||
ausserdem den Fall "der letzte DogFather tritt zurueck"
|
||||
verschluckt, den die Sicherung weiter unten mit einem
|
||||
verstaendlichen Satz beantwortet. */
|
||||
if (person.id === req.person.id) {
|
||||
return res.status(400).json({
|
||||
fehler: "Deine eigene Rolle kannst du nicht ändern. Das muss jemand anderes tun.",
|
||||
});
|
||||
}
|
||||
if (!darfRolleAendern(req.person, person)) {
|
||||
return res.status(403).json({ fehler: "Diese Rolle darfst du nicht ändern." });
|
||||
}
|
||||
if (!rollenZumAendern(req.person).includes(rolle)) {
|
||||
return res.status(403).json({ fehler: "Diese Rolle vergibst du nicht." });
|
||||
}
|
||||
|
||||
/* Dieselbe Auskunft wie beim Anlegen: Wer eine Rolle nicht
|
||||
vergeben darf, darf sie auch nicht zuweisen. Sonst waere das
|
||||
@@ -924,7 +933,26 @@ personenRouter.put("/workspace/api/verwaltung/personen/:id/rolle", gleicheHerkun
|
||||
Rolle." mit 400). Wer durchprobiert, haette daran ablesen
|
||||
koennen, welche Rollen es gibt. Jetzt beide Faelle wortgleich
|
||||
-- wie beim Anlegen. */
|
||||
if (!darfAnlegen(req.person).includes(rolle)) {
|
||||
/* WELCHE ROLLE DARF DIESE PERSON VERGEBEN.
|
||||
|
||||
Hier stand `darfAnlegen`. Das war richtig, solange Vergeben und
|
||||
Anlegen dasselbe waren -- seit dem 20.09. sind sie es nicht
|
||||
mehr: Die rechte Hand darf NIEMANDEN anlegen und trotzdem
|
||||
'modi' und 'gast' vergeben, ein Manager darf einen Creator
|
||||
anlegen und gar keine Rolle vergeben. Gemessen:
|
||||
|
||||
admin anlegen = aendern (sieben Rollen)
|
||||
spicy anlegen = aendern (vier)
|
||||
hand anlegen = — aendern = modi, gast
|
||||
manager anlegen = creator aendern = —
|
||||
|
||||
WORTGLEICH MIT DEM FALL DARUEBER, und das ist Absicht: Zwei
|
||||
verschiedene Antworten -- "Unbekannte Rolle" gegen "die darfst
|
||||
du nicht vergeben" -- verraten beim Durchprobieren, WELCHE
|
||||
Rollen es gibt. Genau davor warnt der Kommentar von 17.09., und
|
||||
eine 403 an dieser Stelle hatte die Luecke am 20.09. kurz
|
||||
wieder aufgemacht. */
|
||||
if (!rollenZumAendern(req.person).includes(rolle)) {
|
||||
return res.status(400).json({ fehler: "Unbekannte Rolle." });
|
||||
}
|
||||
if (person.rolle === rolle) {
|
||||
|
||||
+14
-1
@@ -289,7 +289,20 @@ export function darfRolleAendern(person, ziel) {
|
||||
if (!person || !ziel) return false;
|
||||
if (person.id === ziel.id) return false; // (3)
|
||||
if (!rollenZumAendern(person).length) return false;
|
||||
if (person.rolle === "admin") return ziel.rolle !== "admin";
|
||||
/* DOGFATHER DARF JEDEN ANFASSEN -- auch einen zweiten DogFather.
|
||||
Hier stand `return ziel.rolle !== "admin"`, und das war zu scharf:
|
||||
Es machte aus "DogFather ist nicht mehr VERGEBBAR" ein "an einem
|
||||
DogFather ist nichts mehr zu aendern". Gemessen hat es
|
||||
pruef-haus-trennung -- "solange es zwei gibt, darf einer wechseln"
|
||||
bekam 403 statt 200. Ein zweiter Zugang liess sich damit nicht mehr
|
||||
zurueckstufen; er waere fuer immer DogFather geblieben.
|
||||
|
||||
Die beiden echten Gefahren haengen woanders und bleiben: Niemand
|
||||
KANN 'admin' vergeben (steht nicht in rollenZumAendern), und der
|
||||
LETZTE DogFather laesst sich nicht herabstufen (Sicherung in der
|
||||
Route). Die eigene Zeile ist drei Zeilen darueber schon
|
||||
ausgeschlossen. */
|
||||
if (person.rolle === "admin") return true;
|
||||
/* Spicy Media wie bisher: das ganze Haus ausser DogFather. */
|
||||
if (person.rolle === "spicy") return ziel.rolle !== "admin";
|
||||
if (person.rolle === "hand") {
|
||||
|
||||
@@ -70,6 +70,13 @@
|
||||
+ 'lade die Seite neu.',
|
||||
ungueltig:
|
||||
'Mit der Eingabe stimmt etwas nicht. Sieh die Felder noch einmal durch.',
|
||||
/* Die Kachelfarbe im Chat. Der Fall entsteht nur, wenn die
|
||||
Auswahl aelter ist als die Farbliste -- etwa weil die Seite seit
|
||||
gestern offen liegt. Deshalb sagt der Satz, was zu tun ist, und
|
||||
nicht, was schiefging. */
|
||||
unbekannte_kachel:
|
||||
'Diese Farbe gibt es nicht mehr. Lade die Seite neu und such dir '
|
||||
+ 'eine aus der Liste aus.',
|
||||
|
||||
/* ---- Anmeldung und Zugang ------------------------------------ */
|
||||
nicht_angemeldet:
|
||||
|
||||
Reference in New Issue
Block a user