Spicy Media sieht die Zahlen wieder -- und eine Creator-Liste enthaelt nur Creator
Zwei Dinge, das zweite habe ich nur gefunden, weil das erste eine
Pruefung rot gemacht hat.
1) DIE SPICY-SPERRE IST AUFGEHOBEN.
Filipe: "jetzt soll jede rolle diese kachel sehen. spicy, dogfather,
manager, scout und creator ... der manager scout dogfather oder spicy
koennen eintragen."
Kachel und Tuer hatte ich schon geoeffnet -- es reichte nicht. In
workspace-leistung.js sass eine dritte Schranke, die Spicy Media mit
404 abwies (Rest des Wunsches vom 07.09.). Folge: Die Seite lud, das
Auswahlfeld blieb leer, und es sah aus wie ein Fehler. Drei Schichten
mussten zustimmen, und die dritte stand woanders als die beiden
ersten.
Nebenwirkung, ausdruecklich: Damit stehen im Dashboard wieder
Diamanten, LIVE-Tage und Verweildauer je Creator-Karte. Das war der
zweite Teil der damaligen Entscheidung und faellt mit ihr weg.
Die Pruefung in pruef-spicy wurde nicht geloescht, sondern GEDREHT --
sie schlaegt jetzt an, wenn jemand die Sperre versehentlich wieder
einbaut.
2) EINE LISTE VON CREATOR-NUMMERN ENTHIELT KEINE CREATOR.
Beim Drehen fiel auf: Spicy Media bekam "Agentur, Filipe, Luna, Max,
NeuerCreator, NeuerManager" -- DogFather nur "Luna, NeuerCreator".
Ursache: `ohneVerborgene` schreibt ein `null` ("sieht alles") zu einer
echten Liste aus, sobald es etwas zu verbergen gibt -- zur Liste ALLER
Personen, weil sie nicht wissen kann, wovon "alles" gerade handelt.
Bei DogFather greift das nie (er verbirgt nichts vor sich selbst), bei
Spicy Media schon. Der Aufrufer baut daraus ein `IN (...)` OHNE
Rollenfilter, und damit wurden Manager und Scouts zu Creators.
Repariert an der Wurzel, nicht beim Aufrufer: Es gibt zehn Aufrufer,
und neun richtig plus einen vergessen sieht man nie. Der Name der
Funktion ist das Versprechen -- es wird jetzt dort eingeloest, wo der
Name steht.
AUFGEFALLEN IST ES, WEIL EINE PRUEFUNG DIE BEIDEN LISTEN VERGLICHEN
HAT, statt bei jeder einzeln "ist nicht leer" zu sagen. Genau dieser
Unterschied steht jetzt als eigene Aussage drin.
Gemessen: pruef-backstage-import 50 -> 63 (Manager und Spicy Media
kamen dazu, inklusive der Aussage, dass Spicy Media MEHR Creator sieht
als ein Manager), pruef-spicy 60 -> 62. Dazu gruen: betreuung,
manager-sicht, verborgen, haus-trennung, sicht, aufgabenbrett,
schulung, steckbrief, uebersicht, leistung, tiktok-datei,
fremde-sicht, personen-liste, creator-anlegen, ampel, tagesblick.
NICHT von mir: pruef-agentur meldet 31 Fehler (HTTP 503). Gegen den
Stand ohne meine Aenderungen nachgemessen -- dort dieselben 31. Ein
aelterer, eigener Befund, unangetastet.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -72,7 +72,7 @@ await starten();
|
||||
kind.kill();
|
||||
await new Promise((r) => setTimeout(r, 600));
|
||||
|
||||
let idNova, idKiro, idLumi, idSam;
|
||||
let idNova, idKiro, idLumi, idSam, idMira;
|
||||
{
|
||||
const d = new DatabaseSync(DB);
|
||||
const anlegen = (name, rolle, code, tiktok) => {
|
||||
@@ -85,6 +85,12 @@ let idNova, idKiro, idLumi, idSam;
|
||||
};
|
||||
anlegen("Filipe", "admin", "CODE-DOGI-0001");
|
||||
idSam = anlegen("Sam", "scout", "CODE-SAM-00001");
|
||||
/* Seit dem 11.09.2026 kommen auch Manager und Spicy Media auf diese
|
||||
Seite. Beide sehen andere Creator als ein Scout -- Spicy Media
|
||||
alle (siehtAlles), ein Manager nur seine eigenen und die seiner
|
||||
Scouts. Ohne beide im Bestand waere das ungeprueft. */
|
||||
idMira = anlegen("Mira", "manager", "CODE-MIRA-0001");
|
||||
anlegen("Sasha", "spicy", "CODE-SASHA-0001");
|
||||
/* Nova hat ein Handle, Kiro NICHT -- er wird ueber den Namen
|
||||
gefunden. Lumi hat ein Handle mit anderer Schreibweise als in der
|
||||
Tabelle: Genau daran zeigt sich, ob normalisiert wird. */
|
||||
@@ -98,6 +104,11 @@ let idNova, idKiro, idLumi, idSam;
|
||||
einem Zufall. */
|
||||
d.prepare("INSERT INTO betreuung (creator_id, betreuer_id, seit) VALUES (?,?,?)")
|
||||
.run(idNova, idSam, jetzt);
|
||||
/* Und Sam gehoert zu Mira -- damit der Manager ueber seinen Scout
|
||||
an Nova kommt. Sonst saehe er eine leere Seite, und die Pruefung
|
||||
unten wuerde messen, dass nichts da ist, statt dass es stimmt. */
|
||||
d.prepare("INSERT INTO scout_zuteilung (scout_id, manager_id, seit) VALUES (?,?,?)")
|
||||
.run(idSam, idMira, jetzt);
|
||||
d.close();
|
||||
}
|
||||
await starten();
|
||||
@@ -275,6 +286,21 @@ console.log("\n=== Gegenproben ===");
|
||||
ok(status === 200, `heute als Tag geht dagegen durch (HTTP ${status})`);
|
||||
}
|
||||
|
||||
/* WER SIEHT WEN -- direkt an der Schnittstelle gemessen, bevor der
|
||||
Browser ins Spiel kommt. Wird der Auswahlliste auf der Seite etwas
|
||||
fehlen, steht hier, ob es schon hier fehlte. */
|
||||
for (const [rolle, code, wer] of [
|
||||
["manager", "CODE-MIRA-0001", "über seinen Scout"],
|
||||
["spicy", "CODE-SASHA-0001", "alle"],
|
||||
]) {
|
||||
const keks = await anmelden(rolle, code);
|
||||
const a = await fetch(BASIS + "/workspace/api/leistung", { headers: { Cookie: keks } });
|
||||
const d = await a.json().catch(() => ({}));
|
||||
const namen = (d.creator || []).map((c) => c.name).join(", ");
|
||||
ok(a.status === 200 && namen.length > 0,
|
||||
`${rolle} bekommt Creator (${wer}): ${namen || `LEER, HTTP ${a.status}`}`);
|
||||
}
|
||||
|
||||
/* Vorbedingung fuer die Gegenprobe weiter unten: Sam MUSS Nova sehen.
|
||||
Sonst waere "der Scout sieht den Backstage-Satz nicht" nur die
|
||||
Auskunft, dass seine Seite leer ist. */
|
||||
@@ -444,6 +470,39 @@ console.log("\n=== Die Seite ===");
|
||||
ok(scoutBild.aendern > 0,
|
||||
`er kann einen Tag eintragen (${scoutBild.aendern} Knöpfe in der Liste)`);
|
||||
|
||||
/* MANAGER UND SPICY MEDIA -- die beiden, die ich beinahe nur
|
||||
mitgedacht haette. Sie gehoeren zur Leitung, also sollten sie
|
||||
alles koennen; "sollte" ist aber kein Messwert. Sie sehen
|
||||
ausserdem UNTERSCHIEDLICH viele Creator: Spicy Media alle
|
||||
(siehtAlles), ein Manager nur seine eigenen und die seiner
|
||||
Scouts. Genau das wird hier verglichen -- eine Pruefung, die bei
|
||||
beiden nur "sieht etwas" sagt, haette den Unterschied nie
|
||||
bemerkt. */
|
||||
for (const [rolle, code, mindestens] of [
|
||||
["manager", "CODE-MIRA-0001", 1],
|
||||
["spicy", "CODE-SASHA-0001", 3],
|
||||
]) {
|
||||
const b = await rollenBild(rolle, code);
|
||||
ok(b.kachel === true && /leistung\.html$/.test(b.weg),
|
||||
`${rolle}: findet die Kachel und kommt auf die Seite`);
|
||||
ok(b.fehler === "", `${rolle}: kein Skriptfehler (${b.fehler || "keiner"})`);
|
||||
ok(b.netz === false && b.tt === false && b.import === false && b.ziele === false,
|
||||
`${rolle}: alle vier Wege sind da -- auch die Backstage-Tabelle`);
|
||||
ok(b.sNetz === false && b.sTt === false,
|
||||
`${rolle}: und beide Erklärungen dazu`);
|
||||
ok(b.wahl >= mindestens,
|
||||
`${rolle}: sieht ${b.wahl} Creator zur Auswahl (mindestens ${mindestens})`);
|
||||
}
|
||||
/* Und der Unterschied selbst, als eigene Aussage: Spicy Media sieht
|
||||
MEHR als der Manager. Waeren beide gleich, waere oben alles gruen
|
||||
und die Haustrennung trotzdem kaputt. */
|
||||
{
|
||||
const m = await rollenBild("manager", "CODE-MIRA-0001");
|
||||
const sp = await rollenBild("spicy", "CODE-SASHA-0001");
|
||||
ok(sp.wahl > m.wahl,
|
||||
`Spicy Media sieht mehr Creator als der Manager (${sp.wahl} zu ${m.wahl})`);
|
||||
}
|
||||
|
||||
const creatorBild = await rollenBild("creator", "CODE-NOVA-0001");
|
||||
ok(creatorBild.kachel === true && /leistung\.html$/.test(creatorBild.weg),
|
||||
`der Creator findet die Kachel und kommt auf die Seite (${creatorBild.weg})`);
|
||||
|
||||
+22
-9
@@ -455,20 +455,33 @@ const ruf = async (art, weg, keks, koerper) => {
|
||||
`DogFather sieht weiterhin beide (${dTitel.length})`);
|
||||
}
|
||||
{
|
||||
/* DIE ZAHLEN SIEHT SIE NIRGENDS (07.09.2026).
|
||||
/* DIE ZAHLEN SIEHT SIE WIEDER (11.09.2026) -- umgedreht.
|
||||
|
||||
Zuerst waren nur Kachel und Seite geschlossen -- die Creator-Zahlen
|
||||
standen damit weiterhin im Dashboard, weil das sie ueber eine
|
||||
eigene Schnittstelle holt. Filipe hat entschieden, dass auch das
|
||||
weg soll.
|
||||
Vom 07.09. bis heute stand hier das Gegenteil: Die Schnittstelle
|
||||
antwortete ihr mit 404, nach Filipes Wunsch "bei der spicy rolle,
|
||||
die zahlen diese kategorie nicht sehen". Am 11.09. hat er das
|
||||
aufgehoben: "jetzt soll jede rolle diese kachel sehen. spicy,
|
||||
dogfather, manager, scout und creator."
|
||||
|
||||
Geprueft wird die SCHNITTSTELLE und nicht die Oberflaeche: Eine
|
||||
ausgeblendete Zeile ist keine Sperre. Und mit Gegenprobe, sonst
|
||||
bewiese die Zeile nur, dass es den Weg gar nicht gibt. */
|
||||
DIE PRUEFUNG WURDE NICHT GELOESCHT, SONDERN GEDREHT. Eine
|
||||
entfernte Pruefung senkt die Zahl und beweist nichts; eine
|
||||
gedrehte haelt fest, dass die Entscheidung bewusst war -- und
|
||||
schlaegt an, wenn jemand die Sperre versehentlich wieder
|
||||
einbaut.
|
||||
|
||||
Geprueft wird die SCHNITTSTELLE und nicht die Oberflaeche: Ein
|
||||
eingeblendeter Knopf ist kein Zugang. Und mit Gegenprobe, sonst
|
||||
bewiese die Zeile nur, dass irgendetwas antwortet. */
|
||||
const beiIhr = await ruf("GET", "/workspace/api/leistung", keksSpicy);
|
||||
ok(beiIhr.status === 404, `die Zahlen antworten ihr mit 404 (${beiIhr.status})`);
|
||||
ok(beiIhr.status === 200, `die Zahlen antworten ihr wieder (${beiIhr.status})`);
|
||||
ok((beiIhr.daten?.creator || []).length > 0,
|
||||
`und sie bekommt auch Creator dabei (${(beiIhr.daten?.creator || []).length})`);
|
||||
const beiIhm = await ruf("GET", "/workspace/api/leistung", keksDogi);
|
||||
ok(beiIhm.status === 200, `DogFather bekommt sie weiterhin (${beiIhm.status})`);
|
||||
const ihre = (beiIhr.daten?.creator || []).map((c) => c.name).sort().join(",");
|
||||
const seine = (beiIhm.daten?.creator || []).map((c) => c.name).sort().join(",");
|
||||
ok(ihre === seine,
|
||||
`und beide sehen dieselben -- Spicy Media sieht alles, wie DogFather (sie: ${ihre || "keine"} | er: ${seine || "keine"})`);
|
||||
|
||||
/* UND DAS DASHBOARD BLEIBT FUER SIE STEHEN. Das ist der eigentliche
|
||||
Prueffall: Die Uebersicht holt die Zahlen in einer zusaetzlichen
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
import express from "express";
|
||||
import {
|
||||
db, protokolliere, echteIp, sitzungLesen, istLeitung, istSpicy,
|
||||
db, protokolliere, echteIp, sitzungLesen, istLeitung,
|
||||
sichtbareCreatorIds, ROLLEN_SORTIERUNG, heuteLokal,
|
||||
} from "./workspace.js";
|
||||
import { kandidatenFinden, listeAmPfad, zuTagen } from "./workspace-tiktok-datei.js";
|
||||
@@ -74,32 +74,33 @@ function gleicheHerkunft(req, res, next) {
|
||||
|
||||
leistungRouter.use("/workspace/api/leistung", angemeldet);
|
||||
|
||||
/* SPICY MEDIA SIEHT DIE ZAHLEN NIRGENDS (07.09.2026).
|
||||
/* ---------- Die Spicy-Sperre von 07.09.2026 ist aufgehoben ----------
|
||||
(11.09.2026) Filipe, mit der Zahlen-Kachel im Bild: "jetzt soll jede
|
||||
rolle diese kachel sehen. spicy, dogfather, manager, scout und
|
||||
creator ... der manager scout dogfather oder spicy koennen
|
||||
eintragen."
|
||||
|
||||
Filipe: "bei der spicy rolle, die zahlen diese kategorie nicht
|
||||
sehen." Zuerst habe ich woertlich nur die KATEGORIE geschlossen --
|
||||
Kachel und Seite. Auf Nachfrage, was noch offen sei, habe ich selbst
|
||||
darauf hingewiesen, dass die Creator-Zahlen damit weiterhin im
|
||||
Dashboard stehen (Diamanten, LIVE-Tage, Verweildauer je Karte);
|
||||
Filipe hat entschieden, dass auch das weg soll.
|
||||
Hier stand bis heute eine Sperre, die Spicy Media mit 404
|
||||
abgewiesen hat -- der Rest des Wunsches vom 07.09. ("bei der spicy
|
||||
rolle, die zahlen diese kategorie nicht sehen"). Sie sass
|
||||
ausdruecklich am Server und nicht in der Oberflaeche, und genau
|
||||
deshalb reichte es heute NICHT, Kachel und Tuer zu oeffnen: Die
|
||||
Seite lud, das Auswahlfeld blieb leer, und es sah aus wie ein
|
||||
Fehler.
|
||||
|
||||
DIE SPERRE SITZT AM SERVER UND NICHT IN DER OBERFLAECHE. Eine
|
||||
ausgeblendete Zeile ist keine Sperre: Wer die Adresse kennt, ruft
|
||||
die Schnittstelle direkt auf. Hier kommt sie gar nicht mehr an
|
||||
Daten.
|
||||
GEFUNDEN HAT DAS EINE MESSUNG, NICHT DAS LESEN. Ich hatte Kachel
|
||||
und Tuer geaendert und haette es dabei belassen; erst die Pruefung
|
||||
mit Spicy-Zugang zeigte "0 Creator zur Auswahl" und dahinter das
|
||||
404. Drei Schichten mussten zustimmen, und die dritte stand
|
||||
woanders als die beiden ersten.
|
||||
|
||||
404 statt 403, wie ueberall in diesem Haus: Wer nicht hierher
|
||||
gehoert, muss nicht erfahren, dass es diesen Bereich gibt.
|
||||
NEBENWIRKUNG, ausdruecklich: Damit stehen auch im Dashboard wieder
|
||||
Diamanten, LIVE-Tage und Verweildauer je Creator-Karte. Das war der
|
||||
zweite Teil der damaligen Entscheidung und faellt mit ihr weg.
|
||||
|
||||
DAS DASHBOARD BRICHT DADURCH NICHT. Es holt die Zahlen in EINER
|
||||
zusaetzlichen Abfrage und faengt ihren Fehlschlag ausdruecklich ab
|
||||
("die Karten stehen auch ohne", uebersicht.js) -- bei ihr fehlen
|
||||
also die drei Zeilen, alles andere bleibt. Genau deshalb ist diese
|
||||
eine Zeile hier der ganze Eingriff. */
|
||||
leistungRouter.use("/workspace/api/leistung", (req, res, next) => {
|
||||
if (istSpicy(req.person)) return res.status(404).json({ fehler: "nicht_gefunden" });
|
||||
next();
|
||||
});
|
||||
Was die Zeile NICHT war: eine Rechteregel. Wessen Zahlen Spicy
|
||||
Media sieht, entscheidet weiterhin siehtAlles() -- und das sagt
|
||||
seit jeher "alle". */
|
||||
|
||||
/* ---------- Wer darf was ------------------------------------------------ */
|
||||
|
||||
|
||||
+32
-1
@@ -4750,7 +4750,38 @@ export function hausBedingung(person, spalte = "rolle") {
|
||||
return ` AND ${spalte} IN (${liste})`;
|
||||
}
|
||||
|
||||
export const sichtbareCreatorIds = (person) => nurHaus(ohneVerborgene(sichtbareCreatorIdsRoh(person), person), person);
|
||||
/* EINE LISTE VON CREATOR-NUMMERN DARF NUR CREATOR ENTHALTEN (11.09.2026).
|
||||
|
||||
Klingt selbstverstaendlich, war es nicht. `ohneVerborgene` schreibt
|
||||
ein `null` ("sieht alles") zu einer echten Liste aus, sobald es etwas
|
||||
zu verbergen gibt -- und zwar zur Liste ALLER Personen, weil sie
|
||||
nicht wissen kann, wovon "alles" gerade handelt. Fuer DogFather
|
||||
greift das nie (er verbirgt nichts vor sich selbst), fuer Spicy
|
||||
Media schon: Bei ihr kam die Liste mit Admins, Managern und Scouts
|
||||
darin zurueck.
|
||||
|
||||
GEMESSEN, NICHT VERMUTET: Am 11.09.2026 bekam Spicy Media auf der
|
||||
Zahlen-Seite "Agentur, Filipe, Luna, Max, NeuerCreator,
|
||||
NeuerManager" zur Auswahl -- DogFather dagegen nur "Luna,
|
||||
NeuerCreator". Aufgefallen ist es, weil eine Pruefung die beiden
|
||||
Listen VERGLICHEN hat, statt bei jeder einzeln "ist nicht leer" zu
|
||||
sagen.
|
||||
|
||||
WARUM DIE REPARATUR HIER STEHT UND NICHT BEIM AUFRUFER: Es gibt
|
||||
zehn Aufrufer. Jeder von ihnen baut daraus ein `IN (...)`, und jeder
|
||||
haette die Rolle selbst danebenschreiben muessen -- neun Stellen
|
||||
richtig und eine vergessen sieht man nie. Der Name der Funktion ist
|
||||
das Versprechen; es gehoert dorthin eingeloest, wo der Name steht. */
|
||||
const nurCreatorIds = (ids) => {
|
||||
if (ids === null || !ids.length) return ids;
|
||||
try {
|
||||
return db().prepare(
|
||||
`SELECT id FROM personen WHERE rolle = 'creator' AND id IN (${ids.map(() => "?").join(",")})`)
|
||||
.all(...ids).map((z) => z.id);
|
||||
} catch { return ids; }
|
||||
};
|
||||
|
||||
export const sichtbareCreatorIds = (person) => nurCreatorIds(nurHaus(ohneVerborgene(sichtbareCreatorIdsRoh(person), person), person));
|
||||
export const sichtbarePersonenIds = (person) => nurHaus(ohneVerborgene(sichtbarePersonenIdsRoh(person), person), person);
|
||||
export const betreuerIds = (person) => nurHaus(ohneVerborgene(betreuerIdsRoh(person), person), person);
|
||||
export const einladbareIds = (person) => nurHaus(ohneVerborgene(einladbareIdsRoh(person), person), person);
|
||||
|
||||
Reference in New Issue
Block a user