CallMeTechie
EN Anmelden
Home Produkte Blog Über mich Kontakt

Lizenzschluessel einrichten

🚀 Installation & Setup · Updated vor 1 Monat

Feature-Checks anwenden

Der License-Service wird an drei Stellen gequeried:

1. Middleware — Server-side API-Guard

// src/routes/api/rdp.js
router.use(requireFeature('remote_desktop'));

requireFeature antwortet bei fehlendem Feature mit 403 {ok:false, feature, upgrade_url}. Für quantitative Limits gibt es requireLimit(key, countFn):

// src/routes/api/peers.js (schematisch)
router.post('/', requireLimit('vpn_peers', () => peers.count()), ...);

requireLimit unterscheidet drei Zustände: -1 → unbegrenzt, 0 → Feature nicht verfügbar (403), sonst Vergleich count >= limit.

2. Templates — UI-Gate

injectLicense stellt license.features in jedem View bereit:

{% if license.features.remote_desktop %}
  <a href="/rdp">RDP</a>
{% else %}
  <span class="lock-icon" title="Pro feature">…</span>
{% endif %}

Das UI zeigt gelockte Features normalerweise trotzdem an (mit Lock-Icon), um Upgrade-Pfade sichtbar zu machen.

3. Services — opportunistisch

Im Service-Layer werden Features abgefragt, um Nebenpfade zu überspringen:

// src/routes/api/gateway.js (Heartbeat-Handler)
if (body.hostname && hasFeature('internal_dns')) {
  peers.setHostname(peerId, body.hostname, 'agent');
}

Der Heartbeat selbst schlägt nicht fehl, wenn internal_dns aus ist — das Feld wird einfach ignoriert.

Enforcement bei Downgrade

Wenn ein Lizenzrefresh einen Plan-Wechsel erkennt (previousPlan !== cachedPlan), läuft enforceLimitsInternal():

  1. Für jedes Limit-Feature (vpn_peers, http_routes, l4_routes) wird die Ist-Menge gezählt.
  2. Ist count > limit, werden count - limit älteste Einträge (ORDER BY created_at ASC) auf enabled=0 gesetzt.
  3. WireGuard-Config bzw. Caddy-Config werden synchronisiert — deaktivierte Peers/Routes verschwinden vom Wire.
  4. Activity-Log-Eintrag peer_license_disabled / route_license_disabled.
  5. Optional Email-Alert wenn email_alerts_enabled=true.

Datensätze werden nie gelöscht. Ein späterer Upgrade reaktiviert sie nicht automatisch, aber der Admin sieht sie im UI als deaktiviert und kann manuell enable.

Pattern für neue Features

Bei jedem neuen kostenpflichtigen Feature müssen vier Dinge passieren (siehe feedback_new_feature_license.md):

  1. Flag in COMMUNITY_FALLBACK — meist false, als Limit meist 0.
  2. API-Guardrouter.use(requireFeature('X')) oder pro-Route.
  3. UI-Guard — Template-Wrap mit {% if license.features.X %} und Lock-Fallback.
  4. Service-Fallback — bei Downgrade darf kein Service crashen, sondern nur den Feature-Code-Pfad überspringen.

Key-Rotation und Removal

removeLicense() löscht das JWT, stoppt den Refresh-Timer, setzt Community-Mode, entfernt den Key aus der DB und startet Enforcement. _overrideForTest(features) patcht cachedFeatures direkt — nur für Test-Setup, nicht für Production.

Testen des Licensing-Systems

Der Service exportiert _overrideForTest und _getHardwareFingerprint für Testharnesse. In Test-Setup wird der echte Refresh-Timer nicht gestartet (keine startLicenseRefresh()-Call), damit Tests determiniert bleiben.

Siehe auch

Quelldateien

  • src/services/license.js — Kern-Service, COMMUNITY_FALLBACK, validateLicense, enforceLimitsInternal.
  • src/middleware/license.jsinjectLicense, requireFeature, requireLimit, requireFeatureField.
  • src/services/settings.js — DB-gestützte Key-Speicherung für UI-Aktivierung.
  • config/default.jslicense.server, license.tokenPath, license.key, license.signingKey.

Cookie Settings

Wir verwenden Cookies, um Ihre Erfahrung zu verbessern. Essentielle Cookies sind immer aktiv.

Datenschutzerklärung
ESC
↑↓ navigate open esc close