Zum Inhalt springen

Hook-Referenz: Sicherheit und Identität

In Hooks sprichst du diese sieben Pakete über context an, zum Beispiel zum Token-Erstellen, Passwort-Hashen oder Cookie-Setzen. Die Signaturen stammen aus den // args:-Kommentaren in internal/hook/context_*.go im tibi-server; wo so ein Kommentar fehlt, ist die Signatur aus dem Funktionsrumpf abgeleitet und entsprechend markiert. Jede Funktion zeigt genau einen Fehlerfall mit dem originalen Error-Text aus Code oder Tests (Hook-Fehler enden im Test mit Status 500).

Quelle: context_jwt.go, registriert per RegisterPackageFunctions("jwt", ...) mit create und parse. Ohne secret-Option nutzt der Server ein zufälliges Temporär-Secret (jwtTempSecret, context_jwt.go:21).

Signatur: jwt.create(claims: object, options?: { validityDuration?: number, secret?: string }): string — aus // args: claims:map[string]interface{}, options:map[string]interface{} (context_jwt.go:27). validityDuration setzt exp auf jetzt plus Sekunden.

jwt.create – Beispiel
;(function () {
const token = context.jwt.create({ sub: "user123", role: "admin" }, { validityDuration: 3600 })
throw { status: 200, json: { token: token } }
})()

Fehlerfall (Error): Ohne Claims brichst du mit missing claims in jwt.create function ab, Status 500 (error - missing claims, context_jwt_test.go:109); Claims als String statt Objekt: claims must be object in jwt.create function (context_jwt.go:42).

Signatur: jwt.parse(token: string, options?: { secret?: string }): object — aus // args: token:string, options:map[string]interface{} (context_jwt.go:84). Antwortet mit { valid, claims, header, method, error? } und wirft bei ungültigen Tokens keinen Error: falsches Secret oder abgelaufenes Token liefern valid: false plus error-Text bei Status 200.

jwt.parse – Beispiel
;(function () {
const token = context.jwt.create({ sub: "user123" }, { secret: "s3cr3t" })
const res = context.jwt.parse(token, { secret: "s3cr3t" })
throw { status: 200, json: { valid: res.valid } }
})()

Fehlerfall (Error): Ohne Token: missing token in jwt.parse function, Status 500 (error - missing token, context_jwt_test.go:120); Token als Nicht-String: token must be string in jwt.parse function (context_jwt.go:96).

Quelle: context_user.go, registriert per RegisterPackageFunctions("user", ...) mit auth. Liefert { id, username, role, permissions } oder null ohne Login.

Signatur (abgeleitet): user.auth(): object | null — kein args:-Kommentar, abgeleitet aus dem Rumpf FuncUserAuth (context_user.go:16): nimmt keine Argumente und liest den API-Kontext.

user.auth – Beispiel
;(function () {
const me = context.user.auth()
throw { status: 200, json: { login: me !== null, name: me && me.username } }
})()

Fehlerfall (Error): Außerhalb von Hooks (ohne API-Kontext) scheitert der Aufruf mit user.auth is only valid in hooks (context_user.go:19); ohne Login bekommst du null zurück, keinen Error (auth not logged in, context_user_test.go:44).

Quelle: context_bcrypt.go, registriert per RegisterPackageFunctions("bcrypt", ...) mit hash und check.

Signatur: bcrypt.hash(password: string, options?: { cost?: number }): string — aus // args: password:string, options:map[string]interface{} (context_bcrypt.go:18); Standard-cost ist 14.

bcrypt.hash – Beispiel
;(function () {
const hash = context.bcrypt.hash("s3cr3t-pw")
throw { status: 200, json: { hash: hash } }
})()

Fehlerfall (Error): Ohne Passwort: missing password in bcrypt.hash function, Status 500 (error - missing password, context_bcrypt_test.go:91); falscher cost-Typ: invalid type for costs in bcrypt.hash function — so wörtlich im Code, mit Plural-s (context_bcrypt.go:42).

Signatur: bcrypt.check(password: string, hash: string): boolean — aus // args: password:string, hash:string (context_bcrypt.go:56). Ein falsches Passwort liefert false, keinen Error.

bcrypt.check – Beispiel
;(function () {
const hash = context.bcrypt.hash("s3cr3t-pw")
const ok = context.bcrypt.check("s3cr3t-pw", hash)
throw { status: 200, json: { match: ok } }
})()

Fehlerfall (Error): Weniger als zwei Argumente: missing password and/or hash in bcrypt.check function, Status 500 (error - missing args in check, context_bcrypt_test.go:102).

Quelle: context_crypto.go, registriert per RegisterPackageFunctions("crypto", ...) mit sha256 und md5. Das sind Einweg-Hashes für Prüfsummen, kein Passwort-Hashing — dafür nimmst du das bcrypt-Paket.

Signatur: crypto.sha256(text: string): string — aus // args: string:string (context_crypto.go:19). Liefert Hex, belegt mit "hello" → 2cf24dba…9824 in context_crypto_test.go:22.

crypto.sha256 – Beispiel
;(function () {
const sum = context.crypto.sha256("hello")
throw { status: 200, json: { sha256: sum } }
})()

Fehlerfall (Error): Ohne Argument: missing string in crypto.sha256 function, Status 500 (error - sha256 missing argument, context_crypto_test.go:77).

Signatur: crypto.md5(text: string): string — aus // args: string:string (context_crypto.go:33). Liefert Hex, belegt mit "hello" → 5d41402a…c592 in context_crypto_test.go:44.

crypto.md5 – Beispiel
;(function () {
const sum = context.crypto.md5("hello")
throw { status: 200, json: { md5: sum } }
})()

Fehlerfall (Error): Ohne Argument: missing string in crypto.md5 function, Status 500 (error - md5 missing argument, context_crypto_test.go:88).

Quelle: context_cookie.go, registriert per RegisterPackageFunctions("cookie", ...) mit get und set. Beide brauchen einen Hook-HTTP-Kontext.

Signatur: cookie.get(name: string): string — aus // args: name:string (context_cookie.go:17). Unbekannte Cookies liefern "", keinen Error.

cookie.get – Beispiel
;(function () {
const session = context.cookie.get("session")
throw { status: 200, json: { hasSession: session !== "" } }
})()

Fehlerfall (Error): Ohne Namen: missing cookie name in cookie.get, Status 500 (error - missing cookie name, context_cookie_test.go:55); außerhalb von Hooks: cookie functions only valid in hooks (context_cookie.go:20).

Signatur: cookie.set(name: string, data: string, options?: object): void — aus // args: name:string options:map[string]interface{} (context_cookie.go:40). options kennt maxAge, path, domain, httpOnly, secure und sameSite (strict, lax oder none).

cookie.set – Beispiel
;(function () {
context.cookie.set("session", "abc123", { maxAge: 3600, path: "/", httpOnly: true, sameSite: "lax" })
throw { status: 200, json: { set: true } }
})()

Fehlerfall (Error): Weniger als zwei Argumente: missing cookie name and/or data in cookie.set, Status 500 (error - missing cookie data, context_cookie_test.go:66); unbekanntes sameSite: invalid value for sameSite in cookie.set function (context_cookie.go:136).

Quelle: context_exec.go, registriert per RegisterPackageFunctions("exec", ...) mit command. Läuft mit Timeout (Standard 10000 ms) im Projektverzeichnis und unter der Config-UID.

Signatur: exec.command(command: string, options?: { args?: Array, stdin?: string, dir?: string, env?: Array, timeout?: number, returnObject?: boolean, combineOutput?: boolean }): string | object — aus // args: command:string, options:map[string]interface{} (context_exec.go:22). Ohne returnObject kommt stdout als String; mit returnObject: true antwortet { stdout, stderr, exitCode } (bzw. { output, exitCode } mit combineOutput).

exec.command – Beispiel
;(function () {
const out = context.exec.command("echo", { args: ["Hallo Hook"] })
throw { status: 200, json: { result: out } }
})()

Fehlerfall (Error): Ohne Kommando: missing command in exec.command function (context_exec.go:38); Exit-Code ungleich 0 ohne returnObject: exec.command failed with exit code 1, Status 500 (test exec command error case, context_exec_test.go:65); bei Timeout: exec.command timed out after ... ms (context_exec.go:183).

Quelle: context_config.go, registriert per RegisterPackageFunctions("config", ...) mit namespace, project und server. Alle drei ohne args:-Kommentar — Signaturen aus den Rümpfen abgeleitet (context_config.go:19, :23, :27).

Signatur (abgeleitet): config.namespace(): string — liefert den Namespace, nimmt keine Argumente.

config.namespace – Beispiel
;(function () {
const ns = context.config.namespace()
throw { status: 200, json: { namespace: ns } }
})()

Fehlerfall: Kein Fehlerfall — namespace liest nur ein Feld und kennt keinen Error-Pfad (dokumentierte Abwesenheit, kein Versäumnis).

Signatur (abgeleitet): config.project(): object — liefert die Projekt-Config als Map, nimmt keine Argumente.

config.project – Beispiel
;(function () {
const project = context.config.project()
throw { status: 200, json: { name: project.name } }
})()

Fehlerfall: Kein Fehlerfall — project mappt nur die Config und kennt keinen Error-Pfad (dokumentierte Abwesenheit, kein Versäumnis).

Signatur (abgeleitet): config.server(): object — liefert die Server-Config als Map, nimmt keine Argumente.

config.server – Beispiel
;(function () {
const server = context.config.server()
throw { status: 200, json: { port: server.api && server.api.port } }
})()

Fehlerfall (Error): Kein fixer Error-String im Code — nur interne JSON-Marshal-Fehler werden durchgereicht (context_config.go:30); im Test läuft der Aufruf fehlerfrei mit Status 200 (context_config_test.go:19).

Weiter: Hook-Kontexte als Paket-Index, Hooks schreiben für Lifecycle und Starter-Muster.

Verifiziert am 68b4278 2026-10-16 (tibi-server)