diff --git a/server/pruef-haus-trennung.mjs b/server/pruef-haus-trennung.mjs index e051565c..dec18a2e 100644 --- a/server/pruef-haus-trennung.mjs +++ b/server/pruef-haus-trennung.mjs @@ -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" }) }); diff --git a/server/workspace-personen.js b/server/workspace-personen.js index 313848c8..c6ffcd2c 100644 --- a/server/workspace-personen.js +++ b/server/workspace-personen.js @@ -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) { diff --git a/server/workspace.js b/server/workspace.js index e4bf2722..4de4050d 100644 --- a/server/workspace.js +++ b/server/workspace.js @@ -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") { diff --git a/workspace/assets/js/meldung.js b/workspace/assets/js/meldung.js index c935d9a1..27f9870a 100644 --- a/workspace/assets/js/meldung.js +++ b/workspace/assets/js/meldung.js @@ -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: