corrad-af-2024/components/rbac/RoleTemplates.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

238 lines
7.8 KiB
Vue

<template>
<rs-card>
<template #header>
<div>
<h3 class="text-lg font-medium text-gray-900 dark:text-white">Quick Role Templates</h3>
<p class="text-sm text-gray-600 dark:text-gray-400">Apply pre-configured permission sets to roles</p>
</div>
</template>
<template #body>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div
v-for="template in templates"
:key="template.id"
@click="applyTemplate(template.id)"
class="template-card cursor-pointer p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 hover:bg-primary-50 dark:hover:bg-primary-900/10 transition-colors group"
>
<div class="flex items-center mb-3">
<div
class="p-2 rounded-lg mr-3 transition-colors"
:class="template.iconBg"
>
<Icon
:name="template.icon"
class="w-5 h-5"
:class="template.iconColor"
/>
</div>
<div>
<h4 class="font-medium text-gray-900 dark:text-white">{{ template.name }}</h4>
<p class="text-xs text-gray-500 dark:text-gray-400">{{ template.userCount }} users</p>
</div>
</div>
<p class="text-sm text-gray-600 dark:text-gray-400 mb-3">{{ template.description }}</p>
<!-- Permission Preview -->
<div class="space-y-2">
<div class="flex items-center justify-between text-xs">
<span class="text-gray-500 dark:text-gray-400">Permissions</span>
<span class="font-medium text-gray-700 dark:text-gray-300">{{ template.permissionCount }}</span>
</div>
<!-- Permission Categories -->
<div class="flex flex-wrap gap-1">
<span
v-for="category in template.categories"
:key="category"
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300"
>
{{ category }}
</span>
</div>
<!-- Permission Level Indicator -->
<div class="flex items-center mt-2">
<div class="flex-1 bg-gray-200 dark:bg-gray-700 rounded-full h-1.5">
<div
class="h-1.5 rounded-full transition-all duration-300"
:class="template.levelColor"
:style="{ width: template.permissionLevel + '%' }"
></div>
</div>
<span class="ml-2 text-xs text-gray-500 dark:text-gray-400">{{ template.levelLabel }}</span>
</div>
</div>
<!-- Apply Button -->
<div class="mt-3 pt-3 border-t border-gray-200 dark:border-gray-700">
<rs-button
@click.stop="applyTemplate(template.id)"
variant="primary-outline"
size="sm"
class="w-full text-xs"
>
Apply Template
</rs-button>
</div>
</div>
</div>
<!-- Selected Role Info -->
<div v-if="selectedRole" class="mt-6 p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg">
<div class="flex items-center">
<Icon name="ph:info" class="w-5 h-5 text-blue-600 dark:text-blue-400 mr-2" />
<span class="text-sm text-blue-800 dark:text-blue-200">
Template will be applied to <strong>{{ selectedRole.name }}</strong> role
</span>
</div>
</div>
<!-- Custom Template Creator -->
<div class="mt-6 pt-6 border-t border-gray-200 dark:border-gray-700">
<div class="flex items-center justify-between mb-4">
<h4 class="text-sm font-medium text-gray-900 dark:text-white">Custom Templates</h4>
<rs-button
@click="$emit('create-custom-template')"
variant="primary-outline"
size="sm"
>
<Icon name="ph:plus" class="w-4 h-4 mr-1" />
Create Custom
</rs-button>
</div>
<div v-if="customTemplates.length > 0" class="grid grid-cols-1 md:grid-cols-2 gap-3">
<div
v-for="customTemplate in customTemplates"
:key="customTemplate.id"
class="flex items-center justify-between p-3 border border-gray-200 dark:border-gray-700 rounded-lg"
>
<div>
<h5 class="text-sm font-medium text-gray-900 dark:text-white">{{ customTemplate.name }}</h5>
<p class="text-xs text-gray-500 dark:text-gray-400">{{ customTemplate.description }}</p>
</div>
<div class="flex items-center space-x-2">
<button
@click="applyTemplate(customTemplate.id)"
class="text-xs text-primary hover:text-primary/80"
>
Apply
</button>
<button
@click="$emit('edit-custom-template', customTemplate.id)"
class="text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700"
>
Edit
</button>
</div>
</div>
</div>
<div v-else class="text-center py-4">
<p class="text-sm text-gray-500 dark:text-gray-400">No custom templates created yet</p>
</div>
</div>
</template>
</rs-card>
</template>
<script setup>
const props = defineProps({
selectedRole: {
type: Object,
default: null
},
customTemplates: {
type: Array,
default: () => []
}
})
const emit = defineEmits([
'template-applied',
'create-custom-template',
'edit-custom-template'
])
const templates = [
{
id: 'administrator',
name: 'Administrator',
description: 'Full access to all features and functions',
icon: 'ph:crown',
iconColor: 'text-yellow-600 dark:text-yellow-400',
iconBg: 'bg-yellow-100 dark:bg-yellow-900/30',
userCount: 2,
permissionCount: 45,
permissionLevel: 100,
levelLabel: 'Full Access',
levelColor: 'bg-red-500',
categories: ['All Menus', 'All Components', 'All Features']
},
{
id: 'manager',
name: 'Manager',
description: 'Team management and approval permissions',
icon: 'ph:briefcase',
iconColor: 'text-blue-600 dark:text-blue-400',
iconBg: 'bg-blue-100 dark:bg-blue-900/30',
userCount: 8,
permissionCount: 28,
permissionLevel: 75,
levelLabel: 'High Access',
levelColor: 'bg-orange-500',
categories: ['Management', 'Approval', 'Reports']
},
{
id: 'editor',
name: 'Editor',
description: 'Content creation and editing capabilities',
icon: 'ph:pencil',
iconColor: 'text-green-600 dark:text-green-400',
iconBg: 'bg-green-100 dark:bg-green-900/30',
userCount: 15,
permissionCount: 18,
permissionLevel: 50,
levelLabel: 'Medium Access',
levelColor: 'bg-yellow-500',
categories: ['Content', 'Basic Edit', 'View']
},
{
id: 'viewer',
name: 'Viewer',
description: 'Read-only access to assigned areas',
icon: 'ph:eye',
iconColor: 'text-gray-600 dark:text-gray-400',
iconBg: 'bg-gray-100 dark:bg-gray-900/30',
userCount: 25,
permissionCount: 8,
permissionLevel: 25,
levelLabel: 'View Only',
levelColor: 'bg-blue-500',
categories: ['View Only', 'Basic Access']
}
]
const applyTemplate = (templateId) => {
emit('template-applied', templateId)
}
</script>
<style scoped>
.template-card:hover .bg-yellow-100 {
@apply bg-yellow-200;
}
.template-card:hover .bg-blue-100 {
@apply bg-blue-200;
}
.template-card:hover .bg-green-100 {
@apply bg-green-200;
}
.template-card:hover .bg-gray-100 {
@apply bg-gray-200;
}
</style>