myCRM/assets/js/layout/AppMenu.vue
olli b4974b93ef feat: integrate ApiPlatformBundle and enhance settings access control
- Added ApiPlatformBundle to the project configuration.
- Updated SettingsController to use custom access control for viewing and managing settings.
- Modified AppFixtures to reflect new module structure and permissions for project management.
- Adjusted ProjectStatus and ProjectTask entities to align with new permission checks.
- Enhanced User entity to include a method for retrieving module permissions.
- Implemented CleanupModulesCommand to deactivate or remove unimplemented modules.
- Added CSRF protection configuration for forms.
- Introduced property_info configuration for enhanced property handling.
- Updated base template to include user module permissions in the frontend.
- Created test_permissions.php for testing user permissions and roles.
2025-12-28 09:49:18 +01:00

154 lines
4.9 KiB
Vue

<script setup>
import { ref, onMounted } from 'vue';
import { useAuthStore } from '../stores/auth';
import { usePermissionStore } from '../stores/permissions';
import AppMenuItem from './AppMenuItem.vue';
const authStore = useAuthStore();
const permissionStore = usePermissionStore();
// Core-Menü mit Permission-Prüfungen
const coreMenu = [
{
label: 'Home',
items: [
{
label: 'Dashboard',
icon: 'pi pi-fw pi-home',
to: '/',
visible: () => permissionStore.canView('dashboard')
}
]
},
{
label: 'CRM',
items: [
{
label: 'Kontakte',
icon: 'pi pi-fw pi-users',
to: '/contacts',
visible: () => permissionStore.canView('contacts')
},
{
label: 'Projekte',
icon: 'pi pi-fw pi-briefcase',
to: '/projects',
visible: () => permissionStore.canView('projects')
},
{
label: 'Tätigkeiten',
icon: 'pi pi-fw pi-list-check',
to: '/project-tasks',
visible: () => permissionStore.canView('project_tasks')
}
]
}
];
// Administration-Menü mit Permission-Prüfungen
const adminMenu = {
label: 'Administration',
items: [
{
label: 'Projekt-Status',
icon: 'pi pi-fw pi-tag',
to: '/project-statuses',
visible: () => permissionStore.canView('projects')
},
{
label: 'Benutzerverwaltung',
icon: 'pi pi-fw pi-user-edit',
to: '/users',
visible: () => permissionStore.canView('users')
},
{
label: 'Rollenverwaltung',
icon: 'pi pi-fw pi-shield',
to: '/roles',
visible: () => permissionStore.canView('roles')
},
{
label: 'Einstellungen',
icon: 'pi pi-fw pi-cog',
to: '/settings',
visible: () => permissionStore.canView('settings')
}
]
};
// Dynamisches Menü (wird geladen)
const model = ref([...coreMenu]);
// Plugin-Menüs laden
const loadPluginMenus = async () => {
try {
const response = await fetch('/api/plugin-menu/grouped');
const data = await response.json();
if (data.success && data.data) {
// Plugin-Menüs als eigene Gruppen hinzufügen
Object.entries(data.data).forEach(([groupLabel, items]) => {
// Konvertiere zu PrimeVue Menü-Format
const menuGroup = {
label: groupLabel,
items: items.map(item => {
// Erstelle Permission-Prüfung
let visibleFn;
if (item.permission) {
// Explizite Permission aus Plugin
visibleFn = () => authStore.hasPermission(item.permission);
} else if (item.module) {
// Fallback: Leite von Modulname ab (z.B. 'billing')
visibleFn = () => permissionStore.canView(item.module);
} else if (item.source) {
// Fallback: Nutze Plugin-Identifier als Modulname
visibleFn = () => permissionStore.canView(item.source);
}
return {
label: item.label,
icon: item.icon ? `pi pi-fw ${item.icon}` : 'pi pi-fw pi-circle',
to: item.to,
...(item.items && { items: item.items }),
...(visibleFn && { visible: visibleFn })
};
})
};
model.value.push(menuGroup);
});
}
// Administration-Menü am Ende hinzufügen
model.value.push(adminMenu);
} catch (error) {
console.error('Fehler beim Laden der Plugin-Menüs:', error);
// Fallback: Nur Core + Admin Menü
model.value = [...coreMenu, adminMenu];
}
};
// Beim Mount laden - warten bis Permissions geladen sind
onMounted(async () => {
// Warten bis Permissions geladen sind
while (!permissionStore.loaded) {
await new Promise(resolve => setTimeout(resolve, 100));
}
loadPluginMenus();
});
</script>
<template>
<ul class="layout-menu">
<template v-for="(item, i) in model" :key="item">
<app-menu-item v-if="!item.separator && (!item.visible || item.visible())" :item="item" :index="i"></app-menu-item>
<li v-if="item.separator" class="menu-separator"></li>
</template>
</ul>
</template>
<style lang="scss" scoped></style>