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

501 lines
12 KiB
Markdown

# 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 <module-identifier> <gitea-token>
# 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