147 lines
6.0 KiB
TypeScript
147 lines
6.0 KiB
TypeScript
/**
|
|
* Die eingebauten Platzhalter (#010, aufgeloest in #012).
|
|
*
|
|
* Ein Platzhalter `{{schluessel}}` in Titel, Hilfetext oder Befehl wird beim
|
|
* Abarbeiten eines Laufs ersetzt. Woraus, steht hier: entweder aus einer
|
|
* Variablen der Vorlage oder aus einer der eingebauten Quellen. Ein Schluessel,
|
|
* der zu keiner von beiden passt, bleibt im Lauf als `{{schluessel}}` stehen —
|
|
* sichtbar, aber nutzlos. Deshalb warnt der Editor davor.
|
|
*
|
|
* Die Liste ist bewusst Daten und kein Code: der Editor zeigt sie als Hilfe an,
|
|
* die Warnung vergleicht dagegen, und #012 baut die Aufloesung darauf auf. Eine
|
|
* zweite Aufzaehlung an anderer Stelle wuerde unweigerlich auseinanderlaufen.
|
|
*/
|
|
|
|
export type PlatzhalterQuelle = "GERAET_LAUF" | "MITARBEITER" | "ABTEILUNG" | "BESONDERS";
|
|
|
|
export type EingebauterPlatzhalter = {
|
|
readonly schluessel: string;
|
|
readonly quelle: PlatzhalterQuelle;
|
|
readonly erklaerung: string;
|
|
/** Nur im Modus DIENSTLEISTUNG gefuellt; im Modus INTERN bleibt der Wert leer. */
|
|
readonly nurDienstleistung?: true;
|
|
};
|
|
|
|
export const EINGEBAUTE_PLATZHALTER: readonly EingebauterPlatzhalter[] = [
|
|
// Aus Geraet und Lauf
|
|
{ schluessel: "hostname", quelle: "GERAET_LAUF", erklaerung: "Hostname des Geräts im Lauf" },
|
|
{ schluessel: "seriennummer", quelle: "GERAET_LAUF", erklaerung: "Seriennummer des Geräts" },
|
|
{ schluessel: "inventarnummer", quelle: "GERAET_LAUF", erklaerung: "Inventarnummer des Geräts" },
|
|
{ schluessel: "ticket", quelle: "GERAET_LAUF", erklaerung: "Ticketnummer am Lauf" },
|
|
{ schluessel: "datum", quelle: "GERAET_LAUF", erklaerung: "heutiges Datum" },
|
|
{ schluessel: "techniker", quelle: "GERAET_LAUF", erklaerung: "Name des Bearbeiters" },
|
|
{
|
|
schluessel: "kunde",
|
|
quelle: "GERAET_LAUF",
|
|
erklaerung: "Name des Kunden",
|
|
nurDienstleistung: true,
|
|
},
|
|
{
|
|
schluessel: "kundenkuerzel",
|
|
quelle: "GERAET_LAUF",
|
|
erklaerung: "Kürzel des Kunden",
|
|
nurDienstleistung: true,
|
|
},
|
|
|
|
// Aus dem Mitarbeiter
|
|
{ schluessel: "mitarbeiter", quelle: "MITARBEITER", erklaerung: "vollständiger Name" },
|
|
{ schluessel: "benutzer", quelle: "MITARBEITER", erklaerung: "gleichbedeutend mit mitarbeiter" },
|
|
{ schluessel: "vorname", quelle: "MITARBEITER", erklaerung: "Vorname" },
|
|
{ schluessel: "nachname", quelle: "MITARBEITER", erklaerung: "Nachname" },
|
|
{ schluessel: "upn", quelle: "MITARBEITER", erklaerung: "User Principal Name" },
|
|
{ schluessel: "sam", quelle: "MITARBEITER", erklaerung: "sAMAccountName, höchstens 20 Zeichen" },
|
|
{ schluessel: "mail", quelle: "MITARBEITER", erklaerung: "Mail-Adresse" },
|
|
{ schluessel: "abteilung", quelle: "MITARBEITER", erklaerung: "Name der Abteilung" },
|
|
{ schluessel: "titel", quelle: "MITARBEITER", erklaerung: "Funktion oder Titel" },
|
|
{ schluessel: "vorgesetzter", quelle: "MITARBEITER", erklaerung: "Name des Vorgesetzten" },
|
|
{ schluessel: "vorgesetzter_sam", quelle: "MITARBEITER", erklaerung: "sAMAccountName des Vorgesetzten" },
|
|
{ schluessel: "dn", quelle: "MITARBEITER", erklaerung: "Distinguished Name im Verzeichnis" },
|
|
|
|
// Aus der Abteilung
|
|
{
|
|
schluessel: "ou",
|
|
quelle: "ABTEILUNG",
|
|
erklaerung: "Ziel-Container: Eltern-Container des dn, sonst die Ziel-OU der Abteilung",
|
|
},
|
|
{ schluessel: "gruppen", quelle: "ABTEILUNG", erklaerung: "Standardgruppen, kommagetrennt" },
|
|
|
|
// Besonders
|
|
{
|
|
schluessel: "generiertes_passwort",
|
|
quelle: "BESONDERS",
|
|
erklaerung:
|
|
"20 Zeichen, bei jeder Anzeige neu erzeugt und nirgends gespeichert — auch nicht im Protokoll",
|
|
},
|
|
];
|
|
|
|
export const QUELLEN_TEXT: Record<PlatzhalterQuelle, string> = {
|
|
GERAET_LAUF: "Gerät und Lauf",
|
|
MITARBEITER: "Mitarbeiter",
|
|
ABTEILUNG: "Abteilung",
|
|
BESONDERS: "Besonders",
|
|
};
|
|
|
|
const EINGEBAUTE_SCHLUESSEL: ReadonlySet<string> = new Set(
|
|
EINGEBAUTE_PLATZHALTER.map((platzhalter) => platzhalter.schluessel),
|
|
);
|
|
|
|
export function istEingebaut(schluessel: string): boolean {
|
|
return EINGEBAUTE_SCHLUESSEL.has(schluessel);
|
|
}
|
|
|
|
/**
|
|
* Eingebaute Platzhalter, die eine Vorlagenvariable **nicht** belegen darf.
|
|
*
|
|
* Es sind die fuenf, die eine Aussage ueber **wer, wann und fuer wen** machen:
|
|
*
|
|
* - `techniker` und `datum` unterschreiben einen Befehl. Eine Variable dafuer
|
|
* hiesse, dass in einem fertigen Befehl ein fremder Name und ein falsches
|
|
* Datum stehen koennen, ohne dass es auffaellt.
|
|
* - `kunde` und `kundenkuerzel` sind im Modus INTERN ausdruecklich leer (#008).
|
|
* Eine Variable haette die Kundenebene in den Befehl zurueckgeholt, die es
|
|
* dort nicht gibt.
|
|
* - `generiertes_passwort` wird ohnehin vor jeder Zuordnung abgefangen; hier
|
|
* steht es, damit niemand eine Variable anlegt, die nie wirkt.
|
|
*
|
|
* Alles andere bleibt erlaubt, und das ist wichtig: beim Onboarding gibt es die
|
|
* Person im Verzeichnis noch nicht, die Vorlage fragt `upn`, `sam` und `mail`
|
|
* also selbst ab. Genau dafuer sind Variablen da.
|
|
*/
|
|
export const GESPERRTE_VARIABLENNAMEN: ReadonlySet<string> = new Set([
|
|
"techniker",
|
|
"datum",
|
|
"kunde",
|
|
"kundenkuerzel",
|
|
"generiertes_passwort",
|
|
]);
|
|
|
|
/** Darf eine Vorlagenvariable so heissen? */
|
|
export function istAlsVariableErlaubt(schluessel: string): boolean {
|
|
return !GESPERRTE_VARIABLENNAMEN.has(schluessel);
|
|
}
|
|
|
|
/**
|
|
* Die Platzhalter, die weder eingebaut noch als Variable definiert sind.
|
|
*
|
|
* Das ist eine **Warnung**, keine Ablehnung: ein Tippfehler faellt so im Editor
|
|
* auf, statt erst dem Techniker im Lauf. Speichern und Veroeffentlichen bleiben
|
|
* erlaubt — es kann gute Gruende geben, einen Platzhalter stehen zu lassen, etwa
|
|
* wenn die Variable noch kommt.
|
|
*/
|
|
export function unbekanntePlatzhalter(
|
|
verwendete: readonly string[],
|
|
variablenSchluessel: readonly string[],
|
|
): readonly string[] {
|
|
const bekannt = new Set(variablenSchluessel);
|
|
return verwendete.filter((schluessel) => !bekannt.has(schluessel) && !istEingebaut(schluessel));
|
|
}
|
|
|
|
/** Variablen, die definiert sind, aber nirgends verwendet werden. */
|
|
export function unbenutzteVariablen(
|
|
verwendete: readonly string[],
|
|
variablenSchluessel: readonly string[],
|
|
): readonly string[] {
|
|
const benutzt = new Set(verwendete);
|
|
return variablenSchluessel.filter((schluessel) => !benutzt.has(schluessel));
|
|
}
|