Files
mpm/modules/demo/backend/platform-module-sdk.js

100 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* MPM Modul-SDK – Authentifizierungs-Helper (Phase 6).
* CommonJS-Variante (Module laufen als Node-CommonJS-Prozesse).
*
* Jedes Modul läuft hinter dem Modul-Gateway der Management-Plattform.
* Der Gateway authentifiziert den Benutzer zentral und übergibt die
* Identität über interne Header. Module dürfen diese Header NIE
* direkt von außen akzeptieren – deshalb stellt dieses SDK sicher,
* dass die Identität nur aus dem Gateway-Flow stammt.
*
* Sicherheitsregeln:
* - Module lauschen nur auf 127.0.0.1 (nie öffentlich erreichbar)
* - Der Gateway entfernt das Session-Cookie vor dem Proxy
* - Identitäts-Header werden vom Gateway gesetzt, nicht vom Client
*/
/** Identitäts-Header, die der Modul-Gateway setzt. */
const GATEWAY_HEADERS = {
userId: 'x-user-id',
username: 'x-user-username',
displayName: 'x-user-display-name',
role: 'x-user-role',
};
/** Vom Gateway übergebene Benutzer-Identität. */
// interface GatewayIdentity {
// userId: string;
// username: string;
// displayName: string;
// role: 'ADMIN' | 'USER';
// }
/**
* Extrahiert die Benutzer-Identität aus den Gateway-Headern.
* @returns Identität oder null, wenn der Request nicht über den
* Gateway kam (z. B. direkter Aufruf ohne Plattform).
*/
function extractIdentity(headers) {
const userId = readHeader(headers, GATEWAY_HEADERS.userId);
const username = readHeader(headers, GATEWAY_HEADERS.username);
const displayName = readHeader(headers, GATEWAY_HEADERS.displayName);
const role = readHeader(headers, GATEWAY_HEADERS.role);
if (!userId || !username || !role) {
return null;
}
if (role !== 'ADMIN' && role !== 'USER') {
return null;
}
return { userId, username, displayName: displayName ?? username, role };
}
/** Liest einen Header (case-insensitive, erster Wert). */
function readHeader(headers, name) {
const lowerName = name.toLowerCase();
for (const [key, value] of Object.entries(headers)) {
if (key.toLowerCase() === lowerName) {
if (Array.isArray(value)) {
return value[0] ?? null;
}
return value ?? null;
}
}
return null;
}
/**
* Standard-Antworten des Modul-API-Vertrags (Phase 6):
* Jedes Modul muss diese drei Endpunkte bereitstellen:
* GET /health → Liveness/Readiness
* GET /api/manifest → Manifest zur Laufzeit
* GET /api/me → Aktueller Benutzer (vom Gateway übergeben)
*/
/** Erstellt die /health-Antwort nach Vertrag. */
function healthResponse(moduleId, version) {
return { moduleId, version, status: 'healthy' };
}
/** Erstellt die /api/me-Antwort nach Vertrag. */
function meResponse(identity, moduleId, permissions = []) {
return {
user: {
id: identity.userId,
username: identity.username,
displayName: identity.displayName,
platformRole: identity.role,
},
module: { id: moduleId },
permissions,
};
}
module.exports = {
GATEWAY_HEADERS,
extractIdentity,
healthResponse,
meResponse,
};