myCRM/docs/PLUGIN_MENUS_AND_PERMISSIONS.md
olli a787019a3b feat: Implement PDF upload functionality in PDFUploadForm.vue
- Added a file input for PDF uploads with validation for file type and size.
- Implemented file size formatting and user feedback for selected files.
- Created upload and cancel methods with placeholder for future API integration.

feat: Create PaymentForm.vue for handling payments

- Developed a form for entering payment details including date, amount, method, and notes.
- Integrated currency formatting and dropdown for payment methods.
- Implemented save and cancel actions with API call for saving payment data.

docs: Add documentation for dynamic plugin menus and permissions

- Provided guidelines for defining menu items and permissions in plugins.
- Explained the process for synchronizing permissions and integrating menus in the frontend.
- Included examples and best practices for plugin development.

feat: Add database migrations for invoices, invoice items, and payments

- Created migration scripts to define the database schema for invoices, invoice items, and payments.
- Established foreign key relationships between invoices and related entities.

feat: Implement command for synchronizing plugin permissions

- Developed a console command to synchronize plugin permissions with the database.
- Added options for dry-run and force synchronization for unlicensed modules.

feat: Create API controller for plugin menu items

- Implemented API endpoints to retrieve plugin menu items in both flat and grouped formats.
- Ensured access control with role-based permissions for API access.

feat: Develop service for managing plugin menu items

- Created a service to collect and manage menu items from installed plugins.
- Implemented methods for retrieving flat and grouped menu items for frontend use.

feat: Add service for synchronizing plugin permissions

- Developed a service to handle the synchronization of plugin permissions with the database.
- Included logic for creating and updating permission modules based on plugin definitions.
2025-12-05 11:13:41 +01:00

522 lines
11 KiB
Markdown

# Plugin-Menüs und Permissions
Anleitung zur dynamischen Registrierung von Menü-Items und Permissions durch Plugins.
## Übersicht
Das Plugin-System unterstützt jetzt:
**Dynamische Menü-Items** - Plugins können eigene Menüpunkte hinzufügen
**Automatische Permission-Synchronisation** - Modul-Permissions werden automatisch in der DB angelegt
**Permission-basierte Sichtbarkeit** - Menüpunkte erscheinen nur für berechtigte User
**Gruppierung** - Plugin-Menüs können gruppiert werden
---
## 1. Menü-Items im Plugin definieren
### In deiner Plugin-Klasse:
```php
public function getMenuItems(): array
{
return [
[
'label' => 'Rechnungen', // Menü-Titel
'icon' => 'pi-file-pdf', // PrimeIcons Icon (ohne pi pi-fw prefix)
'group' => 'Finanzen', // Gruppierung im Menü
'items' => [
[
'label' => 'Alle Rechnungen',
'icon' => 'pi-list',
'to' => '/billing/invoices', // Vue Router path
'permission' => 'billing.view' // Optional: Permission-Check
],
[
'label' => 'Neue Rechnung',
'icon' => 'pi-plus',
'to' => '/billing/invoices/create',
'permission' => 'billing.create'
],
[
'separator' => true // Optional: Trennlinie
],
[
'label' => 'Einstellungen',
'icon' => 'pi-cog',
'to' => '/billing/settings',
'permission' => 'billing.manage'
]
]
]
];
}
```
### Menü-Item Optionen:
| Feld | Typ | Required | Beschreibung |
|------|-----|----------|--------------|
| `label` | string | ✅ | Anzeigename des Menüpunkts |
| `icon` | string | ❌ | PrimeIcons Icon (ohne `pi pi-fw` prefix) |
| `to` | string | ❌ | Vue Router path |
| `url` | string | ❌ | Externe URL (alternativ zu `to`) |
| `items` | array | ❌ | Sub-Menüpunkte |
| `permission` | string | ❌ | Permission-String für Sichtbarkeits-Check |
| `group` | string | ❌ | Gruppierung im Hauptmenü |
| `separator` | bool | ❌ | Trennlinie (nur in Sub-Items) |
---
## 2. Permissions definieren
### In deiner Plugin-Klasse:
```php
public function getPermissionModules(): array
{
return ['billing', 'invoicing'];
}
```
Das System erstellt automatisch folgende Permissions:
- `billing.view`
- `billing.create`
- `billing.edit`
- `billing.delete`
- `billing.export`
- `billing.manage`
### Permission-Synchronisation durchführen:
```bash
# Alle Plugins synchronisieren
php bin/console app:plugin:sync-permissions
# Nur ein bestimmtes Plugin
php bin/console app:plugin:sync-permissions billing
# Dry-Run (zeigt nur was passieren würde)
php bin/console app:plugin:sync-permissions --dry-run
```
**Output:**
```
Plugin Permission-Module Synchronisation
========================================
Synchronisiere alle Plugins...
------------------------------
Aktion Anzahl
Neu erstellt 2
Aktualisiert 0
Übersprungen 5
```
---
## 3. Frontend Integration
### API-Endpoints:
#### GET /api/plugin-menu
Gibt alle Plugin-Menü-Items als flache Liste zurück.
**Response:**
```json
{
"success": true,
"data": [
{
"label": "Alle Rechnungen",
"icon": "pi-list",
"to": "/billing/invoices",
"permission": "billing.view",
"source": "billing"
}
],
"count": 1
}
```
#### GET /api/plugin-menu/grouped
Gibt gruppierte Plugin-Menü-Items zurück.
**Response:**
```json
{
"success": true,
"data": {
"Finanzen": [
{
"label": "Rechnungen",
"icon": "pi-file-pdf",
"items": [...]
}
]
},
"groups": ["Finanzen"]
}
```
### AppMenu.vue
Das Menü lädt automatisch Plugin-Menüs beim Mount:
```vue
<script setup>
import { ref, onMounted } from 'vue';
const model = ref([...coreMenu]);
const loadPluginMenus = async () => {
const response = await fetch('/api/plugin-menu/grouped');
const data = await response.json();
// Plugin-Menüs werden automatisch hinzugefügt
// Permission-Checks werden automatisch durchgeführt
};
onMounted(() => {
loadPluginMenus();
});
</script>
```
---
## 4. Permission-Checks im Frontend
### Mit Composition API:
```vue
<script setup>
import { useAuthStore } from '@/stores/auth';
const authStore = useAuthStore();
// Permission prüfen
const canViewInvoices = authStore.hasPermission('billing.view');
</script>
<template>
<Button v-if="canViewInvoices" label="Rechnung anzeigen" />
</template>
```
### Im Template:
```vue
<template>
<div v-if="authStore.hasPermission('billing.create')">
<Button label="Neue Rechnung" @click="createInvoice" />
</div>
</template>
```
---
## 5. Beispiel: Vollständiges Plugin
### BillingModulePlugin.php
```php
<?php
namespace MyCRM\BillingModule;
use App\Plugin\LicenseValidatorInterface;
use App\Plugin\ModulePluginInterface;
class BillingModulePlugin implements ModulePluginInterface
{
public function __construct(
private readonly LicenseValidatorInterface $licenseValidator
) {}
public function getIdentifier(): string
{
return 'billing';
}
public function getDisplayName(): string
{
return 'Rechnungsmodul';
}
public function getVersion(): string
{
return '1.0.0';
}
public function getDescription(): string
{
return 'Verwaltung von Rechnungen, Angeboten und Zahlungen';
}
public function isLicensed(): bool
{
return $this->licenseValidator->validate('billing')['valid'];
}
public function getLicenseInfo(): array
{
return $this->licenseValidator->validate('billing');
}
public function boot(): void
{
if (!$this->isLicensed()) {
throw new \RuntimeException('Billing Module nicht lizenziert');
}
// Services, Routes, etc. registrieren
}
public function getPermissionModules(): array
{
return ['billing', 'invoicing', 'payments'];
}
public function getMenuItems(): array
{
return [
[
'label' => 'Rechnungen',
'icon' => 'pi-file-pdf',
'group' => 'Finanzen',
'items' => [
[
'label' => 'Dashboard',
'icon' => 'pi-chart-line',
'to' => '/billing/dashboard',
'permission' => 'billing.view'
],
[
'label' => 'Alle Rechnungen',
'icon' => 'pi-list',
'to' => '/billing/invoices',
'permission' => 'billing.view'
],
[
'label' => 'Neue Rechnung',
'icon' => 'pi-plus',
'to' => '/billing/invoices/create',
'permission' => 'billing.create'
],
[
'separator' => true
],
[
'label' => 'Zahlungen',
'icon' => 'pi-money-bill',
'to' => '/billing/payments',
'permission' => 'payments.view'
],
[
'label' => 'Einstellungen',
'icon' => 'pi-cog',
'to' => '/billing/settings',
'permission' => 'billing.manage'
]
]
]
];
}
public function canInstall(): array
{
$errors = [];
if (PHP_VERSION_ID < 80200) {
$errors[] = 'PHP 8.2+ erforderlich';
}
return [
'success' => empty($errors),
'errors' => $errors
];
}
}
```
---
## 6. Workflow: Neues Plugin mit Menüs
### Schritt 1: Plugin erstellen
```bash
cd ../mycrm-billing-module
composer init
# Name: mycrm/billing-module
```
### Schritt 2: Plugin-Klasse implementieren
Siehe Beispiel oben - implementiere `getMenuItems()` und `getPermissionModules()`.
### Schritt 3: In myCRM installieren
```bash
cd ../myCRM
composer config repositories.mycrm-billing-module path ../mycrm-billing-module
composer require mycrm/billing-module:@dev
```
### Schritt 4: Permissions synchronisieren
```bash
php bin/console app:plugin:sync-permissions billing
```
**Output:**
```
Neu erstellt: 3 (billing, invoicing, payments)
```
### Schritt 5: Cache leeren
```bash
php bin/console cache:clear
```
### Schritt 6: Lizenz aktivieren
```bash
php bin/console app:module:license billing YOUR_GITEA_TOKEN
```
### Schritt 7: Testen
1. Frontend öffnen
2. Plugin-Menü erscheint unter "Finanzen"
3. Menüpunkte sind nur sichtbar mit Berechtigung
---
## 7. Debugging
### Menü-Items überprüfen:
```bash
curl http://localhost:8000/api/plugin-menu | jq
```
### Permissions in DB überprüfen:
```sql
SELECT * FROM modules WHERE code IN ('billing', 'invoicing', 'payments');
```
### Plugin-Status:
```bash
php bin/console app:module:list
```
### Logs:
```bash
tail -f var/log/dev.log | grep -E "(Plugin|Menu|Permission)"
```
---
## 8. Best Practices
### ✅ DO's:
- **Gruppiere verwandte Menüs** - Nutze `group` für bessere Organisation
- **Permission-Checks** - Definiere `permission` für alle sensiblen Menüpunkte
- **Icons verwenden** - Macht das Menü übersichtlicher
- **Synchronisiere nach Installation** - `app:plugin:sync-permissions` nach jedem Plugin-Update
### ❌ DON'Ts:
- **Keine Core-Gruppen überschreiben** - "Home", "CRM", "Administration" sind reserviert
- **Keine tiefen Verschachtelungen** - Max. 2 Ebenen (Gruppe → Items)
- **Keine externen URLs ohne Warnung** - User erwarten interne Navigation
---
## 9. Troubleshooting
### Problem: Menü erscheint nicht
**Lösung:**
```bash
# Cache leeren
php bin/console cache:clear
# Plugin-Status prüfen
php bin/console app:module:list
# API testen
curl http://localhost:8000/api/plugin-menu/grouped
# Browser-Console überprüfen
```
### Problem: Permissions fehlen
**Lösung:**
```bash
# Permissions synchronisieren
php bin/console app:plugin:sync-permissions
# DB überprüfen
SELECT * FROM modules WHERE code = 'billing';
# Rolle zuweisen
# In der Rollenverwaltung das neue Modul auswählen
```
### Problem: Permission-Checks funktionieren nicht
**Lösung:**
- Prüfe ob User die Rolle hat
- Prüfe ob Rolle die Permission hat
- Prüfe `authStore.hasPermission()` Implementierung
---
## 10. Migration bestehender Plugins
Wenn du bereits Plugins hast, füge einfach `getMenuItems()` hinzu:
```php
// Altes Plugin
class MyPlugin implements ModulePluginInterface {
// ... bestehende Methoden ...
}
// Neu: Füge hinzu
class MyPlugin implements ModulePluginInterface {
// ... bestehende Methoden ...
public function getMenuItems(): array
{
return [
// Deine Menüs hier
];
}
}
```
Dann:
```bash
composer dump-autoload
php bin/console cache:clear
```
---
## Support
Bei Fragen siehe:
- `PLUGIN_SYSTEM.md` - Allgemeine Plugin-Architektur
- `GITEA_LICENSE_SYSTEM.md` - Lizenzierung
- `docs/PERMISSIONS.md` - Permission-System