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

11 KiB

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:

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:

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:

# 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:

{
    "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:

{
    "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:

<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:

<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:

<template>
    <div v-if="authStore.hasPermission('billing.create')">
        <Button label="Neue Rechnung" @click="createInvoice" />
    </div>
</template>

5. Beispiel: Vollständiges Plugin

BillingModulePlugin.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

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

cd ../myCRM
composer config repositories.mycrm-billing-module path ../mycrm-billing-module
composer require mycrm/billing-module:@dev

Schritt 4: Permissions synchronisieren

php bin/console app:plugin:sync-permissions billing

Output:

Neu erstellt: 3 (billing, invoicing, payments)

Schritt 5: Cache leeren

php bin/console cache:clear

Schritt 6: Lizenz aktivieren

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:

curl http://localhost:8000/api/plugin-menu | jq

Permissions in DB überprüfen:

SELECT * FROM modules WHERE code IN ('billing', 'invoicing', 'payments');

Plugin-Status:

php bin/console app:module:list

Logs:

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:

# 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:

# 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:

// 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:

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