generated from corrad-software/corrad-af-2024
206 lines
7.0 KiB
Vue
206 lines
7.0 KiB
Vue
<script setup>
|
|
import { ref, computed, onMounted, defineAsyncComponent } from 'vue';
|
|
import { useDmsStore } from '~/stores/dms';
|
|
|
|
// Define page metadata
|
|
definePageMeta({
|
|
title: "Access Management",
|
|
middleware: ["auth"],
|
|
requiresAuth: true,
|
|
breadcrumb: [
|
|
{
|
|
name: "DMS",
|
|
path: "/dms",
|
|
},
|
|
{
|
|
name: "Access Management",
|
|
path: "/dms/access-management",
|
|
},
|
|
],
|
|
});
|
|
|
|
// Lazy load components to improve initial page load
|
|
const DMSApprovalQueue = defineAsyncComponent(() =>
|
|
import('~/components/dms/workflows/DMSApprovalQueue.vue')
|
|
);
|
|
const DMSAccessRequestTracker = defineAsyncComponent(() =>
|
|
import('~/components/dms/workflows/DMSAccessRequestTracker.vue')
|
|
);
|
|
|
|
// Store
|
|
const dmsStore = useDmsStore();
|
|
|
|
// Component state
|
|
const activeTab = ref('requests');
|
|
const isLoading = ref(true);
|
|
const hasError = ref(false);
|
|
const errorMessage = ref('');
|
|
|
|
// User role and permissions
|
|
const userPermissions = ref({
|
|
canApprove: false,
|
|
canReject: false,
|
|
canViewAll: false
|
|
});
|
|
|
|
// Tabs definition
|
|
const tabs = [
|
|
{
|
|
id: 'requests',
|
|
label: 'Access Requests',
|
|
icon: 'lock-access',
|
|
description: 'Manage pending and historical access requests'
|
|
},
|
|
{
|
|
id: 'metrics',
|
|
label: 'Performance Metrics',
|
|
icon: 'chart',
|
|
description: 'Track access request KPIs and time metrics'
|
|
}
|
|
];
|
|
|
|
// Methods
|
|
const changeTab = (tabId) => {
|
|
activeTab.value = tabId;
|
|
};
|
|
|
|
// Load user permissions
|
|
const loadUserPermissions = async () => {
|
|
try {
|
|
isLoading.value = true;
|
|
|
|
// In a real implementation, this would be fetched from an authentication service
|
|
// For now we'll simulate it with the store
|
|
const userId = dmsStore.currentUser.id;
|
|
const userRole = dmsStore.currentUser.role;
|
|
|
|
// Get permissions from the store (simulated Authentik integration)
|
|
const permissions = await dmsStore.getRbacPermissions(userId);
|
|
|
|
// Set the permissions
|
|
userPermissions.value = {
|
|
canApprove: permissions.permissions.accessRequests.approve || false,
|
|
canReject: permissions.permissions.accessRequests.reject || false,
|
|
canViewAll: permissions.permissions.accessRequests.viewAll || false
|
|
};
|
|
} catch (error) {
|
|
console.error('Failed to load user permissions:', error);
|
|
hasError.value = true;
|
|
errorMessage.value = 'Failed to load user permissions. Please try again.';
|
|
} finally {
|
|
isLoading.value = false;
|
|
}
|
|
};
|
|
|
|
// Get SVG icon
|
|
const getSvgIcon = (iconName) => {
|
|
const icons = {
|
|
'lock-access': `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>`,
|
|
'chart': `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"></line><line x1="12" y1="20" x2="12" y2="4"></line><line x1="6" y1="20" x2="6" y2="14"></line></svg>`,
|
|
'user': `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>`
|
|
};
|
|
|
|
return icons[iconName] || '';
|
|
};
|
|
|
|
// Lifecycle hooks
|
|
onMounted(() => {
|
|
loadUserPermissions();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="dms-access-management h-screen flex flex-col">
|
|
<LayoutsBreadcrumb />
|
|
|
|
<div class="flex-1 min-h-0 p-4">
|
|
<RsCard
|
|
height="full"
|
|
overflow="hidden"
|
|
bodyPadding="none"
|
|
class="h-full"
|
|
>
|
|
<template #header>
|
|
<div class="flex justify-between items-center">
|
|
<h1 class="text-2xl font-bold text-gray-900 dark:text-gray-100">Access Management</h1>
|
|
<div class="flex space-x-2">
|
|
<RsButton variant="secondary-outline" size="sm">
|
|
<Icon name="mdi:export" class="w-4 h-4 mr-2" />
|
|
Export Report
|
|
</RsButton>
|
|
|
|
<RsButton variant="primary" size="sm">
|
|
<Icon name="mdi:plus" class="w-4 h-4 mr-2" />
|
|
New Request
|
|
</RsButton>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<template #body>
|
|
<div class="h-full flex flex-col min-h-0">
|
|
<!-- Tabs -->
|
|
<div class="border-b border-gray-200 dark:border-gray-700 px-6">
|
|
<nav class="-mb-px flex space-x-8">
|
|
<button
|
|
@click="activeTab = 'requests'"
|
|
:class="[
|
|
'py-2 px-1 border-b-2 font-medium text-sm transition-colors',
|
|
activeTab === 'requests'
|
|
? 'border-primary text-primary'
|
|
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300'
|
|
]"
|
|
>
|
|
Access Requests
|
|
<span v-if="pendingCount > 0" class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
|
|
{{ pendingCount }}
|
|
</span>
|
|
</button>
|
|
|
|
<button
|
|
@click="activeTab = 'metrics'"
|
|
:class="[
|
|
'py-2 px-1 border-b-2 font-medium text-sm transition-colors',
|
|
activeTab === 'metrics'
|
|
? 'border-primary text-primary'
|
|
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300'
|
|
]"
|
|
>
|
|
Performance Metrics
|
|
</button>
|
|
</nav>
|
|
</div>
|
|
|
|
<!-- Tab Content - Scrollable -->
|
|
<div class="flex-1 overflow-auto min-h-0">
|
|
<!-- Access Requests Tab -->
|
|
<div v-if="activeTab === 'requests'" class="h-full">
|
|
<DMSApprovalQueue
|
|
:showClosed="userPermissions.canViewAll"
|
|
:filterByUser="userPermissions.canViewAll ? null : dmsStore.currentUser.id"
|
|
:maxItems="0"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Metrics Tab -->
|
|
<div v-else-if="activeTab === 'metrics'" class="h-full">
|
|
<DMSAccessRequestTracker
|
|
:userId="userPermissions.canViewAll ? null : dmsStore.currentUser.id"
|
|
:timeRange="'30days'"
|
|
:showPersonal="true"
|
|
:showDepartmental="userPermissions.canViewAll"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</RsCard>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.dms-access-management {
|
|
height: calc(100vh - 64px);
|
|
}
|
|
</style> |