Spicy Media legt Manager UND Scouts an -- eine Liste statt vier
Filipe, mit Bildschirmfoto der Zugaenge-Seite: "die spicy rolle soll auch manager und scouts hinzufuegen koennen." DER MANAGER-KNOPF FEHLTE NICHT AUS RECHTEGRUENDEN. Serverseitig war die Tuer /workspace/api/manager-anlegen fuer Spicy Media die ganze Zeit offen. Es gab nur nichts zum Draufdruecken -- wegen ZWEIER Listen in derselben Funktion, drei Zeilen auseinander (personen.js): const darf = ... spicy ? ['manager', 'creator'] : ['creator']; ... if ((r.wert === 'admin' || r.wert === 'manager') && ich.rolle !== 'admin') continue; Die erste erlaubt den Manager, die zweite nimmt ihn wieder weg. Uebrig blieb ein einziger Knopf: Creator. Nichts war kaputt, nichts wurde rot, es fehlte einfach -- die Sorte Fehler, die nur jemandem auffaellt, der davorsitzt. FUER SCOUTS GAB ES UEBERHAUPT KEINE TUER. Nur DogFather konnte welche anlegen. Und die Wegwahl in der Oberflaeche war eine Kette mit Auffangbecken (`rolle === 'manager' ? ... : creator-anlegen`): Ein Scout waere im else gelandet, und creator-anlegen legt IMMER einen Creator an. Der Knopf haette Erfolg gemeldet und das Falsche getan. DIE ANTWORT STEHT JETZT AN EINER STELLE. `darfAnlegen` in workspace.js sagt, wer wen anlegen darf. Daraus lesen: - die beiden Team-Tueren (Manager, Scout) - die allgemeine Verwaltungs-Tuer von DogFather - die Oberflaeche, ueber `darf_anlegen` in /workspace/api/ich Die Oberflaeche hat damit gar keine eigene Liste mehr und kann deshalb auch nicht mehr abweichen -- weder zu streng noch zu grosszuegig. ZWEI TUEREN, NICHT EINE MIT EINEM ROLLENFELD. Der Absatz an der Manager-Tuer raet davon ab, und der Rat gilt: Eine Tuer, die NICHTS anderes kann, als eine bestimmte Rolle anzulegen, ist sicherer als eine, die vorher nachfragt. `teamTuer(rolle)` baut beide aus demselben Text -- die Rolle wird beim Einhaengen festgelegt und kommt nie aus dem Aufruf. Geprueft: ein mitgeschicktes "rolle: admin" bleibt wirkungslos. GEPRUEFT (pruef-creator-anlegen, 33 -> 49 Pruefungen) - Spicy Media legt Manager an -> 201, Rolle stimmt - Spicy Media legt Scout an -> 201, Rolle stimmt - "rolle: admin" mitgeschickt -> wirkungslos, es wird ein Scout - ein Manager durch die Scout-Tuer -> 404 - ein Scout durch die Scout-Tuer -> 404 - Personenliste lesen -> 200 (die eine gewollte Ausnahme) - darueber anlegen -> 404, und es entsteht niemand - /api/ich nennt Spicy: manager, scout, creator -- und keinen DogFather - ein Manager bekommt genau eine Rolle genannt, ein Scout keine - die Knoepfe auf der Seite stimmen mit alldem ueberein - DogFather sieht unveraendert alle -- gemessen, nicht geglaubt Der erste Anlauf der Pruefung behauptete, Spicy Media komme gar nicht an /workspace/api/verwaltung. Falsch, und sie wurde zu Recht rot: nurAdmin laesst genau einen Fall durch, das LESEN der Personenliste. Diese Trennung ist jetzt festgenagelt. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -97,6 +97,9 @@ let idDogi, idMax, idMia, idScoutMax, idScoutMia, idCreator;
|
||||
idScoutMax = anlegen(d, "SamVonMax", "scout", "CODE-SAM-00001");
|
||||
idScoutMia = anlegen(d, "TimVonMia", "scout", "CODE-TIM-00001");
|
||||
idCreator = anlegen(d, "Luna", "creator", "CODE-LUNA-0001");
|
||||
/* Seit dem 10.09.2026 gehoert Spicy Media dazu: Sie darf Manager UND
|
||||
Scouts anlegen, und genau das steht im Abschnitt 6. */
|
||||
anlegen(d, "Agentur", "spicy", "CODE-SPIC-0001");
|
||||
d.prepare("INSERT INTO scout_zuteilung (scout_id, manager_id, seit) VALUES (?,?,?)")
|
||||
.run(idScoutMax, idMax, jetzt);
|
||||
d.prepare("INSERT INTO scout_zuteilung (scout_id, manager_id, seit) VALUES (?,?,?)")
|
||||
@@ -118,6 +121,7 @@ const keksMax = await anmelden("manager", "CODE-MAX-00001");
|
||||
const keksMia = await anmelden("manager", "CODE-MIA-00001");
|
||||
const keksScout = await anmelden("scout", "CODE-SAM-00001");
|
||||
const keksLuna = await anmelden("creator", "CODE-LUNA-0001");
|
||||
const keksSpicy = await anmelden("spicy", "CODE-SPIC-0001");
|
||||
|
||||
const ruf = async (art, weg, keks, koerper) => {
|
||||
const a = await fetch(BASIS + weg, { method: art,
|
||||
@@ -301,6 +305,145 @@ console.log("\n=== Der Knopf auf dem Dashboard ===");
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
6. SPICY MEDIA LEGT MANAGER UND SCOUTS AN (10.09.2026)
|
||||
|
||||
Filipe, mit Bildschirmfoto: "die spicy rolle soll auch manager und
|
||||
scouts hinzufuegen koennen."
|
||||
|
||||
Der Fehler davor war kein fehlendes Recht, sondern ZWEI Listen, die
|
||||
einander widersprachen: Die Oberflaeche erlaubte Spicy Media in einer
|
||||
Zeile den Manager und nahm ihn drei Zeilen spaeter wieder weg. Fuer
|
||||
Scouts gab es ueberhaupt keine Tuer.
|
||||
|
||||
Deshalb wird hier BEIDES geprueft — dass es geht, und dass die
|
||||
Oberflaeche dieselbe Antwort bekommt wie der Server. Eine der beiden
|
||||
Pruefungen allein haette den Fehler nicht gefunden: Serverseitig war
|
||||
der Manager ja die ganze Zeit erlaubt.
|
||||
======================================================================= */
|
||||
console.log("\n=== Spicy Media legt Manager und Scouts an ===");
|
||||
{
|
||||
const { status, daten } = await ruf("POST", "/workspace/api/manager-anlegen",
|
||||
keksSpicy, { name: "NeuerManager" });
|
||||
ok(status === 201, `ein Manager entsteht (HTTP ${status})`);
|
||||
ok(daten?.rolle === "manager", `und ist wirklich ein Manager (${daten?.rolle})`);
|
||||
}
|
||||
{
|
||||
const { status, daten } = await ruf("POST", "/workspace/api/scout-anlegen",
|
||||
keksSpicy, { name: "NeuerScout" });
|
||||
ok(status === 201, `ein Scout entsteht (HTTP ${status})`);
|
||||
/* DIE ROLLE IST HIER DER GANZE PUNKT. Vor dem Umbau waere die
|
||||
Oberflaeche mit "scout" beim Creator-Weg gelandet, und der legt
|
||||
IMMER einen Creator an -- der Knopf haette Erfolg gemeldet und das
|
||||
Falsche getan. */
|
||||
ok(daten?.rolle === "scout", `und ist wirklich ein Scout (${daten?.rolle})`);
|
||||
}
|
||||
{
|
||||
/* Die Rolle kommt NICHT aus dem Aufruf: Wer sie mitschickt, aendert
|
||||
nichts. Die Tuer kennt genau eine. */
|
||||
const { status, daten } = await ruf("POST", "/workspace/api/scout-anlegen",
|
||||
keksSpicy, { name: "MoechtegernChef", rolle: "admin" });
|
||||
ok(status === 201 && daten?.rolle === "scout",
|
||||
`ein mitgeschicktes "rolle: admin" bleibt wirkungslos (${daten?.rolle})`);
|
||||
}
|
||||
{
|
||||
const { status } = await ruf("POST", "/workspace/api/scout-anlegen",
|
||||
keksMax, { name: "ScoutVonMax" });
|
||||
ok(status === 404, `ein Manager kommt durch diese Tuer nicht (HTTP ${status})`);
|
||||
}
|
||||
{
|
||||
const { status } = await ruf("POST", "/workspace/api/scout-anlegen",
|
||||
keksScout, { name: "ScoutVomScout" });
|
||||
ok(status === 404, `ein Scout auch nicht (HTTP ${status})`);
|
||||
}
|
||||
/* DIE AUSNAHME, DIE ES WIRKLICH GIBT — und ihre Grenze.
|
||||
|
||||
Erster Anlauf dieser Pruefung behauptete, Spicy Media komme gar nicht
|
||||
an /workspace/api/verwaltung. Das war falsch, und die Pruefung wurde
|
||||
zu Recht rot: `nurAdmin` laesst genau EINEN Fall durch, das LESEN der
|
||||
Personenliste ("spicy soll genau das sehen koennen"). Ueberblick ist
|
||||
nicht Verwaltung — und genau diese Trennung gehoert festgenagelt,
|
||||
sonst weitet sie sich beim naechsten Umbau unbemerkt aus. */
|
||||
{
|
||||
const { status } = await ruf("GET", "/workspace/api/verwaltung/personen", keksSpicy);
|
||||
ok(status === 200, `die Personenliste darf Spicy Media LESEN (HTTP ${status})`);
|
||||
}
|
||||
{
|
||||
const { status } = await ruf("POST", "/workspace/api/verwaltung/personen",
|
||||
keksSpicy, { name: "AufDemKurzenWeg", rolle: "admin" });
|
||||
ok(status === 404, `aber nicht darueber anlegen (HTTP ${status})`);
|
||||
const z = new DatabaseSync(DB).prepare(
|
||||
"SELECT rolle FROM personen WHERE name = ?").get("AufDemKurzenWeg");
|
||||
ok(!z, "und es entsteht dabei auch niemand");
|
||||
}
|
||||
|
||||
/* ---- Und die Oberflaeche fragt dieselbe Stelle ---------------------- */
|
||||
{
|
||||
const { daten } = await ruf("GET", "/workspace/api/ich", keksSpicy);
|
||||
const darf = daten?.darf_anlegen || [];
|
||||
ok(darf.includes("manager") && darf.includes("scout") && darf.includes("creator"),
|
||||
`/api/ich nennt Spicy Media: ${darf.join(", ")}`);
|
||||
/* DAS WICHTIGERE: was NICHT drinsteht. Ein Knopf zu viel waere hier
|
||||
schlimmer als einer zu wenig -- er verspraeche ein Recht, das es
|
||||
nicht gibt. */
|
||||
ok(!darf.includes("admin"), "und keinen DogFather");
|
||||
}
|
||||
{
|
||||
const { daten } = await ruf("GET", "/workspace/api/ich", keksMax);
|
||||
const darf = daten?.darf_anlegen || [];
|
||||
ok(darf.length === 1 && darf[0] === "creator",
|
||||
`ein Manager bekommt genau eine Rolle genannt: ${darf.join(", ") || "keine"}`);
|
||||
}
|
||||
{
|
||||
const { daten } = await ruf("GET", "/workspace/api/ich", keksScout);
|
||||
const darf = daten?.darf_anlegen || [];
|
||||
ok(darf.length === 0, `ein Scout bekommt keine genannt (${darf.length})`);
|
||||
}
|
||||
|
||||
/* ---- Die Knoepfe auf der Zugaenge-Seite ----------------------------- */
|
||||
console.log("\n=== Die Rollenknoepfe auf der Zugaenge-Seite ===");
|
||||
{
|
||||
const pw = await import("file:///C:/Users/qciga/Documents/Obelix/Analyse/node_modules/playwright/index.mjs");
|
||||
const browser = await pw.chromium.launch();
|
||||
const knoepfeFuer = async (rolle, code) => {
|
||||
const ctx = await browser.newContext({ viewport: { width: 1400, height: 900 } });
|
||||
const seite = await ctx.newPage();
|
||||
await seite.goto(BASIS + "/workspace/", { waitUntil: "networkidle" });
|
||||
await seite.click(`.rolle[data-rolle="${rolle}"]`);
|
||||
await seite.fill("#code", code);
|
||||
await seite.click("button[type=submit]");
|
||||
await seite.waitForURL("**/start.html", { timeout: 25000 });
|
||||
await seite.goto(BASIS + "/workspace/personen.html", { waitUntil: "networkidle" });
|
||||
await seite.waitForTimeout(1600);
|
||||
const liste = await seite.$$eval(".rollenwahl__knopf",
|
||||
(ks) => ks.map((k) => k.dataset.rolle)).catch(() => []);
|
||||
await ctx.close();
|
||||
return liste;
|
||||
};
|
||||
const spicy = await knoepfeFuer("spicy", "CODE-SPIC-0001");
|
||||
ok(spicy.includes("manager"), `Spicy Media sieht den Manager-Knopf (${spicy.join(", ")})`);
|
||||
ok(spicy.includes("scout"), "und den Scout-Knopf");
|
||||
ok(spicy.includes("creator"), "und den Creator-Knopf");
|
||||
ok(!spicy.includes("admin"), "aber keinen DogFather-Knopf");
|
||||
/* GEGENPROBE: Die Zaehlung erkennt einen fehlenden Knopf wirklich.
|
||||
Beim Manager MUSS genau einer stehen -- stuenden dort drei, waere
|
||||
die Messung oben wertlos. */
|
||||
const managerKnoepfe = await knoepfeFuer("manager", "CODE-MAX-00001");
|
||||
ok(managerKnoepfe.length === 1 && managerKnoepfe[0] === "creator",
|
||||
`ein Manager sieht genau einen: ${managerKnoepfe.join(", ")}`);
|
||||
/* UND BEI DOGFATHER AENDERT SICH NICHTS. Er bekommt jetzt eine
|
||||
laengere Liste vom Server (auch die verborgenen Rollen), die
|
||||
Knopfliste der Seite kennt aber nur die fuenf sichtbaren -- der
|
||||
Schnitt der beiden ist derselbe wie vorher. Das ist eine Behauptung
|
||||
ueber MEINE Aenderung, also gehoert sie gemessen und nicht
|
||||
geglaubt. */
|
||||
const dogiKnoepfe = await knoepfeFuer("admin", "CODE-DOGI-0001");
|
||||
ok(dogiKnoepfe.length >= 5 && ["spicy", "admin", "manager", "scout", "creator"]
|
||||
.every((r) => dogiKnoepfe.includes(r)),
|
||||
`DogFather sieht weiterhin alle fuenf: ${dogiKnoepfe.join(", ")}`);
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
kind.kill();
|
||||
await new Promise((r) => setTimeout(r, 400));
|
||||
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* Zugabe */ }
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
import express from "express";
|
||||
import {
|
||||
db, protokolliere, echteIp, sitzungLesen, personAnlegen, codeNeu, sitzungToken, personSperren, betreuungSetzen, scoutZuteilungSetzen, istLeitung, istDogFather, siehtAlles, ROLLEN_SORTIERUNG, ROLLEN_REIHE, istSpicy, verborgeneIds, TEAM_DOGI_ROLLEN,
|
||||
db, protokolliere, echteIp, sitzungLesen, personAnlegen, codeNeu, sitzungToken, personSperren, betreuungSetzen, scoutZuteilungSetzen, istLeitung, istDogFather, siehtAlles, ROLLEN_SORTIERUNG, ROLLEN_REIHE, istSpicy, verborgeneIds, TEAM_DOGI_ROLLEN, darfAnlegen,
|
||||
} from "./workspace.js";
|
||||
import { sicherungJetzt } from "./workspace-sicherung.js";
|
||||
|
||||
@@ -520,27 +520,61 @@ personenRouter.post("/workspace/api/creator-anlegen", gleicheHerkunft, nurLeitun
|
||||
EINEN MANAGER LEGT MAN NICHT NEBENBEI AN: Er sieht danach jeden
|
||||
Creator, den er betreut, und legt selbst welche an. Deshalb bleibt
|
||||
diese Tuer Spicy Media und DogFather vorbehalten -- ein Manager kann
|
||||
keinen zweiten Manager schaffen. */
|
||||
personenRouter.post("/workspace/api/manager-anlegen", gleicheHerkunft, (req, res) => {
|
||||
try {
|
||||
const person = sitzungLesen(req);
|
||||
if (!person) return res.status(401).json({ fehler: "nicht_angemeldet" });
|
||||
if (!siehtAlles(person)) return res.status(404).json({ fehler: "nicht_gefunden" });
|
||||
keinen zweiten Manager schaffen.
|
||||
|
||||
const name = String(req.body?.name ?? "").trim();
|
||||
if (name.length < 2) return res.status(400).json({ fehler: "Name fehlt." });
|
||||
if (name.length > NAME_MAX) return res.status(400).json({ fehler: "Name ist zu lang." });
|
||||
const vorhanden = db().prepare(
|
||||
"SELECT 1 FROM personen WHERE lower(name) = lower(?) AND aktiv = 1").get(name);
|
||||
if (vorhanden) return res.status(409).json({ fehler: "Diesen Namen gibt es schon." });
|
||||
NACHTRAG 10.09.2026 — JETZT AUCH SCOUTS, UND TROTZDEM ZWEI TUEREN.
|
||||
|
||||
const neu = personAnlegen(name, "manager", { ...person, ip: echteIp(req) });
|
||||
res.status(201).json({ id: neu.id, name: neu.name, rolle: neu.rolle, code: neu.code });
|
||||
} catch (fehler) {
|
||||
console.error("[workspace] Manager anlegen:", fehler?.message);
|
||||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||
}
|
||||
});
|
||||
Filipe: "die spicy rolle soll auch manager und scouts hinzufuegen
|
||||
koennen." Fuer Scouts gab es bis heute ueberhaupt keinen Weg ausser
|
||||
ueber DogFather.
|
||||
|
||||
Der naheliegende Griff waere gewesen, hier ein Feld `rolle`
|
||||
anzunehmen. Genau davon raet der Absatz oben ab, und der Rat gilt
|
||||
weiter: Eine Tuer, die NICHTS anderes kann, als eine bestimmte Rolle
|
||||
anzulegen, ist sicherer als eine, die vorher nachfragt. Eine
|
||||
vergessene Abfrage waere ein zweiter Zugang mit allen Rechten; eine
|
||||
vergessene Abfrage an einer Tuer, die nur "scout" kennt, ist ein
|
||||
Aergernis, aber keine Luecke.
|
||||
|
||||
Also weiterhin zwei Tueren mit je einer festen Rolle — nur nicht mehr
|
||||
zweimal derselbe Text. `teamTuer(rolle)` baut den Griff, die Rolle
|
||||
wird beim EINHAENGEN festgelegt und kommt nie aus dem Aufruf.
|
||||
|
||||
Und die Frage "darf diese Person das ueberhaupt" beantwortet nicht
|
||||
mehr diese Datei, sondern `darfAnlegen` in workspace.js — dieselbe
|
||||
Auskunft, aus der auch die Oberflaeche ihre Knoepfe baut. Zwei Listen
|
||||
fuer dieselbe Aussage waren der Grund, warum Spicy Media den
|
||||
Manager-Knopf nie zu sehen bekam. */
|
||||
function teamTuer(rolle) {
|
||||
return (req, res) => {
|
||||
try {
|
||||
const person = sitzungLesen(req);
|
||||
if (!person) return res.status(401).json({ fehler: "nicht_angemeldet" });
|
||||
/* ZWEI SCHLOESSER, ABSICHTLICH. `siehtAlles` sagt, wer diese Tuer
|
||||
ueberhaupt sieht; `darfAnlegen` sagt, ob sie fuer genau diese
|
||||
Rolle offen ist. Faellt eines der beiden weg, haelt das andere. */
|
||||
if (!siehtAlles(person)) return res.status(404).json({ fehler: "nicht_gefunden" });
|
||||
if (!darfAnlegen(person).includes(rolle)) {
|
||||
return res.status(403).json({ fehler: "Diese Rolle legst du nicht an." });
|
||||
}
|
||||
|
||||
const name = String(req.body?.name ?? "").trim();
|
||||
if (name.length < 2) return res.status(400).json({ fehler: "Name fehlt." });
|
||||
if (name.length > NAME_MAX) return res.status(400).json({ fehler: "Name ist zu lang." });
|
||||
const vorhanden = db().prepare(
|
||||
"SELECT 1 FROM personen WHERE lower(name) = lower(?) AND aktiv = 1").get(name);
|
||||
if (vorhanden) return res.status(409).json({ fehler: "Diesen Namen gibt es schon." });
|
||||
|
||||
const neu = personAnlegen(name, rolle, { ...person, ip: echteIp(req) });
|
||||
res.status(201).json({ id: neu.id, name: neu.name, rolle: neu.rolle, code: neu.code });
|
||||
} catch (fehler) {
|
||||
console.error(`[workspace] ${rolle} anlegen:`, fehler?.message);
|
||||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||
}
|
||||
};
|
||||
}
|
||||
personenRouter.post("/workspace/api/manager-anlegen", gleicheHerkunft, teamTuer("manager"));
|
||||
personenRouter.post("/workspace/api/scout-anlegen", gleicheHerkunft, teamTuer("scout"));
|
||||
|
||||
/* Welche Scouts kann ich einem neuen Creator gleich mitgeben?
|
||||
Dieselbe Regel wie oben, nur lesend -- damit die Oberflaeche genau
|
||||
@@ -594,10 +628,22 @@ personenRouter.post("/workspace/api/verwaltung/personen", gleicheHerkunft, (req,
|
||||
/* ERSTER VORBEHALT: Eine Leitung anlegen darf nur DogFather.
|
||||
Duerfte ein Manager das, koennte er sich einen zweiten Zugang mit
|
||||
vollen Rechten schaffen -- und waere damit nicht mehr begrenzbar.
|
||||
"Nur DogFather hat alle endgueltigen Rechte" faengt hier an. */
|
||||
if (!istDogFather(req.person) && (rolle === "admin" || rolle === "manager")) {
|
||||
"Nur DogFather hat alle endgueltigen Rechte" faengt hier an.
|
||||
|
||||
SEIT DEM 10.09.2026 STEHT DIE ANTWORT NICHT MEHR HIER, sondern in
|
||||
`darfAnlegen` (workspace.js) — derselben Auskunft, aus der auch
|
||||
die beiden Team-Tueren und die Oberflaeche ihre Knoepfe bauen.
|
||||
Vorher stand die Regel an vier Stellen in drei Dateien, und genau
|
||||
daran ist sie zerbrochen: Zwei davon widersprachen einander, und
|
||||
Spicy Media bekam den Manager-Knopf nie zu sehen.
|
||||
|
||||
Am Ergebnis aendert sich nichts — die Liste sagt fuer DogFather
|
||||
"alles" und fuer einen Manager "nur Creator", also genau das, was
|
||||
hier vorher ausgeschrieben stand. Es steht nur noch an einer
|
||||
Stelle. */
|
||||
if (!darfAnlegen(req.person).includes(rolle)) {
|
||||
return res.status(403).json({
|
||||
fehler: "DogFather und Manager legt nur DogFather selbst an.",
|
||||
fehler: "Diese Rolle legst du nicht an.",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -115,6 +115,59 @@ const LEITUNG = new Set(["spicy", "admin", "manager"]);
|
||||
export const istLeitung = (person) => !!person && LEITUNG.has(person.rolle);
|
||||
export const istDogFather = (person) => !!person && person.rolle === "admin";
|
||||
|
||||
/* =======================================================================
|
||||
WER DARF WEN ANLEGEN — die einzige Liste dazu (10.09.2026)
|
||||
|
||||
Filipe, mit Bildschirmfoto der Zugaenge-Seite: "die spicy rolle soll
|
||||
auch manager und scouts hinzufuegen koennen."
|
||||
|
||||
Sie konnte es nicht. Der Grund war NICHT ein fehlendes Recht, sondern
|
||||
ZWEI Listen, die einander widersprachen — in derselben Funktion, drei
|
||||
Zeilen auseinander (personen.js):
|
||||
|
||||
const darf = ... : ich.rolle === 'spicy' ? ['manager', 'creator']
|
||||
...
|
||||
if ((r.wert === 'admin' || r.wert === 'manager') && ich.rolle !== 'admin') continue;
|
||||
|
||||
Die erste Zeile erlaubt Spicy Media einen Manager, die zweite nimmt
|
||||
ihn wieder weg. Uebrig blieb genau ein Knopf: Creator. Serverseitig
|
||||
war der Weg fuer den Manager die ganze Zeit offen — es gab nur keinen
|
||||
Knopf dafuer.
|
||||
|
||||
Das ist im Haus die immer gleiche Sorte Fehler: zwei Stellen fuer
|
||||
dieselbe Aussage, und die spaetere gewinnt still. Deshalb steht die
|
||||
Antwort ab jetzt EINMAL hier, und alle fragen sie:
|
||||
|
||||
- die drei Anlege-Wege in workspace-personen.js
|
||||
- die Oberflaeche, ueber `darf_anlegen` in /workspace/api/ich
|
||||
|
||||
Die Oberflaeche hat damit gar keine eigene Liste mehr. Sie kann
|
||||
deshalb auch nicht mehr von der des Servers abweichen — weder zu
|
||||
streng (ein Recht, das niemand findet) noch zu grosszuegig (ein Knopf,
|
||||
der eine Absage bringt).
|
||||
|
||||
WARUM SPICY MEDIA SCOUTS ANLEGEN DARF, ABER KEINE LEITUNG:
|
||||
Ein Scout und ein Manager arbeiten unter Spicy Media — sie
|
||||
einzustellen ist genau die Aufgabe dieser Rolle. Einen DogFather
|
||||
anzulegen ist es nicht: Das waere ein zweiter Zugang mit allen
|
||||
endgueltigen Rechten, und den vergibt nur DogFather selbst.
|
||||
======================================================================= */
|
||||
const ANLEGBAR = {
|
||||
/* DogFather: alles, was es gibt. Er geht ueber /verwaltung/personen. */
|
||||
admin: [...ROLLEN],
|
||||
/* Spicy Media: das ganze Team, aber keine Leitung ueber sich. */
|
||||
spicy: ["manager", "scout", "creator"],
|
||||
/* Ein Manager stellt Creator ein, die er dann auch betreut. */
|
||||
manager: ["creator"],
|
||||
};
|
||||
|
||||
/** Welche Rollen darf diese Person anlegen? Immer ein Feld, nie null —
|
||||
* wer nichts darf, bekommt eine leere Liste und keinen Sonderfall. */
|
||||
export function darfAnlegen(person) {
|
||||
if (!person) return [];
|
||||
return [...(ANLEGBAR[person.rolle] ?? [])];
|
||||
}
|
||||
|
||||
/* WER FUEHRT TEAM DOGI? (10.09.2026)
|
||||
*
|
||||
* DogFather und seine rechte Hand -- und sonst niemand. Spicy Media und
|
||||
@@ -3262,6 +3315,14 @@ workspaceRouter.get("/workspace/api/ich", (req, res) => {
|
||||
rolle_name: ROLLEN_NAME[person.rolle] ?? person.rolle,
|
||||
sicht,
|
||||
bild,
|
||||
/* WELCHE ROLLEN ICH ANLEGEN DARF (10.09.2026).
|
||||
|
||||
Damit hat die Oberflaeche keine eigene Liste mehr. Vorher standen
|
||||
dort zwei, die einander widersprachen, und Spicy Media sah
|
||||
deshalb nur den Creator-Knopf — obwohl der Weg fuer den Manager
|
||||
serverseitig offen war. Wer die Antwort nur an einer Stelle hat,
|
||||
kann sie nicht an zweien verschieden haben. */
|
||||
darf_anlegen: darfAnlegen(person),
|
||||
/* DIE KACHELN, WENN SIE NICHT IM BROWSER STEHEN DUERFEN.
|
||||
|
||||
Fuer die fuenf bekannten Rollen steht hier `null`, und die
|
||||
|
||||
Reference in New Issue
Block a user