myCRM/docs/GITEA_LICENSE_SYSTEM.md
2025-12-04 10:53:18 +01:00

12 KiB

Gitea-basiertes Lizenzierungs-System

Übersicht

Das Gitea-basierte Lizenzierungs-System nutzt Gitea Repository-Zugriff als Lizenzierung für myCRM-Module. Anstatt einen separaten Lizenzserver zu betreiben, prüft das System, ob ein Benutzer Zugriff auf das private Gitea-Repository eines Moduls hat.

Konzept

Gitea Access Token → Repository-Zugriff → Gültige Lizenz

Vorteile

Keine separate Lizenzserver-API nötig - Nutzt bestehende Gitea-Infrastruktur Einfache Verwaltung - Access Control über Gitea UI Flexibel - Granulare Berechtigungen pro Repository Sicher - Nutzt Gitea's bewährte Authentifizierung Offline-Support - 24h Cache + 7 Tage Grace Period Composer-Integration - Gleiche Tokens für Composer und Lizenzierung

Funktionsweise

  1. Modul-Repositories in Gitea erstellen (z.B. mycrm/mycrm-billing-module)
  2. Private Repositories - Nur lizenzierte Benutzer haben Zugriff
  3. Gitea Access Token als Lizenzschlüssel verwenden
  4. myCRM prüft Repository-Zugriff über Gitea API
  5. Zugriff = Lizenz gültig

Installation & Konfiguration

1. Gitea-Backend aktivieren

# .env.local
LICENSE_BACKEND=GiteaLicenseValidator
GITEA_BASE_URL=https://git.mycrm.local
GITEA_ORGANIZATION=mycrm
INSTANCE_ID=deine-unique-instance-id

2. Modul-Repository in Gitea erstellen

Namenskonvention: mycrm-{module-identifier}-module

Beispiele:

  • Billing-Modul: mycrm-billing-module
  • Invoicing-Modul: mycrm-invoicing-module
  • Inventory-Modul: mycrm-inventory-module

Repository-Settings:

  • Visibility: Private
  • Owner: Deine Organisation oder dein User (z.B. mycrm)

3. Gitea Access Token generieren

  1. Gehe zu Gitea → Settings → Applications
  2. Klicke auf "Generate New Token"
  3. Name: myCRM License - {Modul-Name}
  4. Scopes auswählen:
    • repo (Read access to repositories)
  5. Token kopieren (wird nur einmal angezeigt!)

4. Lizenz in myCRM registrieren

Option A: CLI (empfohlen)

php bin/console app:module:license billing YOUR_GITEA_TOKEN_HERE

Option B: Manuell in .env.local

# .env.local
GITEA_TOKEN_BILLING=abc123def456...
GITEA_TOKEN_INVOICING=xyz789ghi012...

5. Verifizieren

php bin/console app:module:list

Ausgabe sollte zeigen:

billing       ✓ Aktiv  Gitea Repository-Zugriff bestätigt (mycrm/mycrm-billing-module)

Repository-Metadaten für Lizenzinformationen

Das System kann Lizenzinformationen aus Repository-Metadaten extrahieren:

Features über Topics

Füge Topics zum Repository hinzu, um Features zu definieren:

Topics: feature-invoices, feature-payments, feature-reports

Diese werden als features im Lizenz-Array zurückgegeben:

[
    'valid' => true,
    'features' => ['invoices', 'payments', 'reports'],
    // ...
]

Ablaufdatum in Description

Füge das Ablaufdatum in die Repository-Description ein:

Premium Billing Module for myCRM
License expires: 2025-12-31

Unterstützte Formate:

  • expires: YYYY-MM-DD
  • valid until: YYYY-MM-DD
  • License expires: YYYY-MM-DD

Das System parsed automatisch das Datum:

[
    'valid' => true,
    'expiresAt' => DateTimeImmutable('2025-12-31'),
    // ...
]

Access Control: Wer darf welches Modul nutzen?

Variante 1: Team-Zugriff per Gitea Teams

  1. Team in Gitea erstellen

    • Gehe zu Organisation → Teams → "Create Team"
    • Name: Premium Customers
  2. Team-Mitglieder hinzufügen

    • Team → Members → "Add Member"
  3. Repository dem Team zuweisen

    • Repository → Settings → Collaboration
    • Add Team: Premium Customers mit Read Permission
  4. Jedes Team-Mitglied erhält Zugriff

    • Alle Mitglieder können nun Tokens mit Repo-Zugriff generieren

Variante 2: Individuelle Collaborators

  1. Repository → Settings → Collaboration
  2. "Add Collaborator"
  3. User auswählen + Read Permission
  4. User kann jetzt Token mit Zugriff generieren

Variante 3: Organisation-weiter Zugriff

  1. Organisation → Settings → Members
  2. Mitglieder mit Read-Rechten auf alle Private Repos
  3. Alle Mitglieder haben automatisch Zugriff auf alle Module

Composer Integration

Da Gitea-Tokens sowohl für Lizenzierung als auch für Composer-Installation genutzt werden können, ist die Integration nahtlos:

composer.json konfigurieren

composer config repositories.mycrm-billing vcs https://git.mycrm.local/mycrm/mycrm-billing-module

auth.json konfigurieren

{
    "http-basic": {
        "git.mycrm.local": {
            "username": "dein-gitea-username",
            "password": "DEIN_GITEA_TOKEN"
        }
    }
}

Modul installieren

composer require mycrm/billing-module

Ein Token für beides:

  • Composer Installation
  • Lizenz-Validierung

CLI-Befehle

Lizenz registrieren

php bin/console app:module:license <module-identifier> <gitea-token>

# Beispiel
php bin/console app:module:license billing abc123def456ghi789

Alle Module auflisten

php bin/console app:module:list

# Ausgabe:
# ┌───────────┬────────┬─────────────────────────────────────────────┐
# │ Modul     │ Status │ Lizenz-Info                                  │
# ├───────────┼────────┼─────────────────────────────────────────────┤
# │ billing   │ ✓ Aktiv│ Gitea Repository-Zugriff (mycrm/mycrm-...)  │
# │ invoicing │ ✗ Inakt│ Kein Gitea Access Token vorhanden           │
# └───────────┴────────┴─────────────────────────────────────────────┘

Lizenz widerrufen

php bin/console app:module:revoke billing

Caching & Offline-Betrieb

Cache-Strategie

Online-Validierung → 24h Cache → 7 Tage Grace Period → Offline-Fallback
  1. Erste Validierung: Gitea API-Call
  2. 24 Stunden: Gecacht, keine API-Calls
  3. Nach 24h: Neue Online-Validierung
  4. Offline-Fall: Grace Period (7 Tage ab letzter erfolgreicher Validierung)

Cache-Verhalten

// Bei jedem Request wird geprüft:
if (cache_valid && within_24h) {
    return cached_license;
}

// Online-Validierung
try {
    $license = validate_with_gitea();
    cache($license, 24h);
} catch (NetworkError $e) {
    // Fallback auf Cache mit Grace Period
    if (cached_license && within_7_days) {
        return cached_license;
    }
    throw LicenseException();
}

Vorteile

  • Performance: Nur 1 API-Call pro 24h
  • Offline-Betrieb: 7 Tage funktionsfähig ohne Internet
  • Kein Dauerbetrieb offline: Nach 7 Tagen ist Online-Validierung erforderlich

API-Endpunkte

Das System stellt REST-API-Endpunkte für Admin-UIs bereit:

GET /api/modules

Liste aller Module mit Lizenz-Status

{
    "modules": [
        {
            "identifier": "billing",
            "name": "Billing & Invoicing",
            "version": "1.0.0",
            "license": {
                "valid": true,
                "licensedTo": "Max Mustermann",
                "expiresAt": "2025-12-31T23:59:59+00:00",
                "message": "Gitea Repository-Zugriff bestätigt (mycrm/mycrm-billing-module)",
                "features": ["invoices", "payments", "reports"]
            }
        }
    ]
}

POST /api/modules/{module}/license

Lizenz registrieren

curl -X POST https://mycrm.local/api/modules/billing/license \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"licenseKey": "abc123def456..."}'

DELETE /api/modules/{module}/license

Lizenz widerrufen

curl -X DELETE https://mycrm.local/api/modules/billing/license \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

Security Best Practices

DO's

  • Tokens niemals committen - Nutze .env.local (nicht in Git)
  • Token-Scopes minimal halten - Nur repo:read erforderlich
  • Tokens rotieren - Regelmäßig neue Tokens generieren
  • Team-basierte Zugriffssteuerung - Nutze Gitea Teams für Kunden-Gruppen
  • HTTPS verwenden - Gitea nur über HTTPS erreichbar machen
  • Tokens pro Modul - Separate Tokens für jedes Modul

DONT's

  • Keine Tokens in composer.json - Nur in auth.json
  • Keine universellen Tokens - Nicht einen Token für alle Module
  • Keine öffentlichen Repositories - Module müssen private sein
  • Keine Shared Tokens - Jeder Kunde eigener Token

Troubleshooting

Problem: "Kein Zugriff auf Modul-Repository"

Ursachen:

  1. Token hat keine repo:read Berechtigung
  2. Repository ist nicht vorhanden
  3. User ist nicht Collaborator/Team-Mitglied
  4. Repository-Name folgt nicht Namenskonvention

Lösung:

# Token testen
curl -H "Authorization: token YOUR_TOKEN" \
  https://git.mycrm.local/api/v1/repos/mycrm/mycrm-billing-module

# Sollte Status 200 zurückgeben

Problem: "Gitea nicht erreichbar"

Symptom: Modul läuft, zeigt aber "Offline-Modus (Grace Period)"

Ursache: Gitea-Server nicht erreichbar, aber gecachte Lizenz noch gültig

Aktion: Prüfe GITEA_BASE_URL in .env.local

Problem: "Grace Period abgelaufen"

Symptom: Modul wird nicht gestartet

Ursache: Letzte erfolgreiche Validierung > 7 Tage her

Lösung:

  1. Gitea-Server erreichbar machen
  2. Cache clearen: php bin/console cache:clear
  3. Modul neu starten

Migration: Standard-Lizenzserver → Gitea

Schritt 1: Bestehende Lizenzen notieren

php bin/console app:module:list

Schritt 2: Gitea-Repositories erstellen

Für jedes lizenzierte Modul:

  1. Repository anlegen: mycrm-{modul}-module
  2. Als Private setzen
  3. Kunden als Collaborators hinzufügen

Schritt 3: .env.local aktualisieren

# Alt (entfernen oder auskommentieren)
#LICENSE_BACKEND=LicenseValidator
#LICENSE_SERVER_URL=https://license.mycrm.local
#LICENSE_BILLING=eyJhbGciOi...

# Neu
LICENSE_BACKEND=GiteaLicenseValidator
GITEA_BASE_URL=https://git.mycrm.local
GITEA_ORGANIZATION=mycrm
GITEA_TOKEN_BILLING=abc123...

Schritt 4: Cache leeren & testen

php bin/console cache:clear
php bin/console app:module:list

Erweiterte Konfiguration

Modul-spezifische Repository-Namen

Standardmäßig: mycrm-{module}-module

Für custom Namen, erweitere GiteaLicenseValidator::getRepositoryName():

private function getRepositoryName(string $moduleIdentifier): string
{
    // Custom Mapping
    $mapping = [
        'billing' => 'premium-billing-suite',
        'invoicing' => 'invoice-pro',
    ];

    return $mapping[$moduleIdentifier] ?? 'mycrm-' . $moduleIdentifier . '-module';
}

Custom Feature-Extraction

Erweitere extractFeaturesFromRepository() für eigene Logik:

private function extractFeaturesFromRepository(array $repoData): array
{
    // Beispiel: Features aus Repository-README parsen
    // Beispiel: Features aus Gitea Webhooks abrufen
    // ...
}

Vergleich: Standard vs. Gitea

Feature Standard-Lizenzserver Gitea-Lizenzserver
Infrastruktur Eigene REST-API Bestehende Gitea-Instanz
Setup-Aufwand Hoch Niedrig
Verwaltung Custom UI Gitea UI
Token-Typ JWT Gitea Access Token
Access Control Custom-Logik Gitea Permissions
Composer-Integration Separat Gleiche Tokens
Offline-Support 7 Tage 7 Tage
Skalierung Custom Gitea

Fazit

Das Gitea-basierte Lizenzierungs-System ist ideal, wenn:

Du bereits Gitea für Versionskontrolle nutzt Du keine separate Lizenzserver-API betreiben möchtest Du flexible, repository-basierte Access Control benötigst Du Composer-Installation und Lizenzierung vereinheitlichen willst

Nächste Schritte:

  1. Gitea-Instanz einrichten (falls noch nicht vorhanden)
  2. Private Modul-Repositories erstellen
  3. .env.local konfigurieren
  4. Erste Lizenz registrieren
  5. Testen!

Fragen? Siehe auch:

  • PLUGIN_SYSTEM.md - Vollständige Plugin-System-Dokumentation
  • PLUGIN_QUICKSTART.md - 5-Minuten-Setup