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:
@@ -3,27 +3,271 @@ import { v } from 'convex/values';
|
||||
import type { Doc } from './_generated/dataModel';
|
||||
import { getCurrentUserFunction } from './auth';
|
||||
|
||||
// Catálogo base de recursos e ações
|
||||
// Ajuste/expanda conforme os módulos disponíveis no sistema
|
||||
export const CATALOGO_RECURSOS = [
|
||||
{
|
||||
recurso: 'funcionarios',
|
||||
acoes: [
|
||||
'dashboard',
|
||||
'ver',
|
||||
'listar',
|
||||
'criar',
|
||||
'editar',
|
||||
'excluir',
|
||||
'aprovar_ausencias',
|
||||
'aprovar_ferias'
|
||||
]
|
||||
},
|
||||
{
|
||||
recurso: 'simbolos',
|
||||
acoes: ['dashboard', 'ver', 'listar', 'criar', 'editar', 'excluir']
|
||||
}
|
||||
] as const;
|
||||
// Catálogo de permissões base para seed controlado via mutation
|
||||
const PERMISSOES_BASE = {
|
||||
permissoes: [
|
||||
// Funcionários
|
||||
{
|
||||
nome: 'funcionarios.dashboard',
|
||||
recurso: 'funcionarios',
|
||||
acao: 'dashboard',
|
||||
descricao: 'Acessar o painel de funcionários'
|
||||
},
|
||||
{
|
||||
nome: 'funcionarios.ver',
|
||||
recurso: 'funcionarios',
|
||||
acao: 'ver',
|
||||
descricao: 'Visualizar detalhes de funcionários'
|
||||
},
|
||||
{
|
||||
nome: 'funcionarios.listar',
|
||||
recurso: 'funcionarios',
|
||||
acao: 'listar',
|
||||
descricao: 'Listar funcionários'
|
||||
},
|
||||
{
|
||||
nome: 'funcionarios.criar',
|
||||
recurso: 'funcionarios',
|
||||
acao: 'criar',
|
||||
descricao: 'Criar novos funcionários'
|
||||
},
|
||||
{
|
||||
nome: 'funcionarios.editar',
|
||||
recurso: 'funcionarios',
|
||||
acao: 'editar',
|
||||
descricao: 'Editar dados de funcionários'
|
||||
},
|
||||
{
|
||||
nome: 'funcionarios.excluir',
|
||||
recurso: 'funcionarios',
|
||||
acao: 'excluir',
|
||||
descricao: 'Excluir funcionários'
|
||||
},
|
||||
{
|
||||
nome: 'funcionarios.aprovar_ausencias',
|
||||
recurso: 'funcionarios',
|
||||
acao: 'aprovar_ausencias',
|
||||
descricao: 'Aprovar ausências de funcionários'
|
||||
},
|
||||
{
|
||||
nome: 'funcionarios.aprovar_ferias',
|
||||
recurso: 'funcionarios',
|
||||
acao: 'aprovar_ferias',
|
||||
descricao: 'Aprovar férias de funcionários'
|
||||
},
|
||||
// Símbolos
|
||||
{
|
||||
nome: 'simbolos.dashboard',
|
||||
recurso: 'simbolos',
|
||||
acao: 'dashboard',
|
||||
descricao: 'Acessar o painel de símbolos'
|
||||
},
|
||||
{
|
||||
nome: 'simbolos.ver',
|
||||
recurso: 'simbolos',
|
||||
acao: 'ver',
|
||||
descricao: 'Visualizar detalhes de símbolos'
|
||||
},
|
||||
{
|
||||
nome: 'simbolos.listar',
|
||||
recurso: 'simbolos',
|
||||
acao: 'listar',
|
||||
descricao: 'Listar símbolos'
|
||||
},
|
||||
{
|
||||
nome: 'simbolos.criar',
|
||||
recurso: 'simbolos',
|
||||
acao: 'criar',
|
||||
descricao: 'Criar novos símbolos'
|
||||
},
|
||||
{
|
||||
nome: 'simbolos.editar',
|
||||
recurso: 'simbolos',
|
||||
acao: 'editar',
|
||||
descricao: 'Editar símbolos'
|
||||
},
|
||||
{
|
||||
nome: 'simbolos.excluir',
|
||||
recurso: 'simbolos',
|
||||
acao: 'excluir',
|
||||
descricao: 'Excluir símbolos'
|
||||
},
|
||||
// TI - Usuários
|
||||
{
|
||||
nome: 'ti_usuarios.listar',
|
||||
recurso: 'ti_usuarios',
|
||||
acao: 'listar',
|
||||
descricao: 'Listar usuários do sistema'
|
||||
},
|
||||
{
|
||||
nome: 'ti_usuarios.criar',
|
||||
recurso: 'ti_usuarios',
|
||||
acao: 'criar',
|
||||
descricao: 'Criar novos usuários de acesso'
|
||||
},
|
||||
{
|
||||
nome: 'ti_usuarios.editar',
|
||||
recurso: 'ti_usuarios',
|
||||
acao: 'editar',
|
||||
descricao: 'Editar usuários de acesso'
|
||||
},
|
||||
{
|
||||
nome: 'ti_usuarios.bloquear',
|
||||
recurso: 'ti_usuarios',
|
||||
acao: 'bloquear',
|
||||
descricao: 'Bloquear ou desbloquear usuários'
|
||||
},
|
||||
// TI - Perfis
|
||||
{
|
||||
nome: 'ti_perfis.listar',
|
||||
recurso: 'ti_perfis',
|
||||
acao: 'listar',
|
||||
descricao: 'Listar perfis de acesso'
|
||||
},
|
||||
{
|
||||
nome: 'ti_perfis.criar',
|
||||
recurso: 'ti_perfis',
|
||||
acao: 'criar',
|
||||
descricao: 'Criar novos perfis de acesso'
|
||||
},
|
||||
{
|
||||
nome: 'ti_perfis.editar',
|
||||
recurso: 'ti_perfis',
|
||||
acao: 'editar',
|
||||
descricao: 'Editar perfis de acesso'
|
||||
},
|
||||
// TI - Painel de Permissões
|
||||
{
|
||||
nome: 'ti_painel_permissoes.gerenciar',
|
||||
recurso: 'ti_painel_permissoes',
|
||||
acao: 'gerenciar',
|
||||
descricao: 'Gerenciar matriz de permissões por perfil'
|
||||
},
|
||||
// TI - Solicitações de Acesso
|
||||
{
|
||||
nome: 'ti_solicitacoes_acesso.ver',
|
||||
recurso: 'ti_solicitacoes_acesso',
|
||||
acao: 'ver',
|
||||
descricao: 'Visualizar solicitações de acesso'
|
||||
},
|
||||
{
|
||||
nome: 'ti_solicitacoes_acesso.aprovar',
|
||||
recurso: 'ti_solicitacoes_acesso',
|
||||
acao: 'aprovar',
|
||||
descricao: 'Aprovar solicitações de acesso'
|
||||
},
|
||||
{
|
||||
nome: 'ti_solicitacoes_acesso.reprovar',
|
||||
recurso: 'ti_solicitacoes_acesso',
|
||||
acao: 'reprovar',
|
||||
descricao: 'Reprovar solicitações de acesso'
|
||||
},
|
||||
// TI - Configurações de E-mail
|
||||
{
|
||||
nome: 'ti_configuracoes_email.configurar',
|
||||
recurso: 'ti_configuracoes_email',
|
||||
acao: 'configurar',
|
||||
descricao: 'Configurar parâmetros de envio de e-mail'
|
||||
},
|
||||
// TI - Monitoramento
|
||||
{
|
||||
nome: 'ti_monitoramento.ver',
|
||||
recurso: 'ti_monitoramento',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar painel de monitoramento geral'
|
||||
},
|
||||
{
|
||||
nome: 'ti_monitoramento_emails.ver',
|
||||
recurso: 'ti_monitoramento_emails',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar monitoramento de envio de e-mails'
|
||||
},
|
||||
// TI - Notificações
|
||||
{
|
||||
nome: 'ti_notificacoes.configurar',
|
||||
recurso: 'ti_notificacoes',
|
||||
acao: 'configurar',
|
||||
descricao: 'Configurar notificações do sistema'
|
||||
},
|
||||
// TI - Times
|
||||
{
|
||||
nome: 'ti_times.gerenciar',
|
||||
recurso: 'ti_times',
|
||||
acao: 'gerenciar',
|
||||
descricao: 'Gerenciar times/equipes de TI'
|
||||
},
|
||||
// TI - Painel Administrativo
|
||||
{
|
||||
nome: 'ti_painel_administrativo.ver',
|
||||
recurso: 'ti_painel_administrativo',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar painel administrativo de TI'
|
||||
},
|
||||
// Financeiro
|
||||
{
|
||||
nome: 'financeiro.ver',
|
||||
recurso: 'financeiro',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar telas do módulo de financeiro'
|
||||
},
|
||||
// Controladoria
|
||||
{
|
||||
nome: 'controladoria.ver',
|
||||
recurso: 'controladoria',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar telas do módulo de controladoria'
|
||||
},
|
||||
// Licitações
|
||||
{
|
||||
nome: 'licitacoes.ver',
|
||||
recurso: 'licitacoes',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar telas do módulo de licitações'
|
||||
},
|
||||
// Compras
|
||||
{
|
||||
nome: 'compras.ver',
|
||||
recurso: 'compras',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar telas do módulo de compras'
|
||||
},
|
||||
// Jurídico
|
||||
{
|
||||
nome: 'juridico.ver',
|
||||
recurso: 'juridico',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar telas do módulo jurídico'
|
||||
},
|
||||
// Comunicação
|
||||
{
|
||||
nome: 'comunicacao.ver',
|
||||
recurso: 'comunicacao',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar telas do módulo de comunicação'
|
||||
},
|
||||
// Programas Esportivos
|
||||
{
|
||||
nome: 'programas_esportivos.ver',
|
||||
recurso: 'programas_esportivos',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar telas do módulo de programas esportivos'
|
||||
},
|
||||
// Secretaria Executiva
|
||||
{
|
||||
nome: 'secretaria_executiva.ver',
|
||||
recurso: 'secretaria_executiva',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar telas do módulo de secretaria executiva'
|
||||
},
|
||||
// Gestão de Pessoas
|
||||
{
|
||||
nome: 'gestao_pessoas.ver',
|
||||
recurso: 'gestao_pessoas',
|
||||
acao: 'ver',
|
||||
descricao: 'Acessar telas do módulo de gestão de pessoas'
|
||||
}
|
||||
]
|
||||
} as const;
|
||||
|
||||
export const listarRecursosEAcoes = query({
|
||||
args: {},
|
||||
@@ -33,10 +277,18 @@ export const listarRecursosEAcoes = query({
|
||||
acoes: v.array(v.string())
|
||||
})
|
||||
),
|
||||
handler: async () => {
|
||||
return CATALOGO_RECURSOS.map((r) => ({
|
||||
recurso: r.recurso,
|
||||
acoes: [...r.acoes]
|
||||
handler: async (ctx) => {
|
||||
const permissoes = await ctx.db.query('permissoes').collect();
|
||||
|
||||
const recursos: Record<string, Set<string>> = {};
|
||||
for (const perm of permissoes) {
|
||||
const set = (recursos[perm.recurso] ||= new Set<string>());
|
||||
set.add(perm.acao);
|
||||
}
|
||||
|
||||
return Object.entries(recursos).map(([recurso, acoes]) => ({
|
||||
recurso,
|
||||
acoes: Array.from(acoes).sort()
|
||||
}));
|
||||
}
|
||||
});
|
||||
@@ -56,7 +308,7 @@ export const listarPermissoesAcoesPorRole = query({
|
||||
.withIndex('by_role', (q) => q.eq('roleId', args.roleId))
|
||||
.collect();
|
||||
|
||||
// Carregar documentos de permissões
|
||||
// Carregar documentos de permissões vinculadas a este role
|
||||
const actionsByResource: Record<string, Set<string>> = {};
|
||||
for (const rp of rolePerms) {
|
||||
const perm = await ctx.db.get(rp.permissaoId);
|
||||
@@ -65,13 +317,10 @@ export const listarPermissoesAcoesPorRole = query({
|
||||
set.add(perm.acao);
|
||||
}
|
||||
|
||||
// Normalizar para todos os recursos do catálogo
|
||||
const result: Array<{ recurso: string; acoes: Array<string> }> = [];
|
||||
for (const item of CATALOGO_RECURSOS) {
|
||||
const granted = Array.from(actionsByResource[item.recurso] ?? new Set<string>());
|
||||
result.push({ recurso: item.recurso, acoes: granted });
|
||||
}
|
||||
return result;
|
||||
return Object.entries(actionsByResource).map(([recurso, acoes]) => ({
|
||||
recurso,
|
||||
acoes: Array.from(acoes).sort()
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -84,24 +333,12 @@ export const atualizarPermissaoAcao = mutation({
|
||||
},
|
||||
returns: v.null(),
|
||||
handler: async (ctx, args) => {
|
||||
// Garantir documento de permissão (recurso+acao)
|
||||
let permissao = await ctx.db
|
||||
// Buscar documento de permissão (recurso+acao)
|
||||
const permissao = await ctx.db
|
||||
.query('permissoes')
|
||||
.withIndex('by_recurso_e_acao', (q) => q.eq('recurso', args.recurso).eq('acao', args.acao))
|
||||
.first();
|
||||
|
||||
if (!permissao) {
|
||||
const nome = `${args.recurso}.${args.acao}`;
|
||||
const descricao = `Permite ${args.acao} em ${args.recurso}`;
|
||||
const id = await ctx.db.insert('permissoes', {
|
||||
nome,
|
||||
descricao,
|
||||
recurso: args.recurso,
|
||||
acao: args.acao
|
||||
});
|
||||
permissao = await ctx.db.get(id);
|
||||
}
|
||||
|
||||
if (!permissao) return null;
|
||||
|
||||
// Verificar vínculo atual
|
||||
@@ -128,6 +365,36 @@ export const atualizarPermissaoAcao = mutation({
|
||||
}
|
||||
});
|
||||
|
||||
export const seedPermissoesBase = mutation({
|
||||
args: {},
|
||||
returns: v.null(),
|
||||
handler: async (ctx) => {
|
||||
console.log('🔐 Seed de permissões base...');
|
||||
|
||||
for (const perm of PERMISSOES_BASE.permissoes) {
|
||||
const existente = await ctx.db
|
||||
.query('permissoes')
|
||||
.withIndex('by_nome', (q) => q.eq('nome', perm.nome))
|
||||
.first();
|
||||
|
||||
if (existente) {
|
||||
console.log(` ℹ️ Permissão já existe: ${perm.nome}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
await ctx.db.insert('permissoes', {
|
||||
nome: perm.nome,
|
||||
descricao: perm.descricao,
|
||||
recurso: perm.recurso,
|
||||
acao: perm.acao
|
||||
});
|
||||
console.log(` ✅ Permissão criada: ${perm.nome}`);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
export const verificarAcao = query({
|
||||
args: {
|
||||
usuarioId: v.id('usuarios'),
|
||||
|
||||
Reference in New Issue
Block a user