- 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.
238 lines
7.8 KiB
Vue
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> |