# 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 ```bash # .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) ```bash php bin/console app:module:license billing YOUR_GITEA_TOKEN_HERE ``` #### Option B: Manuell in .env.local ```bash # .env.local GITEA_TOKEN_BILLING=abc123def456... GITEA_TOKEN_INVOICING=xyz789ghi012... ``` ### 5. Verifizieren ```bash 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: ```php [ '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: ```php [ '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 ```bash composer config repositories.mycrm-billing vcs https://git.mycrm.local/mycrm/mycrm-billing-module ``` ### auth.json konfigurieren ```json { "http-basic": { "git.mycrm.local": { "username": "dein-gitea-username", "password": "DEIN_GITEA_TOKEN" } } } ``` ### Modul installieren ```bash composer require mycrm/billing-module ``` **Ein Token für beides:** - ✅ Composer Installation - ✅ Lizenz-Validierung --- ## CLI-Befehle ### Lizenz registrieren ```bash php bin/console app:module:license # Beispiel php bin/console app:module:license billing abc123def456ghi789 ``` ### Alle Module auflisten ```bash 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 ```bash 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 ```php // 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 ```json { "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 ```bash 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 ```bash 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:** ```bash # 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 ```bash 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 ```bash # 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 ```bash 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()`: ```php 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: ```php 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