501 lines
12 KiB
Markdown
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
|