myCRM/docs/PLUGIN_SYSTEM_SUMMARY.md
olli 42e7bc7e10 feat(billing-module): Implementieren der Modulstruktur und Lizenzverwaltung
- Hinzufügen der DependencyInjection-Konfiguration für das Billing-Modul.
- Erstellen der Invoice-Entity mit API-Ressourcen und Berechtigungen.
- Konfigurieren der Services in services.yaml für das Billing-Modul.
- Implementieren von CLI-Commands zur Verwaltung von Modul-Lizenzen und zur Auflistung installierter Module.
- Erstellen eines API-Controllers zur Verwaltung von Modulen und Lizenzen.
- Hinzufügen eines EventListeners für das Booten von Modulen.
- Definieren von Interfaces für Lizenzvalidierung und Modul-Plugins.
- Implementieren der ModuleRegistry zur Verwaltung und Booten von Modulen.
- Erstellen eines LicenseValidator-Services zur Validierung und Registrierung von Lizenzen.
2025-12-03 15:14:07 +01:00

417 lines
12 KiB
Markdown

# Plugin-System: Zusammenfassung der Implementierung
## Executive Summary
Das implementierte Plugin-System ermöglicht die Installation und Verwaltung von optionalen, lizenzierbaren Modulen in myCRM. Module sind vollständig unabhängige Composer-Packages, die ohne Änderungen am Core nachträglich installiert werden können und nur mit gültiger Lizenz funktionieren.
## Kernmerkmale
### ✅ Anforderung: Leicht nachträglich installierbar
**Gelöst durch:**
- Composer-basierte Installation (`composer require mycrm/modul-name`)
- Symfony Flex Auto-Configuration für Bundle-Registrierung
- Automatische Service-Discovery über Tagged Iterators
- Keine manuelle Code-Änderung im Core erforderlich
### ✅ Anforderung: Keine Core-Abhängigkeiten
**Gelöst durch:**
- Interface-basierte Architektur (`ModulePluginInterface`, `LicenseValidatorInterface`)
- Core kennt nur Interfaces, keine konkreten Module
- Module registrieren sich selbst via Dependency Injection
- Loose Coupling durch Event-System und Service-Tags
### ✅ Anforderung: Lizenzvalidierung erforderlich
**Gelöst durch:**
- REST-API basierte Lizenzprüfung gegen externen Server
- JWT-Token Format für Lizenzschlüssel
- Caching mit 24h TTL + 7 Tage Grace Period
- Offline-Betrieb möglich (gecachte Validierung)
- Module werden nur mit gültiger Lizenz gebootet
## Architektur-Komponenten
### 1. Core-System (Hauptprojekt)
**Interfaces:**
```
/src/Plugin/
├── ModulePluginInterface.php # Plugin-Contract
└── LicenseValidatorInterface.php # Lizenz-Contract
```
**Implementierungen:**
```
/src/
├── Plugin/ModuleRegistry.php # Plugin-Verwaltung
├── Service/LicenseValidator.php # Lizenzprüfung
├── EventListener/ModuleBootListener.php # Auto-Boot
├── Command/
│ ├── ModuleListCommand.php # CLI: Liste
│ └── ModuleLicenseCommand.php # CLI: Lizenz-Verwaltung
└── Controller/Api/ModuleManagementController.php # REST-API
```
**Frontend:**
```
/assets/js/views/
└── ModuleManagement.vue # Admin-UI
```
### 2. Modul-Package (externes Repository)
```
mycrm-modulname/
├── composer.json # Symfony Bundle Type
├── src/
│ ├── ModulnameModulePlugin.php # Implements ModulePluginInterface
│ ├── ModulnameBundle.php # Symfony Bundle
│ ├── DependencyInjection/ # Container Extension
│ ├── Entity/ # Doctrine Entities
│ ├── Controller/ # API Controllers
│ ├── Security/Voter/ # Permissions
│ └── Service/ # Business Logic
├── config/
│ ├── services.yaml # Service-Tag: app.module_plugin
│ └── routes.yaml
└── migrations/ # Doctrine Migrations
```
## Workflow
### Installation eines Moduls
```mermaid
graph TD
A[composer require mycrm/modul] --> B[Composer installiert Package]
B --> C[Symfony Flex registriert Bundle]
C --> D[DI Container lädt Services]
D --> E[ModuleRegistry erkennt Plugin via Tag]
E --> F[Admin registriert Lizenz]
F --> G[LicenseValidator prüft gegen Server]
G --> H{Lizenz gültig?}
H -->|Ja| I[ModuleBootListener bootet Modul]
H -->|Nein| J[Modul bleibt inaktiv]
I --> K[Modul verfügbar]
```
### Lizenzvalidierung
```mermaid
sequenceDiagram
participant App as myCRM
participant Cache as Cache
participant Validator as LicenseValidator
participant Server as Lizenzserver
App->>Validator: validate("billing")
Validator->>Cache: getCached("billing")
alt Cache Hit & Grace Period aktiv
Cache-->>Validator: Gecachte Lizenz
Validator-->>App: Valid (cached)
else Cache Miss oder abgelaufen
Validator->>Server: POST /api/validate
alt Server erreichbar
Server-->>Validator: {valid: true, ...}
Validator->>Cache: speichern (24h TTL)
Validator-->>App: Valid
else Server nicht erreichbar
alt Gecachte Lizenz in Grace Period
Validator-->>App: Valid (offline)
else Keine Grace Period
Validator-->>App: Invalid
end
end
end
```
## API-Übersicht
### REST-API Endpunkte
```
GET /api/modules # Alle Module auflisten
GET /api/modules/{id} # Modul-Details
POST /api/modules/{id}/license # Lizenz registrieren
DELETE /api/modules/{id}/license # Lizenz widerrufen
POST /api/modules/{id}/validate # Lizenz validieren
GET /api/modules/licenses # Alle Lizenzen
```
### CLI-Commands
```bash
app:module:list # Module auflisten
app:module:license <module> [key] # Lizenz verwalten
--revoke # Lizenz widerrufen
--validate # Lizenz prüfen
```
## Integration mit bestehendem System
### Permission-System
Module können eigene Permission-Module registrieren:
```php
public function getPermissionModules(): array
{
return ['billing', 'invoices', 'payments'];
}
```
Diese werden automatisch im Role-Permission-System verfügbar und können über die bestehenden Voter geprüft werden:
```php
$this->denyAccessUnlessGranted('VIEW', 'billing');
```
### API Platform Integration
Modul-Entities implementieren `ModuleAwareInterface`:
```php
class Invoice implements ModuleAwareInterface
{
public function getModuleName(): string
{
return 'billing';
}
}
#[ApiResource(
security: "is_granted('VIEW', 'billing')"
)]
```
### Vue.js Frontend
Module können eigene Vue-Komponenten bereitstellen:
```javascript
// Modul-Package: assets/js/index.js
export default {
components: { InvoiceManagement },
routes: [/* ... */]
}
// Haupt-App: Bedingte Integration
if (window.myCRM.modules.billing?.active) {
app.use(BillingModule)
}
```
## Sicherheits-Features
### 1. Lizenzschlüssel-Speicherung
- Environment-Variablen (`.env.local`)
- Nicht im Git-Repository (`.env.local` in `.gitignore`)
- Optional: Verschlüsselte DB-Speicherung
### 2. API-Zugriff
- Alle Management-Endpunkte: `#[IsGranted('ROLE_ADMIN')]`
- Lizenzschlüssel werden nie im Frontend exponiert
- CSRF-Protection via Symfony
### 3. Offline-Schutz
- Grace Period verhindert Dauerbetrieb ohne Validierung
- Cache-TTL: 24 Stunden
- Grace Period: 7 Tage nach letzter Validierung
### 4. Modul-Isolation
- Module können Core nicht modifizieren
- Eigene Doctrine Entity-Manager möglich
- Eigene Namespaces, keine Konflikte
## Performance-Optimierung
### Caching-Strategie
```
Lizenzvalidierung:
├── Online-Check: Nur alle 24h
├── Cache-Hit: < 1ms
└── Offline-Mode: Grace Period 7 Tage
```
### Lazy-Loading
- Module booten nur beim ersten Request
- Frontend-Komponenten lazy-loaded
- Doctrine-Mappings on-demand
### Service-Tagging
- Automatische Plugin-Discovery
- Kein manuelles Service-Scanning
- Symfony DI Container optimiert
## Testing-Strategie
### Unit-Tests
```php
class MyModulePluginTest extends TestCase
{
public function testIsLicensedWithValidLicense(): void
{
$validator = $this->createMock(LicenseValidatorInterface::class);
$validator->method('validate')->willReturn(['valid' => true]);
$plugin = new MyModulePlugin($validator);
$this->assertTrue($plugin->isLicensed());
}
}
```
### Integration-Tests
```php
class LicenseValidatorTest extends KernelTestCase
{
public function testValidateFetchesFromServer(): void
{
$client = $this->createMock(HttpClientInterface::class);
// Mock HTTP-Response
$validator = new LicenseValidator($client, ...);
$result = $validator->validate('billing');
$this->assertTrue($result['valid']);
}
}
```
### Functional-Tests
```php
class ModuleManagementControllerTest extends WebTestCase
{
public function testListModulesRequiresAdmin(): void
{
$client = static::createClient();
$client->request('GET', '/api/modules');
$this->assertResponseStatusCodeSame(401);
}
}
```
## Deployment-Checklist
### Erstinstallation
- [ ] Core-System: `services_plugin.yaml` importieren
- [ ] Environment: `LICENSE_SERVER_URL` setzen
- [ ] Environment: `INSTANCE_ID` generieren
- [ ] Cache-Clear: `php bin/console cache:clear`
### Modul-Installation
- [ ] Composer: `composer require mycrm/modul-name`
- [ ] Bundle: Automatisch registriert oder manuell in `bundles.php`
- [ ] Migrations: `php bin/console doctrine:migrations:migrate`
- [ ] Lizenz: `php bin/console app:module:license modul-name`
- [ ] Cache: `php bin/console cache:clear`
- [ ] Test: `php bin/console app:module:list`
### Produktion
- [ ] `.env.local` mit Lizenzen auf Server deployen
- [ ] Lizenzserver-Firewall: Zugriff erlauben
- [ ] Monitoring: Lizenz-Ablaufdaten überwachen
- [ ] Backup: `.env.local` in Backup einschließen
## Erweiterungsmöglichkeiten
### Bereits implementiert
✅ Interface-basierte Architektur
✅ Lizenzvalidierung mit Online/Offline-Modus
✅ CLI-Commands für Verwaltung
✅ REST-API für Admin-UI
✅ Vue.js Admin-Interface
✅ Integration mit Permission-System
✅ Caching mit Grace Period
✅ Composer-basierte Installation
### Zukünftige Features (optional)
- 🔮 Multi-Tenancy-Support (mehrere Instanzen, eine Lizenz)
- 🔮 Offline-Lizenzierung (Air-Gapped Systeme)
- 🔮 Automatische Update-Benachrichtigungen
- 🔮 Modul-Marketplace Integration
- 🔮 Feature-Flags innerhalb von Modulen
- 🔮 Modul-Dependencies (Modul A benötigt Modul B)
- 🔮 Rollback-Mechanismus bei Installation
## Technologie-Stack
### Backend
- PHP 8.3+
- Symfony 7.1 LTS
- Doctrine ORM
- API Platform
- PSR-6 Cache (Symfony Cache)
- PSR-3 Logger (Monolog)
### Frontend
- Vue.js 3 (Composition API)
- PrimeVue (UI-Komponenten)
- Tailwind CSS
### DevOps
- Composer (Package Management)
- Symfony Flex (Auto-Configuration)
- Doctrine Migrations
## Code-Statistik
```
Core-System (neu):
├── Interfaces: 2 Dateien
├── Services: 2 Dateien
├── Commands: 2 Dateien
├── Controller: 1 Datei
├── EventListener: 1 Datei
└── Vue-Komponenten: 1 Datei
Beispiel-Modul:
├── Plugin-Klasse: 1 Datei
├── Bundle: 1 Datei
├── DependencyInjection: 2 Dateien
├── Entity: 1 Datei (Beispiel)
└── Konfiguration: 1 Datei
Dokumentation:
├── PLUGIN_SYSTEM.md: Vollständige Anleitung
├── PLUGIN_SYSTEM_SUMMARY.md: Diese Datei
├── EXAMPLE_MODULE_STRUCTURE.md: Modul-Template
└── example-module/: Code-Beispiele
```
## Kosten-Nutzen-Analyse
### Vorteile
**Modularität**: Kunden zahlen nur für benötigte Features
**Wartbarkeit**: Module unabhängig updatebar
**Skalierbarkeit**: Beliebig viele Module möglich
**Lizenzierung**: Automatische Kontrolle über Funktionen
**Entwicklung**: Parallele Modul-Entwicklung möglich
**Testing**: Module isoliert testbar
**Deployment**: Schrittweise Einführung möglich
### Aufwand
⚠️ **Initial**: ~2-3 Tage für Core-System (bereits implementiert)
⚠️ **Pro Modul**: ~1-2 Tage zusätzlich für Plugin-Setup
⚠️ **Lizenzserver**: Separater Service erforderlich
⚠️ **Dokumentation**: Pro Modul individuell
### ROI
Mit diesem System können Sie:
- Module einzeln lizenzieren und verkaufen
- Upselling durch Feature-Module
- Trial-Lizenzen mit Ablaufdatum
- Pay-per-Feature-Modelle
- White-Label-Lösungen mit unterschiedlichen Modulen
## Kontakt und Support
Diese Implementierung wurde mit Claude Code entwickelt und basiert auf Symfony Best Practices.
**Nächste Schritte:**
1. Lizenzserver implementieren (externe Komponente)
2. Erstes Produktiv-Modul entwickeln (z.B. Billing)
3. Testing und Monitoring in Produktion
4. Dokumentation für Modul-Entwickler erweitern