Die Rolle "Spicy Media" -- und drei Fehler, die nur ihre Pruefung fand
DIE PERSONENTABELLE WURDE NEU GEBAUT. Eine Rolle ist ein erlaubter Wert in einer Spalte, und der steckt in einem CHECK -- den kann SQLite nicht aendern. Auf `personen` zeigen ZWEIUNDFUENFZIG Fremdschluessel. Deshalb wird der Bauplan NICHT abgeschrieben, sondern gelesen: Der CREATE-Text kommt aus sqlite_master, darin wird ausschliesslich die Rollenliste ersetzt, und die Kopierliste kommt aus PRAGMA table_info. Die beiden aelteren Umstellungen schreiben ihre Spalten von Hand ab -- `personen` hat seit damals SIEBEN dazubekommen (bild, ueber_mich, tiktok ...). Wer hier abschreibt, verliert alle Profilbilder. ZWEI FRAGEN, DIE MAN AUSEINANDERHALTEN MUSS: siehtAlles() = DogFather ODER Spicy Media -> Listen, Uebersichten istDogFather() = nur DogFather -> loeschen, Rollen, Codes Es waere weniger Arbeit gewesen, istDogFather() um "spicy" zu erweitern -- und genau das waere der Fehler: Spicy Media koennte dann DogFather loeschen. DER CHAT BRAUCHTE NICHTS. Er haengt allein an der Teilnehmerliste und kennt kein "das Management sieht alles". Spicy Media sieht fremde Gespraeche nicht, weil es dafuer keinen Weg gibt -- nicht, weil eine Abfrage es verbietet. DREI ECHTE FEHLER, alle von pruef-spicy gefunden, keiner vorher sichtbar: 1. MEIN EIGENER KOMMENTAR STAND IM BAUPLAN. SQLite hebt den CREATE-Text woertlich auf, samt Kommentaren. Ich hatte "'spicy' steht HIER mit drin" hineingeschrieben -- und die Erkennung suchte genau dieses Wort im ganzen Text. Ergebnis: Die Umstellung hielt die Tabelle fuer erledigt, obwohl die CHECK-Regel noch die alte war. Jetzt wird die Regel herausgeschnitten und NUR darin gesucht; der Kommentar steht ausserhalb des SQL. 2. DER SICHERUNGSNAME HATTE NUR MINUTEN. `VACUUM INTO` weigert sich, eine vorhandene Datei zu ueberschreiben -- zu Recht. Zwei Umstellungen in derselben Minute wollten in dieselbe Datei, die zweite scheiterte, und weil ohne Sicherung nicht umgestellt wird, blieb sie aus. Es sah nach "lief" aus (die Datei lag ja da) und war keine. Jetzt mit Sekunden. 3. EINE FRISCHE DATENBANK LEGTE DIE ALTE ROLLENLISTE AN und stellte beim allerersten Start sofort um -- Tabelle neu bauen, Sicherung schreiben, fuer nichts. Ein Bauplan, der sofort umgebaut werden muss, ist der falsche. Und ein vierter in der Pruefung selbst: Der Chat-Aufbau benutzte einen falschen Weg, das Gespraech entstand gar nicht -- "Spicy Media sieht 0 Gespraeche" war trotzdem gruen, weil es keine gab. Jetzt ist das Anlegen selbst eine Pruefung, und eine Gegenprobe zeigt, dass Max es sehr wohl sieht. DAZU: Manager sehen die Kachel "Personen & Zugaenge" -- die SEITE geht auf, die Schnittstellen nicht. Alles unter /verwaltung haengt weiter an `nurAdmin` und antwortet 404; sie sehen genau den Teil, fuer den es einen Weg gibt. Spicy Media legt Creator UND Manager an (zweite enge Tuer, Rolle steht auch dort nicht im Aufruf; ein Manager kommt durch sie nicht). Der Rollentext des Managers stimmte nicht mehr -- er legt jetzt Creator an. pruef-spicy: 36 Pruefungen, alle gruen. Ausserdem gruen: personen-liste (33), creator-anlegen (29), sicht (48), css-klassen (15), alle-wege (19), haerte (20), manager-sicht (43). Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+234
-23
@@ -57,17 +57,19 @@ const COOKIE = "dfw_sitzung";
|
||||
const SITZUNG_STUNDEN = 12;
|
||||
const VERSUCHE_MAX = 8; // pro IP
|
||||
const VERSUCHE_FENSTER_MIN = 10;
|
||||
const ROLLEN = new Set(["admin", "manager", "scout", "creator"]);
|
||||
const ROLLEN = new Set(["spicy", "admin", "manager", "scout", "creator"]);
|
||||
|
||||
/* Die Reihenfolge, in der Rollen ueberall erscheinen: DogFather zuerst,
|
||||
dann Manager, dann Scout, dann Creator. Steht hier einmal, damit keine
|
||||
Liste eine eigene Reihenfolge erfindet. */
|
||||
export const ROLLEN_REIHE = ["admin", "manager", "scout", "creator"];
|
||||
/* Die Reihenfolge, in der Rollen ueberall erscheinen: Spicy Media
|
||||
zuerst, dann DogFather, Manager, Scout, Creator. Steht hier einmal,
|
||||
damit keine Liste eine eigene Reihenfolge erfindet. */
|
||||
export const ROLLEN_REIHE = ["spicy", "admin", "manager", "scout", "creator"];
|
||||
|
||||
/* Als SQL-Ausdruck fuer ORDER BY. "ORDER BY rolle" waere alphabetisch
|
||||
(admin, creator, manager, scout) -- also fast genau falsch herum. */
|
||||
(admin, creator, manager, scout, spicy) -- also fast genau falsch
|
||||
herum. */
|
||||
export const ROLLEN_SORTIERUNG =
|
||||
"CASE rolle WHEN 'admin' THEN 0 WHEN 'manager' THEN 1 WHEN 'scout' THEN 2 ELSE 3 END";
|
||||
"CASE rolle WHEN 'spicy' THEN 0 WHEN 'admin' THEN 1 WHEN 'manager' THEN 2"
|
||||
+ " WHEN 'scout' THEN 3 ELSE 4 END";
|
||||
|
||||
/* LEITUNG = DogFather und Manager. Ein Manager darf alles, was
|
||||
DogFather darf -- mit genau zwei Ausnahmen, die in
|
||||
@@ -75,10 +77,44 @@ export const ROLLEN_SORTIERUNG =
|
||||
Leitung veraendern. Sonst koennte er sich selbst zum DogFather machen
|
||||
oder den echten aussperren. "Nur DogFather hat alle endgueltigen
|
||||
Rechte" heisst genau das. */
|
||||
const LEITUNG = new Set(["admin", "manager"]);
|
||||
const LEITUNG = new Set(["spicy", "admin", "manager"]);
|
||||
export const istLeitung = (person) => !!person && LEITUNG.has(person.rolle);
|
||||
export const istDogFather = (person) => !!person && person.rolle === "admin";
|
||||
|
||||
/* =======================================================================
|
||||
SPICY MEDIA (07.09.2026)
|
||||
|
||||
Wunsch Filipe: "eine neue rolle ... die den namen traegt, spicy media,
|
||||
und soll die gleichen rechte haben wie dogfather ausser, bei
|
||||
automationen sollen die nicht sehen und die kategorie personen und
|
||||
zugaenge sollen die nur leute hinzufuegen koennen ... aber die sollen
|
||||
meine privaten chats und so nicht sehen."
|
||||
|
||||
ZWEI FRAGEN, DIE MAN AUSEINANDERHALTEN MUSS -- und genau daran haette
|
||||
man diesen Umbau kaputtmachen koennen:
|
||||
|
||||
WER SIEHT ALLES? -> siehtAlles() = DogFather ODER Spicy Media
|
||||
WER ENTSCHEIDET? -> istDogFather() = nur DogFather
|
||||
|
||||
Die erste Frage stellt sich bei Listen, Uebersichten und Auswertungen:
|
||||
Spicy Media soll alle Manager, Scouts und Creator sehen. Die zweite
|
||||
bei allem Endgueltigen: loeschen, Rollen aendern, Codes neu setzen,
|
||||
Sicherungen, die KI abschalten. Da bleibt DogFather allein.
|
||||
|
||||
Es waere viel weniger Arbeit gewesen, istDogFather() einfach um
|
||||
"spicy" zu erweitern -- und genau das waere der Fehler: Spicy Media
|
||||
koennte dann DogFather loeschen. Zwei Namen, zwei Bedeutungen, und an
|
||||
jeder Stelle steht sichtbar, welche gemeint ist.
|
||||
|
||||
DER CHAT BRAUCHTE NICHTS. Er haengt ausschliesslich an der
|
||||
Teilnehmerliste (chat_teilnehmer) und kennt kein "das Management sieht
|
||||
alles". Spicy Media sieht fremde Gespraeche also nicht, weil es dafuer
|
||||
gar keinen Weg gibt -- nicht, weil eine Abfrage es verbietet.
|
||||
======================================================================= */
|
||||
export const istSpicy = (person) => !!person && person.rolle === "spicy";
|
||||
export const siehtAlles = (person) => !!person
|
||||
&& (person.rolle === "admin" || person.rolle === "spicy");
|
||||
|
||||
/* Der Rollenschluessel bleibt "admin" -- er steckt in der CHECK-Regel der
|
||||
Datenbank, in jeder Sitzung und in jeder Rechteabfrage. Umbenannt wird
|
||||
nur, was man LIEST. Diese Zuordnung ist die einzige Stelle dafuer:
|
||||
@@ -89,6 +125,7 @@ export const istDogFather = (person) => !!person && person.rolle === "admin";
|
||||
Rolle "admin" weiterhin "das Management". Gemeint ist dieselbe Rolle,
|
||||
die in der Oberflaeche "DogFather" heisst. */
|
||||
export const ROLLEN_NAME = {
|
||||
spicy: "Spicy Media",
|
||||
admin: "DogFather",
|
||||
manager: "Manager",
|
||||
scout: "Scout",
|
||||
@@ -120,7 +157,21 @@ let _dbFehler = null;
|
||||
waehrend laufender Schreibvorgaenge).
|
||||
===================================================================== */
|
||||
function umstellungen(d) {
|
||||
const jetztStempel = new Date().toISOString().slice(0, 16).replace(/[-:T]/g, "");
|
||||
/* MIT SEKUNDEN, nicht nur mit Minuten (07.09.2026).
|
||||
|
||||
`VACUUM INTO` weigert sich, eine vorhandene Datei zu ueberschreiben
|
||||
("output file already exists") -- zu Recht, eine Sicherung darf
|
||||
nichts wegwerfen. Der Stempel hatte aber nur Minutenaufloesung:
|
||||
Zwei Umstellungen innerhalb derselben Minute wollten in dieselbe
|
||||
Datei, die zweite scheiterte, und weil ohne Sicherung nicht
|
||||
umgestellt wird, blieb sie einfach aus.
|
||||
|
||||
Das ist genau die unangenehme Sorte Fehler: Es sieht nach "die
|
||||
Umstellung lief" aus (die Datei liegt ja da) und war doch keine.
|
||||
Gefunden von pruef-spicy, das den Server zweimal in derselben
|
||||
Minute startet -- im Betrieb genuegt dafuer ein Neustart im
|
||||
falschen Moment. */
|
||||
const jetztStempel = new Date().toISOString().slice(0, 19).replace(/[-:T]/g, "");
|
||||
|
||||
/* ---- Zeitpunkt des Hochladens in der Bibliothek ----
|
||||
Eine neue Spalte laesst SQLite anstandslos anhaengen -- anders als
|
||||
@@ -635,6 +686,131 @@ function umstellungen(d) {
|
||||
d.exec("PRAGMA foreign_keys = ON");
|
||||
}
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
ROLLE "spicy" (Spicy Media) FREISCHALTEN — 07.09.2026
|
||||
|
||||
Wunsch Filipe: "ich will dass ueber dogfather auch eine kategorie,
|
||||
eine neue rolle entsteht die den namen traegt, spicy media."
|
||||
|
||||
---------------------------------------------------------------------
|
||||
DAS IST DER RISKANTESTE UMBAU IM GANZEN HAUS
|
||||
|
||||
Eine Rolle ist ein erlaubter Wert in einer Spalte, und der steckt in
|
||||
SQLite in einem CHECK. Ein CHECK laesst sich nicht aendern -- die
|
||||
Tabelle muss neu gebaut werden. Bei `eintraege` war das schon
|
||||
unangenehm; hier geht es um `personen`, und auf die zeigen
|
||||
ZWEIUNDFUENFZIG Fremdschluessel aus einem Dutzend Tabellen. Jede
|
||||
Sitzung, jede Aufgabe, jeder Termin, jede Datei haengt daran.
|
||||
|
||||
DESHALB WIRD DER BAUPLAN NICHT ABGESCHRIEBEN, SONDERN GELESEN.
|
||||
|
||||
Die beiden Umstellungen darueber schreiben ihre Spaltenliste von
|
||||
Hand ab. Das ging gut, solange die Liste stimmte -- aber `personen`
|
||||
hat seit damals SIEBEN Spalten dazubekommen (bild, ueber_mich,
|
||||
tiktok, instagram, youtube, twitch und weitere, siehe den
|
||||
Spalten-Nachtrag oben). Wer hier eine Liste abschreibt, verliert
|
||||
beim naechsten Mal genau die Spalte, die jemand letzte Woche
|
||||
ergaenzt hat -- samt allen Profilbildern.
|
||||
|
||||
Also: Der vorhandene CREATE-Text wird aus sqlite_master geholt und
|
||||
darin AUSSCHLIESSLICH die Rollenliste ersetzt. Alles andere -- jede
|
||||
Spalte, jeder Typ, jede Vorgabe -- bleibt woertlich stehen. Und die
|
||||
Kopierliste kommt aus PRAGMA table_info, also aus der Tabelle
|
||||
selbst.
|
||||
|
||||
WENN DIE ERSETZUNG NICHT GREIFT, WIRD NICHT UMGESTELLT. Ein
|
||||
`replace`, das nichts findet, gibt den Text unveraendert zurueck --
|
||||
die Umstellung liefe dann durch, baute dieselbe Tabelle noch einmal
|
||||
und meldete Erfolg. Genau die Sorte gruener Haken, die nichts
|
||||
geprueft hat. Deshalb wird danach nachgesehen, ob 'spicy' wirklich
|
||||
drinsteht.
|
||||
===================================================================== */
|
||||
const rollenPlan = d.prepare(
|
||||
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'personen'").get()?.sql || "";
|
||||
/* GEPRUEFT WIRD DIE REGEL, NICHT DER TEXT (07.09.2026).
|
||||
|
||||
Hier stand `rollenPlan.includes("'spicy'")`. Das ist eine Suche im
|
||||
ganzen gespeicherten Bauplan -- und SQLite hebt den woertlich auf,
|
||||
mitsamt allen Kommentaren darin. Ein erklaerender Satz mit dem Wort
|
||||
'spicy' genuegte, und die Umstellung hielt die Tabelle fuer schon
|
||||
umgestellt, obwohl die CHECK-Regel noch die alte war. Beim Bauen
|
||||
genau so passiert.
|
||||
|
||||
Jetzt wird die Regel selbst herausgeschnitten und NUR darin gesucht.
|
||||
Findet sich keine, gibt es nichts umzustellen. */
|
||||
const regel = rollenPlan.match(/rolle\s+IN\s*\(([^)]*)\)/i)?.[1] || "";
|
||||
if (rollenPlan && regel && !regel.includes("'spicy'")) {
|
||||
const sicherung = `${DB_PFAD}.vor-spicy-${jetztStempel}`;
|
||||
try {
|
||||
d.exec(`VACUUM INTO '${sicherung.replace(/'/g, "''")}'`);
|
||||
console.log("[workspace] Sicherung vor der Umstellung:", sicherung);
|
||||
} catch (fehler) {
|
||||
console.error("[workspace] Sicherung fehlgeschlagen, Umstellung abgebrochen:", fehler?.message);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Nur die Rollenliste ersetzen -- und pruefen, dass es geklappt hat. */
|
||||
const neuerPlan = rollenPlan
|
||||
/* `IF NOT EXISTS` MUSS MIT INS MUSTER (07.09.2026, gefunden von
|
||||
pruef-spicy). SQLite hebt den CREATE-Text WOERTLICH auf -- die
|
||||
Tabelle wurde mit `CREATE TABLE IF NOT EXISTS personen` angelegt,
|
||||
also steht das auch in sqlite_master. Ohne diese drei Woerter im
|
||||
Muster griff die Ersetzung nicht, der Bauplan blieb unveraendert,
|
||||
die Schutzabfrage darunter schlug an -- und die Umstellung waere
|
||||
auf dem echten Server NIE gelaufen. Sie haette es gesagt (das ist
|
||||
der Wert der Abfrage), aber sie waere nie gelaufen. */
|
||||
.replace(/CREATE TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?["'`]?personen["'`]?/i,
|
||||
"CREATE TABLE personen_neu")
|
||||
.replace(/rolle\s+IN\s*\([^)]*\)/i, "rolle IN ('spicy','admin','manager','scout','creator')");
|
||||
if (!neuerPlan.includes("'spicy'") || !neuerPlan.includes("personen_neu")) {
|
||||
console.error("[workspace] Umstellung abgebrochen: Der Bauplan liess sich nicht "
|
||||
+ "umschreiben. Steht die CHECK-Regel noch so da wie erwartet?");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Die Spaltenliste kommt aus der Tabelle, nicht aus dem Gedaechtnis. */
|
||||
const spalten = d.prepare("PRAGMA table_info(personen)").all().map((z) => z.name);
|
||||
if (!spalten.length) {
|
||||
console.error("[workspace] Umstellung abgebrochen: keine Spalten gefunden.");
|
||||
return;
|
||||
}
|
||||
const liste = spalten.map((n) => `"${n}"`).join(", ");
|
||||
|
||||
d.exec("PRAGMA foreign_keys = OFF");
|
||||
try {
|
||||
const vorher = d.prepare("SELECT COUNT(*) AS n FROM personen").get().n;
|
||||
d.exec("BEGIN");
|
||||
d.exec(neuerPlan);
|
||||
d.exec(`INSERT INTO personen_neu (${liste}) SELECT ${liste} FROM personen;`);
|
||||
const nachher = d.prepare("SELECT COUNT(*) AS n FROM personen_neu").get().n;
|
||||
/* Die Zaehlung steht INNERHALB der Transaktion -- stimmt sie nicht,
|
||||
wird zurueckgerollt und die alte Tabelle bleibt unberuehrt. */
|
||||
if (nachher !== vorher) {
|
||||
d.exec("ROLLBACK");
|
||||
console.error(`[workspace] Umstellung abgebrochen: ${vorher} Personen vorher, `
|
||||
+ `${nachher} nachher. Sicherung: ${sicherung}`);
|
||||
} else {
|
||||
d.exec("DROP TABLE personen;");
|
||||
d.exec("ALTER TABLE personen_neu RENAME TO personen;");
|
||||
d.exec("COMMIT");
|
||||
const kaputt = d.prepare("PRAGMA foreign_key_check").all();
|
||||
if (kaputt.length) {
|
||||
console.error("[workspace] ACHTUNG: nach der Umstellung", kaputt.length,
|
||||
"verwaiste Verweise. Sicherung liegt unter", sicherung);
|
||||
} else {
|
||||
console.log(`[workspace] Rolle 'spicy' freigeschaltet, ${nachher} Personen, `
|
||||
+ `${spalten.length} Spalten uebernommen, Verweise geprueft.`);
|
||||
}
|
||||
}
|
||||
} catch (fehler) {
|
||||
try { d.exec("ROLLBACK"); } catch { /* schon zurueckgerollt */ }
|
||||
console.error("[workspace] Umstellung fehlgeschlagen:", fehler?.message,
|
||||
"-- Sicherung:", sicherung);
|
||||
} finally {
|
||||
d.exec("PRAGMA foreign_keys = ON");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function db() {
|
||||
@@ -648,10 +824,23 @@ export function db() {
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
/* ROLLENLISTE: 'spicy' steht hier mit drin, nicht nur in der
|
||||
Umstellung (07.09.2026, gefunden von pruef-spicy). Vorher legte
|
||||
eine frische Datenbank die alte Liste an, und die Umstellung
|
||||
lief beim allerersten Start sofort hinterher -- Tabelle neu
|
||||
bauen, Sicherung schreiben, umbenennen, fuer nichts. Ein
|
||||
Bauplan, der sofort umgebaut werden muss, ist der falsche.
|
||||
|
||||
KEIN KOMMENTAR INNERHALB DIESES CREATE-TEXTES. SQLite hebt ihn
|
||||
woertlich in sqlite_master auf -- samt Kommentaren. Ein Satz mit
|
||||
dem Wort 'spicy' darin haette bedeutet, dass die Umstellung die
|
||||
Tabelle fuer bereits umgestellt haelt, obwohl die CHECK-Regel
|
||||
noch die alte ist. Genau das ist beim Bauen passiert: Der
|
||||
Bauplan enthielt das Wort, die Regel nicht. */
|
||||
CREATE TABLE IF NOT EXISTS personen (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
rolle TEXT NOT NULL CHECK (rolle IN ('admin','manager','scout','creator')),
|
||||
rolle TEXT NOT NULL CHECK (rolle IN ('spicy','admin','manager','scout','creator')),
|
||||
code_hash TEXT NOT NULL,
|
||||
code_salt TEXT NOT NULL,
|
||||
code_n INTEGER NOT NULL,
|
||||
@@ -1456,27 +1645,49 @@ const GESCHUETZT = {
|
||||
Lesezeichen hat, waere weiterhin hineingekommen. Beides gehoert
|
||||
zusammen: bereiche.js zeigt sie nur noch DogFather, diese Zeile
|
||||
laesst nur ihn hinein. */
|
||||
"/workspace/leistung.html": ["admin"],
|
||||
"/workspace/leistung.html": ["spicy", "admin"],
|
||||
/* NUR DogFather (02.09.2026). Die Rollenauswahl verspricht das seit
|
||||
jeher ("Manager -- dieselben Rechte, ausser der
|
||||
Personenverwaltung"), die Schranke hielt sich nur nicht daran.
|
||||
Wunsch: "die manager sollen diese kategorien garnicht sehen". */
|
||||
"/workspace/personen.html": ["admin"],
|
||||
"/workspace/profil.html": ["admin", "manager", "scout", "creator"],
|
||||
/* PERSONEN & ZUGAENGE: jetzt auch fuer Manager und Spicy Media
|
||||
(07.09.2026).
|
||||
|
||||
Filipe: "die manager sehen immer noch nicht die kachel personen &
|
||||
zugangscode, wo sie dan die neuen creator hinzufuegen koennen ...
|
||||
und die sollen in der kategorie wo die jetzt sehen werden auch noch
|
||||
das mit den hinzufuegen sehen, alles andere auf der seite sollen die
|
||||
weiterhin nicht sehen."
|
||||
|
||||
DIE SEITE OEFFNET SICH, DIE SCHNITTSTELLEN NICHT. Das ist der ganze
|
||||
Trick und der Grund, warum das hier ungefaehrlich ist: Alles unter
|
||||
/workspace/api/verwaltung haengt weiterhin an `nurAdmin` -- Rollen
|
||||
aendern, Codes neu setzen, sperren, loeschen, Protokoll lesen
|
||||
bleiben zu und antworten mit 404. Wer die Seite oeffnet, bekommt
|
||||
also genau die Teile zu sehen, fuer die es auch einen Weg gibt.
|
||||
|
||||
Eine Seite ist kein Schutz, sie ist ein Weg. Der Schutz steht in den
|
||||
Schnittstellen, und der ist unveraendert. */
|
||||
"/workspace/personen.html": ["spicy", "admin", "manager"],
|
||||
"/workspace/profil.html": ["spicy", "admin", "manager", "scout", "creator"],
|
||||
/* Der eigene Steckbrief -- jede Rolle hat einen. Ein Creator wird
|
||||
dort nicht hingeschickt (er sieht seinen auf profil.html), darf die
|
||||
Seite aber aufrufen: Sie zeigt ihm dasselbe, nur ohne die Akte. */
|
||||
"/workspace/steckbrief.html": ["admin", "manager", "scout", "creator"],
|
||||
"/workspace/steckbrief.html": ["spicy", "admin", "manager", "scout", "creator"],
|
||||
"/workspace/kalender.html": null,
|
||||
"/workspace/dateien.html": null,
|
||||
"/workspace/bereich.html": ["admin", "manager", "scout", "creator"],
|
||||
"/workspace/report.html": ["admin", "manager", "scout", "creator"],
|
||||
"/workspace/scouting.html": ["admin", "manager", "scout"],
|
||||
"/workspace/bereich.html": ["spicy", "admin", "manager", "scout", "creator"],
|
||||
"/workspace/report.html": ["spicy", "admin", "manager", "scout", "creator"],
|
||||
"/workspace/scouting.html": ["spicy", "admin", "manager", "scout"],
|
||||
"/workspace/calls.html": null,
|
||||
"/workspace/startcheck.html": null,
|
||||
"/workspace/wissen.html": null,
|
||||
/* Ebenfalls nur DogFather: Was von allein passiert, bestimmt, was
|
||||
allen anderen zugeschoben wird. */
|
||||
/* AUTOMATIONEN BLEIBEN BEI DogFather (07.09.2026). Ausdruecklich:
|
||||
"bei automationen sollen die nicht sehen." Dahinter liegen
|
||||
Sicherungen, die KI und der Zustand des Servers -- das ist Betrieb,
|
||||
nicht Betreuung. */
|
||||
"/workspace/automation.html": ["admin"],
|
||||
};
|
||||
|
||||
@@ -1870,7 +2081,7 @@ export function scoutZuteilungSetzen(scoutId, managerId, akteur = null) {
|
||||
* null = alle (nur DogFather). */
|
||||
export function sichtbareCreatorIds(person) {
|
||||
if (!person) return [];
|
||||
if (istDogFather(person)) return null;
|
||||
if (siehtAlles(person)) return null;
|
||||
if (person.rolle === "creator") return [person.id];
|
||||
return betreuteIds(person); // Manager: eigene + die seiner Scouts
|
||||
}
|
||||
@@ -1883,7 +2094,7 @@ export function sichtbareCreatorIds(person) {
|
||||
* seine Scouts dazu -- er führt sie, er muss sie eintragen können. */
|
||||
export function sichtbarePersonenIds(person) {
|
||||
if (!person) return [];
|
||||
if (istDogFather(person)) return null;
|
||||
if (siehtAlles(person)) return null;
|
||||
const creator = sichtbareCreatorIds(person) || [];
|
||||
const scouts = person.rolle === "manager" ? scoutsVon(person.id) : [];
|
||||
/* DOGFATHER IST FUER ALLE SICHTBAR (07.09.2026, Wunsch Filipe:
|
||||
@@ -1968,7 +2179,7 @@ export function betreuerIds(person) {
|
||||
* null = alle (nur DogFather), wie überall in dieser Datei. */
|
||||
export function einladbareIds(person) {
|
||||
if (!person) return [];
|
||||
if (istDogFather(person)) return null;
|
||||
if (siehtAlles(person)) return null;
|
||||
const sichtbar = sichtbarePersonenIds(person) || [];
|
||||
/* DogFather gehört immer dazu: Er ist der Einzige, mit dem jede
|
||||
Rolle zu tun hat, und ihn nicht einladen zu können wäre der erste
|
||||
@@ -2001,7 +2212,7 @@ export function einladbareIds(person) {
|
||||
* null = alle (nur DogFather). */
|
||||
export function schreibbareIds(person) {
|
||||
if (!person) return [];
|
||||
if (istDogFather(person)) return null;
|
||||
if (siehtAlles(person)) return null;
|
||||
|
||||
const basis = new Set(einladbareIds(person) || []);
|
||||
|
||||
@@ -2118,7 +2329,7 @@ export const externSql = (personSpalte, externSpalte) =>
|
||||
spaeter auseinandergelaufen -- und dann haette eine Wiederholung
|
||||
jemandem etwas gezeigt, was der einzelne Termin ihm verbirgt. */
|
||||
export function termineSichtbar(person, praefix = "t") {
|
||||
if (istDogFather(person)) return { wo: "1=1", werte: [] };
|
||||
if (siehtAlles(person)) return { wo: "1=1", werte: [] };
|
||||
const p = praefix;
|
||||
|
||||
/* MITGEZAEHLT WIRD AUCH DIE TEILNEHMERLISTE (05.09.2026).
|
||||
@@ -2236,7 +2447,7 @@ export function darfCreator(person, creatorId) {
|
||||
|
||||
Ein Manager faellt jetzt in dieselbe Zeile wie ein Scout -- die
|
||||
Kette "eigene plus die meiner Scouts" steckt in betreuteIds. */
|
||||
if (istDogFather(person)) return true;
|
||||
if (siehtAlles(person)) return true;
|
||||
if (person.rolle === "creator") return person.id === Number(creatorId);
|
||||
return betreuteIds(person).includes(Number(creatorId));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user