corrad-af-2024/components/examples/PermissionExample.vue
Afiq f05dd42c16 Enhance README and implement RBAC system with Authentik integration
- Updated README.md to reflect the new project name and provide an overview of the Role-Based Access Control (RBAC) system.
- Added new components for RBAC management, including:
  - PermissionExample.vue: Demonstrates permission-based navigation.
  - GroupCard.vue: Displays group information and assigned roles.
  - PermissionMatrix.vue: Visual representation of permissions across roles and resources.
  - RoleTemplates.vue: Quick role templates for applying pre-configured permissions.
  - StatsCards.vue: Displays statistics related to users, groups, and roles.
- Introduced useRbacPermissions.js for managing permission checks.
- Created docker-compose.yml for PostgreSQL and Redis services.
- Developed comprehensive documentation for application management and Authentik integration.
- Added multiple pages for managing applications, groups, roles, and users, including bulk operations and templates.
- Updated navigation structure to include new RBAC management paths.
2025-05-31 15:58:41 +08:00

300 lines
9.4 KiB
Vue

<template>
<div class="permission-example">
<h2 class="text-xl font-bold mb-4">RBAC Permission System Example</h2>
<!-- Menu Navigation Example -->
<div class="mb-6">
<h3 class="text-lg font-medium mb-2">Menu Items (Permission-Based)</h3>
<nav class="flex space-x-4">
<NuxtLink
v-if="canViewDashboard"
to="/dashboard"
class="px-3 py-2 bg-blue-100 text-blue-800 rounded"
>
Dashboard
</NuxtLink>
<NuxtLink
v-if="canViewUsers"
to="/users"
class="px-3 py-2 bg-green-100 text-green-800 rounded"
>
Users
</NuxtLink>
<NuxtLink
v-if="canViewRBAC"
to="/rbac"
class="px-3 py-2 bg-purple-100 text-purple-800 rounded"
>
RBAC Management
</NuxtLink>
<span v-if="!canViewDashboard && !canViewUsers && !canViewRBAC" class="text-gray-500">
No menu items available
</span>
</nav>
</div>
<!-- Component-Level Permissions -->
<div class="mb-6">
<h3 class="text-lg font-medium mb-2">User Actions (Component Permissions)</h3>
<div class="space-y-2">
<div class="flex items-center space-x-2">
<span class="text-gray-700">John Doe</span>
<span class="text-gray-500">john@example.com</span>
<!-- Edit Button -->
<button
v-if="canEditUser"
@click="editUser"
class="px-3 py-1 bg-blue-500 text-white text-sm rounded hover:bg-blue-600"
>
<Icon name="ph:pencil" class="w-4 h-4 mr-1" />
Edit
</button>
<!-- Delete Button -->
<button
v-if="canDeleteUser"
@click="deleteUser"
class="px-3 py-1 bg-red-500 text-white text-sm rounded hover:bg-red-600"
>
<Icon name="ph:trash" class="w-4 h-4 mr-1" />
Delete
</button>
<!-- Sensitive Info (Conditional Display) -->
<span
v-if="canViewSensitiveInfo"
class="px-2 py-1 bg-yellow-100 text-yellow-800 text-xs rounded"
>
Salary: $75,000
</span>
</div>
</div>
</div>
<!-- Feature-Level Permissions -->
<div class="mb-6">
<h3 class="text-lg font-medium mb-2">Advanced Features</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<!-- Data Export -->
<div class="p-4 border rounded-lg">
<h4 class="font-medium mb-2">Data Export</h4>
<button
v-if="canExportData"
@click="exportData"
class="w-full px-3 py-2 bg-green-500 text-white rounded hover:bg-green-600"
>
<Icon name="ph:download" class="w-4 h-4 mr-1" />
Export Data
</button>
<p v-else class="text-sm text-gray-500">Export not available</p>
</div>
<!-- Approval Workflow -->
<div class="p-4 border rounded-lg">
<h4 class="font-medium mb-2">Approvals</h4>
<button
v-if="canApproveRequests"
@click="approveRequest"
class="w-full px-3 py-2 bg-orange-500 text-white rounded hover:bg-orange-600"
>
<Icon name="ph:check" class="w-4 h-4 mr-1" />
Approve Requests
</button>
<p v-else class="text-sm text-gray-500">Approval not available</p>
</div>
<!-- System Backup -->
<div class="p-4 border rounded-lg">
<h4 class="font-medium mb-2">System Backup</h4>
<button
v-if="canSystemBackup"
@click="createBackup"
class="w-full px-3 py-2 bg-red-500 text-white rounded hover:bg-red-600"
>
<Icon name="ph:database" class="w-4 h-4 mr-1" />
Create Backup
</button>
<p v-else class="text-sm text-gray-500">Backup not available</p>
</div>
</div>
</div>
<!-- Reactive Permission Example -->
<div class="mb-6">
<h3 class="text-lg font-medium mb-2">Reactive Permission Check</h3>
<div class="p-4 bg-gray-50 rounded-lg">
<p class="text-sm mb-2">This demonstrates reactive permission checking:</p>
<div class="space-y-2">
<div v-if="bulkActionPermission.isLoading" class="text-gray-500">
<Icon name="ph:spinner" class="w-4 h-4 animate-spin mr-1" />
Checking bulk action permission...
</div>
<div v-else-if="bulkActionPermission.isAllowed" class="text-green-600">
<Icon name="ph:check-circle" class="w-4 h-4 mr-1" />
Bulk actions are enabled for your role
</div>
<div v-else class="text-red-600">
<Icon name="ph:x-circle" class="w-4 h-4 mr-1" />
Bulk actions are not available for your role
</div>
</div>
<button
@click="bulkActionPermission.checkPermission()"
class="mt-2 px-3 py-1 bg-blue-500 text-white text-sm rounded hover:bg-blue-600"
>
Recheck Permission
</button>
</div>
</div>
<!-- Permission Summary -->
<div class="bg-blue-50 p-4 rounded-lg">
<h3 class="text-lg font-medium mb-2">Your Current Permissions</h3>
<div class="grid grid-cols-2 md:grid-cols-4 gap-2 text-sm">
<div :class="canViewDashboard ? 'text-green-600' : 'text-red-600'">
<Icon :name="canViewDashboard ? 'ph:check' : 'ph:x'" class="w-4 h-4 mr-1" />
Dashboard Access
</div>
<div :class="canEditUser ? 'text-green-600' : 'text-red-600'">
<Icon :name="canEditUser ? 'ph:check' : 'ph:x'" class="w-4 h-4 mr-1" />
Edit Users
</div>
<div :class="canExportData ? 'text-green-600' : 'text-red-600'">
<Icon :name="canExportData ? 'ph:check' : 'ph:x'" class="w-4 h-4 mr-1" />
Export Data
</div>
<div :class="canApproveRequests ? 'text-green-600' : 'text-red-600'">
<Icon :name="canApproveRequests ? 'ph:check' : 'ph:x'" class="w-4 h-4 mr-1" />
Approve Requests
</div>
</div>
</div>
</div>
</template>
<script setup>
import {
useRbacPermissions,
useReactivePermission,
PERMISSION_KEYS,
PERMISSION_ACTIONS
} from '~/composables/useRbacPermissions'
// Initialize permission composable
const {
hasPermission,
canAccessMenu,
canSeeComponent,
canPerformAction,
preloadPermissions
} = useRbacPermissions()
// Menu permissions (reactive)
const canViewDashboard = ref(false)
const canViewUsers = ref(false)
const canViewRBAC = ref(false)
// Component permissions (reactive)
const canEditUser = ref(false)
const canDeleteUser = ref(false)
const canViewSensitiveInfo = ref(false)
// Feature permissions (reactive)
const canExportData = ref(false)
const canApproveRequests = ref(false)
const canSystemBackup = ref(false)
// Reactive permission example using composable
const bulkActionPermission = useReactivePermission(PERMISSION_KEYS.COMPONENT.USER_BULK_ACTIONS)
// Preload all required permissions for better performance
const requiredPermissions = [
PERMISSION_KEYS.MENU.DASHBOARD,
PERMISSION_KEYS.MENU.USERS,
PERMISSION_KEYS.MENU.RBAC,
PERMISSION_KEYS.COMPONENT.USER_EDIT_BUTTON,
PERMISSION_KEYS.COMPONENT.USER_DELETE_BUTTON,
PERMISSION_KEYS.COMPONENT.PROFILE_SENSITIVE_INFO,
PERMISSION_KEYS.FEATURE.EXPORT_DATA,
PERMISSION_KEYS.FEATURE.APPROVE_REQUESTS,
PERMISSION_KEYS.FEATURE.SYSTEM_BACKUP
]
// Check all permissions on component mount
onMounted(async () => {
try {
// Preload permissions for better performance
await preloadPermissions(requiredPermissions)
// Check menu permissions
canViewDashboard.value = await canAccessMenu('/dashboard')
canViewUsers.value = await canAccessMenu('/users')
canViewRBAC.value = await canAccessMenu('/rbac')
// Check component permissions
canEditUser.value = await canSeeComponent(PERMISSION_KEYS.COMPONENT.USER_EDIT_BUTTON)
canDeleteUser.value = await canSeeComponent(PERMISSION_KEYS.COMPONENT.USER_DELETE_BUTTON)
canViewSensitiveInfo.value = await canSeeComponent(PERMISSION_KEYS.COMPONENT.PROFILE_SENSITIVE_INFO)
// Check feature permissions
canExportData.value = await canPerformAction(PERMISSION_KEYS.FEATURE.EXPORT_DATA, PERMISSION_ACTIONS.EXPORT)
canApproveRequests.value = await canPerformAction(PERMISSION_KEYS.FEATURE.APPROVE_REQUESTS, PERMISSION_ACTIONS.APPROVE)
canSystemBackup.value = await canPerformAction(PERMISSION_KEYS.FEATURE.SYSTEM_BACKUP, PERMISSION_ACTIONS.CREATE)
} catch (error) {
console.error('Failed to load permissions:', error)
}
})
// Action handlers
const editUser = () => {
console.log('Edit user action')
// Implementation here
}
const deleteUser = () => {
console.log('Delete user action')
// Implementation here
}
const exportData = () => {
console.log('Export data action')
// Implementation here
}
const approveRequest = () => {
console.log('Approve request action')
// Implementation here
}
const createBackup = () => {
console.log('Create backup action')
// Implementation here
}
</script>
<style scoped>
.permission-example {
@apply max-w-4xl mx-auto p-6;
}
.animate-spin {
animation: spin 1s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style>