Ein Husky statt der Krone -- und Spicy sieht DogFather, aber nur ihn
DER HUSKY (screen 1) Filipe: "die krone bei dogfather durch einen husky ersetzen, wie mein logo." Bei 24 Pixeln entscheidet die SILHOUETTE, nicht das Detail. Ein Husky erkennt man an dreierlei, und mehr passt auch nicht hinein: den spitzen aufrechten Ohren, dem breiten Kopf, der nach unten schmal zulaeuft, und der Gesichtsmaske. Fell oder Zunge waeren bei dieser Groesse Matsch -- genau deshalb hat die Krone davor funktioniert. UND ALLE ROLLENSYMBOLE SIND JETZT KOERPER Sie waren reine Konturen in einer Farbe -- daneben auf derselben Seite die Kachelzeichen mit drei Lichtern. Jetzt tragen sie eine gefuellte Flaeche in ihrer Rollenfarbe, die Zeichnung hell darauf, und Augen und Nase eigens gesetzt. Beim gewaehlten Knopf leuchtet die Flaeche staerker -- der einzige Unterschied, den es braucht: mehr Licht auf demselben Gegenstand. SPICY SIEHT DOGFATHER, ABER NICHT DEN ZWEITEN ADMIN (screen 2) Filipe: "die rolle spicy soll auch die rolle dogfather sehen, aber nur dogfather und nicht vanvan." NACHGEMESSEN AM ECHTEN SYSTEM, nicht angenommen: In der Datenbank tragen BEIDE die Rolle `admin` -- id 1 "Dogfather", id 4 "VanVan". Es gibt kein Feld, das den einen vom anderen unterscheidet. Der Unterschied, den es wirklich gibt, ist das Alter: DogFather ist der erste Zugang des Hauses. Deshalb zaehlt die kleinste Nummer unter den Admins -- eine Eigenschaft, die feststeht und nicht am Namen haengt. Die Schwachstelle steht im Code, damit sie niemand sucht: Wuerde Zugang 1 je geloescht, rueckte der naechste nach; dann gehoert ein ausdrueckliches Merkmal in die Tabelle. Die Entscheidung faellt im SERVER, nicht in der Oberflaeche. Dort stand vorher ein Filter, der den ganzen Abschnitt wegnahm -- zwei Regeln fuer dieselbe Frage laufen auseinander, und eine ausgeblendete Zeile hat noch nie etwas geschuetzt. MEINE EIGENEN PRUEFUNGEN VON HEUTE MITTAG FIELEN DABEI Richtig so: Sie pruefen "DogFather steht NICHT darin", und das gilt nicht mehr. Umgeschrieben -- und dabei kam der eigentliche Prueffall dazu: ein ZWEITER Admin-Zugang im Testbestand. Ohne ihn waere die Regel gar nicht pruefbar, bei einem einzigen Admin ist jede Antwort richtig. pruef-spicy von 57 auf 60. NOCH OFFEN aus derselben Nachricht: die Terminarten (BigMatch, Turniere, Special-Live) und der Umbau der Begruessungskachel nach dem Vorbild von VanVans Werktisch. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+25
-5
@@ -213,6 +213,11 @@ for (const z of ausgabe().split(String.fromCharCode(10))) if (z.includes("worksp
|
||||
} catch { erfunden = true; }
|
||||
ok(erfunden, "die Schranke beisst noch -- eine erfundene Rolle wird abgelehnt");
|
||||
const idSpicy = anlegen(s, "Agentur", "spicy", "CODE-SPICY-001");
|
||||
/* EIN ZWEITER ADMIN-ZUGANG. Ohne ihn waere die Regel "Spicy Media
|
||||
sieht DogFather, aber nicht den zweiten Admin" gar nicht pruefbar
|
||||
-- bei einem einzigen Admin ist jede Antwort richtig. Am echten
|
||||
System gibt es zwei (id 1 "Dogfather", id 4 "VanVan"). */
|
||||
anlegen(s, "VanVan", "admin", "CODE-VAN-000001");
|
||||
ok(Number.isInteger(idSpicy) && idSpicy > 0, "'spicy' laesst sich jetzt anlegen");
|
||||
s.close();
|
||||
}
|
||||
@@ -275,9 +280,22 @@ const ruf = async (art, weg, keks, koerper) => {
|
||||
einer Aussage werden drei, und die dritte ist die wichtigste:
|
||||
Ueberblick ist nicht Verwaltung. */
|
||||
ok(status === 200, `die Personenliste ist fuer sie offen (HTTP ${status})`);
|
||||
const listeRollen = (daten?.personen || []).map((x) => x.rolle);
|
||||
ok(listeRollen.length > 0 && !listeRollen.includes("admin"),
|
||||
`und DogFather steht nicht darin (${listeRollen.join(", ") || "leer"})`);
|
||||
/* AM 07.09.2026 PRAEZISIERT. Erst hiess es "DogFather steht nicht
|
||||
darin", dann: "die rolle spicy soll auch die rolle dogfather sehen,
|
||||
aber nur dogfather und nicht vanvan."
|
||||
|
||||
Beide Zugaenge tragen dieselbe Rolle `admin`; unterschieden werden
|
||||
sie ueber das ALTER -- DogFather ist der erste Zugang des Hauses,
|
||||
also die kleinste Nummer. Genau das wird hier gemessen, und der
|
||||
zweite Admin ist der Prueffall: Ohne ihn waere jede Antwort
|
||||
richtig. */
|
||||
const admins = (daten?.personen || []).filter((x) => x.rolle === "admin");
|
||||
ok(admins.length === 1,
|
||||
`genau EIN Admin-Zugang steht in ihrer Liste (${admins.length})`);
|
||||
ok(admins[0]?.id === idDogi,
|
||||
`und zwar der erste, DogFather (${admins[0]?.name || "keiner"})`);
|
||||
ok(!(daten?.personen || []).some((x) => x.name === "VanVan"),
|
||||
"der zweite Admin-Zugang nicht");
|
||||
const prot = await ruf("GET", "/workspace/api/verwaltung/protokoll?anzahl=5", keksSpicy);
|
||||
ok(prot.status === 404, `das Protokoll bleibt zu (HTTP ${prot.status})`);
|
||||
const loeschen = await ruf("DELETE", `/workspace/api/verwaltung/personen/${idLuna}`, keksSpicy);
|
||||
@@ -507,8 +525,10 @@ console.log("\n=== Die Anmeldeseite ===");
|
||||
const abschnitteSpicy = await seite.$$eval(".gruppe__name, .gruppe__kopf",
|
||||
(k) => k.map((x) => x.textContent.trim()).filter(Boolean));
|
||||
const alsText = abschnitteSpicy.join(" | ");
|
||||
ok(!/DogFather/.test(alsText),
|
||||
`bei ihr fehlt der Abschnitt DogFather (${alsText.slice(0, 70) || "keine Abschnitte"})`);
|
||||
ok(/DogFather/.test(alsText),
|
||||
`bei ihr steht der Abschnitt DogFather (${alsText.slice(0, 70) || "keine Abschnitte"})`);
|
||||
ok(/Manager|Creator|Scout/.test(alsText),
|
||||
"und die uebrigen Abschnitte ebenfalls -- die Liste ist nicht leer");
|
||||
await ctx.close();
|
||||
|
||||
/* GEGENPROBE BEI DOGFATHER: Bei ihm steht der Abschnitt "Spicy Media"
|
||||
|
||||
@@ -139,7 +139,30 @@ personenRouter.get("/workspace/api/verwaltung/personen", (req, res) => {
|
||||
nicht in der Abfrage: Die Abfrage ist lang und wird von mehreren
|
||||
Feldern gelesen; eine zusaetzliche Bedingung mittendrin waere die
|
||||
Stelle, an der beim naechsten Umbau jemand danebengreift. */
|
||||
/* FUER SPICY MEDIA: DOGFATHER JA, DER ZWEITE ADMIN-ZUGANG NEIN.
|
||||
|
||||
Filipe: "die rolle spicy soll auch die rolle dogfather sehen,
|
||||
aber nur dogfather sehen und nicht vanvan."
|
||||
|
||||
In der Datenbank tragen BEIDE die Rolle `admin` -- nachgemessen
|
||||
am laufenden System: id 1 "Dogfather", id 4 "VanVan". Es gibt
|
||||
kein Feld, das den einen vom anderen unterscheidet.
|
||||
|
||||
Der Unterschied, den es WIRKLICH gibt, ist das Alter: DogFather
|
||||
ist der erste Zugang des Hauses. Deshalb zaehlt hier die
|
||||
kleinste Nummer unter den Admins -- eine Eigenschaft, die
|
||||
feststeht und nicht am Namen haengt.
|
||||
|
||||
DIE SCHWACHSTELLE STEHT HIER, damit sie niemand sucht: Wuerde
|
||||
Zugang 1 je geloescht, rueckte der naechste Admin nach. Sollte
|
||||
das eintreten, gehoert stattdessen ein ausdrueckliches Merkmal
|
||||
in die Tabelle -- ein `haupt`-Feld. Solange es genau zwei
|
||||
Admin-Zugaenge gibt und der erste DogFather ist, ist die
|
||||
Nummer die ehrlichste Antwort ohne Datenbankumbau. */
|
||||
const ohne = req.ohneDogFather === true;
|
||||
const hauptAdmin = ohne
|
||||
? (db().prepare("SELECT MIN(id) AS id FROM personen WHERE rolle = 'admin'").get()?.id || 0)
|
||||
: 0;
|
||||
res.json({
|
||||
personen: db().prepare(`
|
||||
SELECT p.id, p.name, p.rolle, p.aktiv, p.erstellt, p.letzter_login,
|
||||
@@ -162,7 +185,7 @@ personenRouter.get("/workspace/api/verwaltung/personen", (req, res) => {
|
||||
LEFT JOIN betreuung b ON b.creator_id = p.id
|
||||
LEFT JOIN scout_zuteilung sz ON sz.scout_id = p.id
|
||||
ORDER BY ${ROLLEN_SORTIERUNG.replace("rolle", "p.rolle")}, p.aktiv DESC, p.name`)
|
||||
.all().filter((z) => !(ohne && z.rolle === "admin")),
|
||||
.all().filter((z) => !(ohne && z.rolle === "admin" && z.id !== hauptAdmin)),
|
||||
/* Wer ueberhaupt als zustaendig eingetragen werden kann.
|
||||
|
||||
Bis zum 31.08.2026 waren das nur Scouts. In der Auswahl stand
|
||||
|
||||
Reference in New Issue
Block a user