@ff-admin/core-server (1.0.1)

Published 2026-02-27 17:23:08 +00:00 by jkeffects in FF-Admin/ff-admin-core-server

Installation

@ff-admin:registry=
npm install @ff-admin/core-server@1.0.1
"@ff-admin/core-server": "1.0.1"

About this package

ff-admin-core-server

Core-Funktionalität für ff-admin Server-Anwendungen als wiederverwendbares npm-Package.

Package Content

📋 Inhaltsverzeichnis

Übersicht

@ff-admin/core-server bietet eine vollständige Basis-Infrastruktur für FF-Admin Server-Anwendungen mit Fokus auf Benutzerverwaltung, Authentifizierung, Autorisierung und WebSocket-Kommunikation. Das Package ermöglicht die Verwendung und Entwicklung von Funktionen als Basis für mehrere Anwendungen und eine konsistente API-Struktur sicherzustellen.

Was übernimmt das Package?

🔐 Authentifizierung & Autorisierung

  • JWT-basierte Authentifizierung - Sichere Token-basierte Authentifizierung
  • Passkey-Unterstützung - Moderne WebAuthn/Passkey-Integration
  • Session-Management - Verwaltung von Benutzersitzungen
  • Refresh-Tokens - Automatische Token-Erneuerung
  • Reset-Funktionalität - Zugangs-Reset
  • WebAPI-Tokens - Authentifizierung für externe API-Zugriffe

👥 Benutzerverwaltung

  • User Entity - Vollständiges Benutzermodell mit TypeORM
  • Rollen & Berechtigungen - Flexibles rollenbasiertes Berechtigungssystem
  • Account-Management - Einheitlicher Zugriff auf Account-Funktionen
  • Benachrichtigungen - Benachrichtigungssystem für Benutzer
  • Device-Verwaltung - Tracking und Verwaltung von Geräten/Sessions

🛠️ Admin-Funktionalität

  • Einladungssystem - Verwaltung von Einladungen für neue Benutzer
  • Rollenverwaltung - CRUD-Operationen für Rollen
  • Berechtigungssystem - Granulare Berechtigungen auf User- und Rollenebene
  • WebAPI-Verwaltung - Verwaltung von API-Keys und Berechtigungen
  • Moduleinstellungen - Konfigurierbare Module und Einstellungen
  • Einstellungsverwaltung - Application- und Module-Settings

🌐 REST API Routes

Das Package stellt folgende fertige API-Endpunkte bereit:

  • /api/public - Öffentliche Endpunkte (Setup-Check, etc.)
  • /api/setup - Initiale Setup-Konfiguration
  • /api/reset - Passwort-Reset-Funktionalität
  • /api/invite - Einladungsverwaltung
  • /api/auth - Authentifizierung (Login, Logout, etc.)
  • /api/webapi - WebAPI-Token-Verwaltung
  • /api/admin - Admin-Funktionen (Benutzer, Rollen, etc.)
  • /api/account - Account-Management für eingeloggte Benutzer
  • /api/server - Server-Verwaltung und Informationen

🔌 WebSocket-Unterstützung

  • Socket.IO Integration - Vollständige WebSocket-Unterstützung
  • Namespace-System - Erweiterbare Socket-Namespaces
  • Socket-Authentifizierung - JWT-basierte WebSocket-Authentifizierung
  • Admin UI - Socket.IO Admin Panel für Development

🧰 Helper-Funktionen

  • JWTHelper - Token-Generierung und -Validierung
  • PasskeyHelper - WebAuthn-Operationen
  • PermissionHelper - Berechtigungsprüfungen und Middlewares
  • MailHelper - E-Mail-Versand
  • BackupHelper - Automatische Datenbank-Backups
  • NotificationHelper - Benachrichtigungsverwaltung
  • SettingsHelper - Einstellungsverwaltung
  • DateHelper - Datums- und Zeitoperationen
  • FileSystemHelper - Dateisystem-Operationen
  • StringHelper - String-Manipulationen
  • und weitere...

🛡️ Middlewares

  • Authentication - JWT- und WebAPI-Authentifizierung
  • Access Control - Permissions- und Role-basierter Zugriff
  • Rate Limiting - Schutz vor Brute-Force-Angriffen
  • Error Handling - Zentralisierte Fehlerbehandlung
  • File Upload - Multer-basierter File-Upload
  • Device Detection - Automatische Geräteerkennung
  • PWA Detection - Progressive Web App Erkennung

📦 TypeORM Integration

  • Entities - Vordefinierte Datenbank-Entities für alle Basis-Funktionen
  • CQRS Pattern - Commands und CommandHandlers für Datenbankoperationen
  • Factories - Factory-Pattern für Entitäten
  • Services - Geschäftslogik-Services
  • ViewModels - Optimierte Datenstrukturen für API-Responses

Cron Jobs

  • Tägliche Wartung - Automatische Bereinigung abgelaufener Tokens/Sessions
  • Backup-Automation - Automatische Backups zu konfigurierten Zeitpunkten
  • Erweiterbare Hooks - Eigene Cron-Jobs über registerDailyCronHook hinzufügen

🔧 Exception Handling

  • CustomRequestException - Basisklasse für API-Exceptions
  • BadRequestException - 400 Fehler
  • UnauthorizedRequestException - 401 Fehler
  • ForbiddenRequestException - 403 Fehler
  • InternalException - 500 Fehler
  • DatabaseActionException - Datenbank-spezifische Fehler

Installation

npm install @ff-admin/core-server

Peer Dependencies

Das Package benötigt folgende Peer Dependencies:

  • express >= 5.0.0
  • typeorm >= 0.3.0
  • reflect-metadata

Konfiguration

1. DataSource konfigurieren

Das Package benötigt eine TypeORM DataSource. Diese muss in der Anwendung konfiguriert und an das Package übergeben werden:

import { DataSource } from "typeorm";
import { DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME, DB_SCHEMA, configureDataSource, baseTables } from "@ff-admin/core-server";

const AppDataSource = new DataSource({
  type: "postgres",
  host: DB_HOST,
  port: DB_PORT,
  username: DB_USER,
  password: DB_PASSWORD,
  database: DB_NAME,
  schema: DB_SCHEMA,
  entities: [...baseTables, ...applicationTables],
  migrations: [...applicationMigrations],
  synchronize: false,
});

// DataSource dem Package übergeben
configureDataSource(AppDataSource);

await AppDataSource.initialize();

Wichtig: Die Datenbank-Connection und Migrationen werden von der Anwendung verwaltet, nicht vom Package!

2. Umgebungsvariablen

Das Package erwartet folgende Umgebungsvariablen und veröffentlicht diese auch. Das Package prüft zudem den Inhalt der ENV-Variablen und setzt default Werte, sollte eine ENV nicht verwendet werden.

DB_PORT = 5432
DB_HOST = database_host
DB_NAME = database_name
DB_USERNAME = database_username
DB_PASSWORD = database_password

APPLICATION_SECRET = mysecret

USE_SECURITY_STRICT_LIMIT = (true|false) # default ist true
SECURITY_STRICT_LIMIT_WINDOW = [0-9]*(y|d|h|m|s) # default ist 15m
SECURITY_STRICT_LIMIT_REQUEST_COUNT = strict_request_count # default ist 15
USE_SECURITY_LIMIT = (true|false) # default ist true
SECURITY_LIMIT_WINDOW = [0-9]*(y|d|h|m|s) # default ist 1m
SECURITY_LIMIT_REQUEST_COUNT = request_count # default ist 500

TRUST_PROXY = <boolean|number|ip|ip1,ip2,...> # wenn leer, wird dieser Wert nicht angewendet.

3. Package Config Vals

Setzen der anwendungsspezifischen Konfigurationswerte:

import { PackageConfigVals } from "@ff-admin/core-server";

PackageConfigVals.serverRSSFeedLink = "https://git.your-server.com/server/rss-feed";
PackageConfigVals.clientRSSFeedLink = "https://git.your-server.com/client/rss-feed";

4. Konfiguration bzw. Erweiterung der PackageTypen

Das Package stellt Basis-Typen bereit, welche in der Anwendung erweitert werden können. Eine Ausführliche Information gibt es weiter unten: [Erweiterungen](## Erweiterung)

Verwendung

Express App Setup

import express, { Express } from "express";
import cors from "cors";
import helmet from "helmet";
import morgan from "morgan";
import {
  // Routes
  auth,
  invite,
  reset,
  setup,
  publicAvailable,
  account,
  admin,
  applicationRouter,
  webapi,
  server,
  // Middlewares
  authenticate,
  authenticateAPI,
  preventWebapiAccess,
  allowSetup,
  detectPWA,
  extractDeviceInfo,
  httpApiAvailable,
  errorHandler,
  strictLimiter,
  generalLimiter,
  excludePaths,
  // Helpers
  PermissionHelper,
} from "@ff-admin/core-server";

export const setupApp = (app: Express) => {
  // Express-Konfiguration
  if (process.env.TRUST_PROXY) {
    app.set("trust proxy", process.env.TRUST_PROXY);
  }
  app.set("query parser", "extended");

  // Security & Logging
  app.use(cors());
  app.options("*", cors());
  app.use(helmet());
  app.use(morgan("combined"));

  // Body Parser
  app.use(express.json());
  app.use(express.urlencoded({ extended: true }));

  // API Verfügbarkeit
  app.use(httpApiAvailable);

  // Device Detection
  app.use(detectPWA);
  app.use(extractDeviceInfo);

  // Public Routes
  app.use("/api/public", publicAvailable);
  // Hinzufügen der anwendungsspezifischen Public Routes
  // app.use("/api/public", yourPublicRoutes);

  // Setup, Reset, Invite (mit Rate Limiting)
  app.use("/api/setup", strictLimiter, preventWebapiAccess, allowSetup, setup);
  app.use("/api/reset", strictLimiter, preventWebapiAccess, reset);
  app.use("/api/invite", strictLimiter, preventWebapiAccess, invite);

  // Authentication
  app.use("/api/auth", strictLimiter, preventWebapiAccess, auth);

  // WebAPI Routes
  app.use("/api/webapi", authenticateAPI, webapi);

  // Authentifizierung für alle folgenden Routes
  app.use(authenticate);

  // General Rate Limiting (mit Ausnahmen)
  app.use(excludePaths(generalLimiter, ["/synchronize"]));

  // Admin Routes
  app.use("/api/admin", admin);
  app.use("/api/admin", /* Anwendungs- Admin-Routes */);

  // Application routes
  app.use("/api/application", applicationRouter);

  // Account Routes
  app.use("/api/account", preventWebapiAccess, account);

  // Server Routes (nur für Admins)
  app.use("/api/server", preventWebapiAccess, PermissionHelper.isAdminMiddleware(), server);

  // Error Handler (muss am Ende sein!)
  app.use(errorHandler);
};

WebSocket Setup

import { createServer } from "http";
import { SocketServer } from "@ff-admin/core-server";

const httpServer = createServer(app);

// Socket.IO initialisieren
SocketServer.init(httpServer);

// Eigene Socket-Namespace-Hooks registrieren (optional)
SocketServer.registerSocketNamespaceHook((io) => {
  io.of("/my-namespace")
    .on("connection", (socket) => {
        console.log("socket connection: ", socket.id);
        socketBase(this.io, socket);
    });
});

// App-Namespace-Hooks registrieren (optional)
SocketServer.registerAppNamespaceHook((io, socket) => {
  socket.on("myCustomEvent", (data) => {
    // Handle custom events
  });
});

httpServer.listen(3000);

Eigene Routes erstellen

import { Router } from "express";
import { PermissionHelper, authenticate } from "@ff-admin/core-server";

const router = Router();

// Route mit Authentifizierung
router.get("/my-endpoint", authenticate, async (req, res) => {
  // req.userId, req.username, req.permissions sind verfügbar
  res.json({ message: "Hello " + req.username });
});

// Route mit Berechtigungsprüfung
router.post(
  "/admin-endpoint",
  authenticate,
  PermissionHelper.check("admin.write"),
  async (req, res) => {
    // Nur für Benutzer mit admin.write Berechtigung
    res.json({ success: true });
  }
);

export default router;

Commands verwenden

Das Package verwendet ein CQRS-Pattern. Das Package stellt CommandHandlers für Datenbankoperationen bereit:

import { UserCommandHandler, CreateUserCommand, UpdateUserCommand } from "@ff-admin/core-server";

// Benutzer erstellen
const createCommand: CreateUserCommand = {
  username: "john.doe",
  email: "john@example.com",
  firstname: "John",
  lastname: "Doe",
  password: "securePassword123",
};

const newUser = await UserCommandHandler.create(createCommand);

// Benutzer aktualisieren
const updateCommand: UpdateUserCommand = {
  id: newUser.id,
  firstname: "Jane",
};

await UserCommandHandler.update(updateCommand);

Helpers verwenden

import {
  JWTHelper,
  PermissionHelper,
  MailHelper,
  NotificationHelper,
} from "@ff-admin/core-server";

// JWT erstellen
const token = JWTHelper.sign({ userId: "123", username: "john" });

// JWT validieren
const payload = JWTHelper.verify(token);

// Berechtigungen prüfen
const hasPermission = PermissionHelper.check("admin.users.write");

// E-Mail senden
await MailHelper.send({
  to: "user@example.com",
  subject: "Welcome",
  html: "<h1>Welcome to our platform</h1>",
});

// Benachrichtigung erstellen
await NotificationHelper.create({
  userId: "123",
  title: "New Message",
  message: "You have a new message",
});

Cron Jobs erweitern

import { registerDailyCronHook } from "@ff-admin/core-server";

// Eigene tägliche Wartungsaufgabe registrieren
registerDailyCronHook(async () => {
  console.log("Running custom daily maintenance task");
  // Ihre Logik hier
  await cleanupOldData();
});

Erweiterung

TypeScript Type Declarations erweitern

Das Package bietet mehrere Interfaces, die in der Anwendung erweitern werden können, um anwendungsspezifische Funktionalität hinzuzufügen.

SocketNamespaceMap

Erweitern der Socket.IO Namespaces:

declare module "@ff-admin/core-server" {
  interface SocketNamespaceMap {
    myCustomNamespace: "/custom";
    anotherNamespace: "/another";
  }
}

import { configureSocketNamespace, SocketNamespace } from "@ff-admin/core-server";

// Namespaces konfigurieren
configureSocketNamespace({
  myCustomNamespace: "/custom",
  anotherNamespace: "/another",
});

// Verwendung
console.log(SocketNamespace.myCustomNamespace); // "/custom"
const namespace: SocketNamespace = SocketNamespace.app; // Type-safe

PermissionSectionMap & PermissionModuleMap

Erweitern des Berechtigungssystem um eigene Sections und Module:

declare module "@ff-admin/core-server" {
  interface PermissionSectionMap {
    // Eigene Berechtiungs-Section hinzufügen
    mySection: void;
  }

  interface PermissionModuleMap {
    // Eigene Berechtigungs-Module hinzufügen
    myModule: void;
    anotherModule: void;
  }
}

// Verwendung im Code
import { PermissionHelper } from "@ff-admin/core-server";

// Nachfolgende Funktionen werden benötigt, um die Werte neben den Typen verfügbar zu machen.
extendPermissionSections(/** ... */)
extendPermissionModules(/** ... */)
configureSectionsAndModules(/** ... */)

ModuleSettingTopicMap & ModuleSettingValueMapping

Erweitern der Modul-Einstellungen um eigene Topics und Settings:

declare module "@ff-admin/core-server" {
  interface ModuleSettingTopicMap {
    myModule: void;
  }

  interface ModuleSettingValueMapping {
    "myModule.setting1": string;
    "myModule.setting2": number;
    "myModule.enabled": boolean;
  }
}

import { 
  configurModuleSettingsType, 
  ModuleSettingsSchema 
} from "@ff-admin/core-server";

// Schema für die neuen Settings definieren
configurModuleSettingsType({
  "myModule.setting1": { 
    type: "string", 
    default: "default value" 
  },
  "myModule.setting2": { 
    type: "number", 
    default: 42 
  },
  "myModule.enabled": { 
    type: "boolean", 
    default: false 
  },
});

// Verwendung
import { SettingsHelper } from "@ff-admin/core-server";

const setting = await SettingsHelper.getModuleSetting("myModule.setting1");
await SettingsHelper.setModuleSetting("myModule.enabled", true);

SettingTopicMap & SettingValueMapping

Erweitern der Application-Einstellungen um eigene Topics und Settings:

declare module "@ff-admin/core-server" {
  interface SettingTopicMap {
    myApp: void;
  }

  interface SettingValueMapping {
    "myApp.apiKey": string;
    "myApp.timeout": number;
    "myApp.baseUrl": string;
  }
}

import { 
  configurSettingsType, 
  SettingsSchema 
} from "@ff-admin/core-server";

// Schema für die neuen Settings definieren
configurSettingsType({
  "myApp.apiKey": { 
    type: "string", 
    optional: true 
  },
  "myApp.timeout": { 
    type: "number", 
    default: 5000 
  },
  "myApp.baseUrl": { 
    type: "url", 
    default: "https://api.example.com" 
  },
});

// Verwendung
import { SettingsHelper } from "@ff-admin/core-server";

const apiKey = await SettingsHelper.getSetting("myApp.apiKey");
await SettingsHelper.setSetting("myApp.timeout", 10000);

Eigene Entities

Erweitern der Package-Entities oder erstellen eigener:

import { Entity, Column, ManyToOne } from "typeorm";
import { User } from "@ff-admin/core-server";

@Entity()
export class CustomUserData {
  @Column()
  someCustomField: string;

  @ManyToOne(() => User)
  user: User;
}

Eigene Datenbanktabellen können direkt in der Anwendung angelegt werden. Soll eine bestehende Entität des packages erweitert werden, so kann eine eigene Entity von der Entität des Packages erben. Jedoch müssen dann auch alle Abhängigkeiten zu dieser Ursprungsentität ersetzt und in der Anwendung neue implementiert werden.

Routen überschreiben

Die vom Package bereitgestellten Routen können in der Anwendung jederzeit überschrieben werden. Express verwendet Pattern-Matching für Routes, wobei die zuerst definierte Route Vorrang hat.

import express from "express";
import { 
  auth,           // Package-Route
  authenticate 
} from "@ff-admin/core-server";

const app = express();

// Eigene Login-Route, die die Package-Route überschreibt
app.post("/api/auth/login", async (req, res) => {
  // Ihre angepasste Implementierung
  console.log("Custom login logic");
  // ...
  res.json({ success: true });
});

// Package-Route wird hinzugefügt, aber /api/auth/login ist bereits definiert
// Daher wird die obige Route für /login verwendet
app.use("/api/auth", auth);

// Alternativ: Nur bestimmte Endpunkte vom Package nutzen
app.post("/api/auth/login", customLoginHandler);      // Überschrieben
app.use("/api/auth", auth);                            // Andere Endpunkte vom Package

Wichtig: Definieren Sie Ihre benutzerdefinierten Routen vor den Package-Routen, um sicherzustellen, dass Ihre Implementierung verwendet wird.

Beispiel - Teilweises Überschreiben:

// Setup-Endpunkt mit zusätzlicher Validierung überschreiben
app.post("/api/setup/initial", 
  customValidationMiddleware, 
  customSetupHandler
);

// Restliche Setup-Routen vom Package verwenden
app.use("/api/setup", strictLimiter, preventWebapiAccess, allowSetup, setup);

API-Dokumentation

Express Request Extensions

Das Package erweitert das Express Request-Objekt um folgende Properties:

interface Request {
  userId: string;              // ID des authentifizierten Benutzers
  username: string;            // Username des Benutzers
  firstname: string;           // Vorname
  lastname: string;            // Nachname
  isOwner: boolean;           // Ist der Benutzer Owner?
  permissions: PermissionObject; // Berechtigungsobjekt
  isPWA: boolean;             // Zugriff über PWA?
  isWebApiRequest: boolean;   // Zugriff über WebAPI?
  deviceFingerprint: string;  // Geräte-Fingerprint
  deviceName: string;         // Gerätename
}

Wichtige Exports

Das Package exportiert folgende Hauptkomponenten:

  • Commands - CQRS Commands und CommandHandlers
  • Controllers - Controller für API-Endpunkte
  • Entities - TypeORM Entities
  • Enums - API-Status, Login-Routinen, Socket-Namespaces
  • Exceptions - Custom Exception-Klassen
  • Factories - Factory-Pattern Implementierungen
  • Helpers - Utility-Funktionen
  • Middlewares - Express-Middlewares
  • Routes - Fertige API-Routes
  • Services - Business-Logic Services
  • Types - TypeScript Type Definitions
  • ViewModels - API Response Models
  • WebSocket - Socket.IO Konfiguration

Lizenz

AGPL-3.0-only

Author

JK Effects

Repository

https://code.jk-effects.cloud/FF-Admin/ff-admin-core-server.git

Dependencies

Dependencies

ID Version
@simplewebauthn/server ^13.2.2
cors ^2.8.6
crypto ^1.0.1
dotenv ^17.2.4
express ^5.2.1
express-rate-limit ^8.2.1
express-validator ^7.3.1
helmet ^8.1.0
ip-address ^10.1.0
jsonwebtoken ^9.0.3
lodash.clonedeep ^4.5.0
lodash.uniqby ^4.7.0
moment ^2.30.1
morgan ^1.10.1
ms ^2.1.3
multer ^2.0.2
node-schedule ^2.1.1
nodemailer ^8.0.0
qrcode ^1.5.4
reflect-metadata ^0.2.2
rss-parser ^3.13.0
sharp ^0.34.5
sharp-ico ^0.1.5
socket.io ^4.8.3
speakeasy ^2.0.0
typeorm ^0.3.28
ua-parser-js ^2.0.9
uuid ^13.0.0
validator ^13.15.26

Development dependencies

ID Version
@socket.io/admin-ui ^0.5.1
@types/cors ^2.8.19
@types/express ^5.0.6
@types/ip ^1.1.3
@types/jsonwebtoken ^9.0.10
@types/lodash.clonedeep ^4.5.9
@types/lodash.uniqby ^4.7.9
@types/morgan ^1.9.10
@types/ms ^2.1.0
@types/multer ^2.0.0
@types/node ^25.2.1
@types/node-schedule ^2.1.8
@types/nodemailer ^7.0.9
@types/qrcode ~1.5.6
@types/speakeasy ^2.0.10
@types/uuid ^11.0.0
@types/validator ^13.15.10
ts-node 10.9.2
tsc-alias ^1.8.16
typescript ^5.9.3

Keywords

Feuerwehr ff-admin
Details
npm
2026-02-27 17:23:08 +00:00
5
JK Effects
AGPL-3.0-only
latest
1.6 MiB
Assets (1)
Versions (2) View all
1.0.1 2026-02-27
1.0.0 2026-02-24