refactor: update permission management and role structure
- Enhanced the permission management system by introducing a new base permissions structure, allowing for better organization and clarity. - Updated the role creation process to normalize role levels, limiting them to two levels: 0 (maximum access) and 1 (administrative access). - Improved the UI for permission displays, ensuring users are informed when no permissions are available. - Added alerts and messages to guide users in creating permissions when none exist. - Streamlined backend queries for permissions and roles to improve performance and maintainability.
This commit is contained in:
@@ -543,7 +543,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else if catalogoQuery.data}
|
||||
{:else if catalogoQuery.data && catalogoQuery.data.length > 0}
|
||||
<div class="space-y-2">
|
||||
{#each catalogoQuery.data as item (item.recurso)}
|
||||
{@const recursoExpandido = isRecursoExpandido(roleId, item.recurso)}
|
||||
@@ -576,28 +576,40 @@
|
||||
<!-- Lista de ações (visível quando expandido) -->
|
||||
{#if recursoExpandido}
|
||||
<div class="bg-base-100 border-base-300 border-t px-4 py-3">
|
||||
<div class="space-y-2">
|
||||
{#each ['ver', 'listar', 'criar', 'editar', 'excluir'] as acao (acao)}
|
||||
<label
|
||||
class="hover:bg-base-200 flex cursor-pointer items-center gap-3 rounded p-2 transition-colors"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checkbox-primary"
|
||||
checked={isConcedida(roleId, item.recurso, acao)}
|
||||
disabled={salvando}
|
||||
onchange={(e) =>
|
||||
toggleAcao(roleId, item.recurso, acao, e.currentTarget.checked)}
|
||||
/>
|
||||
<span class="flex-1 font-medium capitalize">{acao}</span>
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
{#if item.acoes.length === 0}
|
||||
<p class="text-base-content/60 text-sm">
|
||||
Nenhuma permissão cadastrada para este recurso.
|
||||
</p>
|
||||
{:else}
|
||||
<div class="space-y-2">
|
||||
{#each item.acoes as acao (acao)}
|
||||
<label
|
||||
class="hover:bg-base-200 flex cursor-pointer items-center gap-3 rounded p-2 transition-colors"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checkbox-primary"
|
||||
checked={isConcedida(roleId, item.recurso, acao)}
|
||||
disabled={salvando}
|
||||
onchange={(e) =>
|
||||
toggleAcao(roleId, item.recurso, acao, e.currentTarget.checked)}
|
||||
/>
|
||||
<span class="flex-1 font-medium">{acao}</span>
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="alert alert-info mt-4">
|
||||
<span class="font-semibold">
|
||||
Nenhuma permissão cadastrada ainda. Use o botão “Criar permissão” para começar.
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -41,19 +41,15 @@
|
||||
const stats = $derived.by(() => {
|
||||
if (carregando) return null;
|
||||
|
||||
const porNivel = {
|
||||
0: roles.filter((r) => r.nivel === 0).length,
|
||||
1: roles.filter((r) => r.nivel === 1).length,
|
||||
2: roles.filter((r) => r.nivel === 2).length,
|
||||
3: roles.filter((r) => r.nivel >= 3).length
|
||||
};
|
||||
const nivelMaximo = roles.filter((r) => r.nivel === 0).length;
|
||||
const nivelAdministrativo = roles.filter((r) => r.nivel === 1).length;
|
||||
const niveisLegado = roles.filter((r) => r.nivel > 1).length;
|
||||
|
||||
return {
|
||||
total: roles.length,
|
||||
nivelMaximo: porNivel[0],
|
||||
nivelAlto: porNivel[1],
|
||||
nivelMedio: porNivel[2],
|
||||
nivelBaixo: porNivel[3],
|
||||
nivelMaximo,
|
||||
nivelAdministrativo,
|
||||
niveisLegado,
|
||||
comSetor: roles.filter((r) => r.setor).length
|
||||
};
|
||||
});
|
||||
@@ -78,10 +74,11 @@
|
||||
|
||||
// Filtro por nível
|
||||
if (filtroNivel !== '') {
|
||||
if (filtroNivel === 3) {
|
||||
resultado = resultado.filter((r) => r.nivel >= 3);
|
||||
} else {
|
||||
if (filtroNivel === 0 || filtroNivel === 1) {
|
||||
resultado = resultado.filter((r) => r.nivel === filtroNivel);
|
||||
} else {
|
||||
// Qualquer outro valor é considerado legado
|
||||
resultado = resultado.filter((r) => r.nivel > 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,22 +93,19 @@
|
||||
function obterCorNivel(nivel: number): string {
|
||||
if (nivel === 0) return 'badge-error';
|
||||
if (nivel === 1) return 'badge-warning';
|
||||
if (nivel === 2) return 'badge-info';
|
||||
// Níveis > 1 são considerados legado
|
||||
return 'badge-ghost';
|
||||
}
|
||||
|
||||
function obterTextoNivel(nivel: number): string {
|
||||
if (nivel === 0) return 'Máximo';
|
||||
if (nivel === 1) return 'Alto';
|
||||
if (nivel === 2) return 'Médio';
|
||||
if (nivel === 3) return 'Baixo';
|
||||
return `Nível ${nivel}`;
|
||||
if (nivel === 1) return 'Administrativo';
|
||||
return `Legado (${nivel})`;
|
||||
}
|
||||
|
||||
function obterCorCardNivel(nivel: number): string {
|
||||
if (nivel === 0) return 'border-l-4 border-error';
|
||||
if (nivel === 1) return 'border-l-4 border-warning';
|
||||
if (nivel === 2) return 'border-l-4 border-info';
|
||||
return 'border-l-4 border-base-300';
|
||||
}
|
||||
|
||||
@@ -176,31 +170,24 @@
|
||||
|
||||
<!-- Estatísticas -->
|
||||
{#if stats}
|
||||
<div class="mb-8 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-5">
|
||||
<div class="mb-8 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<StatsCard title="Total de Perfis" value={stats.total} Icon={Users} color="primary" />
|
||||
<StatsCard
|
||||
title="Nível Máximo"
|
||||
title="Nível Máximo (0)"
|
||||
value={stats.nivelMaximo}
|
||||
description="Acesso total"
|
||||
description="Acesso total ao sistema"
|
||||
Icon={Shield}
|
||||
color="error"
|
||||
/>
|
||||
<StatsCard
|
||||
title="Nível Alto"
|
||||
value={stats.nivelAlto}
|
||||
description="Acesso elevado"
|
||||
title="Nível Administrativo (1)"
|
||||
value={stats.nivelAdministrativo}
|
||||
description="Perfis administrativos com acesso total"
|
||||
Icon={AlertTriangle}
|
||||
color="warning"
|
||||
/>
|
||||
<StatsCard
|
||||
title="Nível Médio"
|
||||
value={stats.nivelMedio}
|
||||
description="Acesso padrão"
|
||||
Icon={Info}
|
||||
color="info"
|
||||
/>
|
||||
<StatsCard
|
||||
title="Com Setor"
|
||||
title="Perfis com Setor"
|
||||
value={stats.comSetor}
|
||||
description={stats.total > 0
|
||||
? ((stats.comSetor / stats.total) * 100).toFixed(0) + '% do total'
|
||||
@@ -209,6 +196,18 @@
|
||||
color="secondary"
|
||||
/>
|
||||
</div>
|
||||
{#if stats.niveisLegado > 0}
|
||||
<div class="alert alert-warning mb-6">
|
||||
<Info class="h-5 w-5" />
|
||||
<div>
|
||||
<h3 class="font-bold">Perfis com níveis legados</h3>
|
||||
<p class="text-sm">
|
||||
Existem {stats.niveisLegado} perfis com nível acima de 1. Esses perfis continuarão
|
||||
sendo tratados como nível 1 (administrativo) após a migração.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<!-- Filtros -->
|
||||
|
||||
Reference in New Issue
Block a user