feat: implement permission checks for various actions across multiple resources, including acoes, atas, atestados, ausencias, ferias, and simbolos

This commit is contained in:
2025-12-12 09:26:30 -03:00
parent 4eb49d3e63
commit 92a9605417
8 changed files with 554 additions and 51 deletions

View File

@@ -1,10 +1,15 @@
import { v } from 'convex/values';
import { mutation, query } from './_generated/server';
import { getCurrentUserFunction } from './auth';
import { internal } from './_generated/api';
export const list = query({
args: {},
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'acoes',
acao: 'listar'
});
return await ctx.db.query('acoes').collect();
}
});
@@ -15,6 +20,11 @@ export const create = mutation({
tipo: v.union(v.literal('projeto'), v.literal('lei'))
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'acoes',
acao: 'criar'
});
const user = await getCurrentUserFunction(ctx);
if (!user) throw new Error('Unauthorized');
@@ -33,6 +43,11 @@ export const update = mutation({
tipo: v.union(v.literal('projeto'), v.literal('lei'))
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'acoes',
acao: 'editar'
});
const user = await getCurrentUserFunction(ctx);
if (!user) throw new Error('Unauthorized');
@@ -48,6 +63,11 @@ export const remove = mutation({
id: v.id('acoes')
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'acoes',
acao: 'excluir'
});
const user = await getCurrentUserFunction(ctx);
if (!user) throw new Error('Unauthorized');

View File

@@ -2,10 +2,15 @@ import { v } from 'convex/values';
import { mutation, query } from './_generated/server';
import type { Id } from './_generated/dataModel';
import { getCurrentUserFunction } from './auth';
import { internal } from './_generated/api';
export const list = query({
args: {},
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'listar'
});
return await ctx.db.query('atas').collect();
}
});
@@ -13,6 +18,10 @@ export const list = query({
export const get = query({
args: { id: v.id('atas') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'ver'
});
return await ctx.db.get(args.id);
}
});
@@ -20,6 +29,10 @@ export const get = query({
export const getObjetos = query({
args: { id: v.id('atas') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'ver'
});
const links = await ctx.db
.query('atasObjetos')
.withIndex('by_ataId', (q) => q.eq('ataId', args.id))
@@ -35,6 +48,10 @@ export const listByObjetoIds = query({
objetoIds: v.array(v.id('objetos'))
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'listar'
});
if (args.objetoIds.length === 0) return [];
// Buscar todos os vínculos ata-objeto para os objetos informados
@@ -66,6 +83,11 @@ export const create = mutation({
objetosIds: v.array(v.id('objetos'))
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'criar'
});
const user = await getCurrentUserFunction(ctx);
if (!user) throw new Error('Unauthorized');
@@ -103,6 +125,11 @@ export const update = mutation({
objetosIds: v.array(v.id('objetos'))
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'editar'
});
const user = await getCurrentUserFunction(ctx);
if (!user) throw new Error('Unauthorized');
@@ -139,6 +166,11 @@ export const update = mutation({
export const remove = mutation({
args: { id: v.id('atas') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'excluir'
});
const user = await getCurrentUserFunction(ctx);
if (!user) throw new Error('Unauthorized');
@@ -170,6 +202,10 @@ export const remove = mutation({
export const generateUploadUrl = mutation({
args: {},
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'editar'
});
return await ctx.storage.generateUploadUrl();
}
});
@@ -183,6 +219,11 @@ export const saveDocumento = mutation({
tamanho: v.number()
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'editar'
});
const user = await getCurrentUserFunction(ctx);
if (!user) throw new Error('Unauthorized');
@@ -201,6 +242,11 @@ export const saveDocumento = mutation({
export const removeDocumento = mutation({
args: { id: v.id('atasDocumentos') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'editar'
});
const user = await getCurrentUserFunction(ctx);
if (!user) throw new Error('Unauthorized');
@@ -215,6 +261,11 @@ export const removeDocumento = mutation({
export const getDocumentos = query({
args: { ataId: v.id('atas') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atas',
acao: 'ver'
});
const docs = await ctx.db
.query('atasDocumentos')
.withIndex('by_ataId', (q) => q.eq('ataId', args.ataId))

View File

@@ -147,6 +147,11 @@ export async function verificarLicencaAtiva(
export const listarTodos = query({
args: {},
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'listar'
});
try {
const [atestados, licencas] = await Promise.all([
ctx.db.query('atestados').collect(),
@@ -258,6 +263,11 @@ export const listarTodos = query({
export const listarPorFuncionario = query({
args: { funcionarioId: v.id('funcionarios') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'listar'
});
const [atestados, licencas] = await Promise.all([
ctx.db
.query('atestados')
@@ -285,6 +295,11 @@ export const listarPorPeriodo = query({
dataFim: v.string()
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'listar'
});
const dataInicioObj = new Date(args.dataInicio);
const dataFimObj = new Date(args.dataFim);
@@ -327,6 +342,10 @@ export const verificarStatusLicenca = query({
},
returns: v.boolean(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'listar'
});
return await verificarLicencaAtiva(ctx, args.funcionarioId);
}
});
@@ -339,6 +358,11 @@ export const obterDadosGraficos = query({
periodo: v.optional(v.number()) // dias (padrão: 30)
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'dashboard'
});
try {
const dias = args.periodo || 30;
const dataLimite = Date.now() - dias * 24 * 60 * 60 * 1000;
@@ -588,6 +612,11 @@ export const obterDadosGraficos = query({
export const obterEstatisticas = query({
args: {},
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'dashboard'
});
const hoje = new Date();
hoje.setHours(0, 0, 0, 0);
const inicioMes = new Date(hoje.getFullYear(), hoje.getMonth(), 1);
@@ -657,6 +686,11 @@ export const obterEventosCalendario = query({
)
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'dashboard'
});
const eventos: Array<{
id: string;
title: string;
@@ -837,6 +871,11 @@ export const generateUploadUrl = mutation({
args: {},
returns: v.string(),
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'criar'
});
const usuario = await getUsuarioAutenticado(ctx);
if (!usuario) throw new Error('Não autenticado');
@@ -853,6 +892,11 @@ export const obterUrlDocumento = query({
},
returns: v.union(v.string(), v.null()),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'listar'
});
const usuario = await getUsuarioAutenticado(ctx);
if (!usuario) throw new Error('Não autenticado');
@@ -874,6 +918,11 @@ export const criarAtestadoMedico = mutation({
},
returns: v.id('atestados'),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'criar'
});
const usuario = await getUsuarioAutenticado(ctx);
if (!usuario) throw new Error('Não autenticado');
@@ -932,6 +981,11 @@ export const criarDeclaracaoComparecimento = mutation({
},
returns: v.id('atestados'),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'criar'
});
const usuario = await getUsuarioAutenticado(ctx);
if (!usuario) throw new Error('Não autenticado');
@@ -990,6 +1044,11 @@ export const criarLicencaMaternidade = mutation({
},
returns: v.id('licencas'),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'criar'
});
const usuario = await getUsuarioAutenticado(ctx);
if (!usuario) throw new Error('Não autenticado');
@@ -1054,6 +1113,11 @@ export const criarLicencaPaternidade = mutation({
},
returns: v.id('licencas'),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'criar'
});
const usuario = await getUsuarioAutenticado(ctx);
if (!usuario) throw new Error('Não autenticado');
@@ -1112,6 +1176,11 @@ export const prorrogarLicencaMaternidade = mutation({
},
returns: v.id('licencas'),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'editar'
});
const usuario = await getUsuarioAutenticado(ctx);
if (!usuario) throw new Error('Não autenticado');
@@ -1169,6 +1238,11 @@ export const excluirAtestado = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'excluir'
});
const usuario = await getUsuarioAutenticado(ctx);
if (!usuario) throw new Error('Não autenticado');
@@ -1215,6 +1289,11 @@ export const excluirLicenca = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'atestados_licencas',
acao: 'excluir'
});
const usuario = await getUsuarioAutenticado(ctx);
if (!usuario) throw new Error('Não autenticado');

View File

@@ -11,6 +11,11 @@ import { getCurrentUserFunction } from './auth';
export const listarTodas = query({
args: {},
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ausencias',
acao: 'listar'
});
const solicitacoes = await ctx.db.query('solicitacoesAusencias').collect();
const solicitacoesComDetalhes = await Promise.all(
@@ -65,6 +70,11 @@ export const listarMinhasSolicitacoes = query({
_refresh: v.optional(v.number()) // Parâmetro para forçar atualização no frontend
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ausencias',
acao: 'criar'
});
const solicitacoes = await ctx.db
.query('solicitacoesAusencias')
.withIndex('by_funcionario', (q) => q.eq('funcionarioId', args.funcionarioId))
@@ -104,6 +114,11 @@ export const listarMinhasSolicitacoes = query({
export const listarSolicitacoesSubordinados = query({
args: { gestorId: v.id('usuarios') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ausencias',
acao: 'aprovar'
});
// Buscar times onde o usuário é gestor
const timesGestor = await ctx.db
.query('times')
@@ -170,6 +185,11 @@ export const listarSolicitacoesSubordinados = query({
export const obterDetalhes = query({
args: { solicitacaoId: v.id('solicitacoesAusencias') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ausencias',
acao: 'listar'
});
const solicitacao = await ctx.db.get(args.solicitacaoId);
if (!solicitacao) return null;
@@ -237,6 +257,11 @@ export const obterDetalhes = query({
export const obterNotificacoesNaoLidas = query({
args: { usuarioId: v.id('usuarios') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ausencias',
acao: 'criar'
});
const notificacoes = await ctx.db
.query('notificacoesAusencias')
.withIndex('by_destinatario_and_lida', (q) =>
@@ -253,6 +278,11 @@ export const obterNotificacoesNaoLidas = query({
export const contarPendentesGestor = query({
args: { gestorId: v.id('usuarios') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ausencias',
acao: 'aprovar'
});
// Buscar times onde o usuário é gestor
const timesGestor = await ctx.db
.query('times')
@@ -359,6 +389,11 @@ export const criarSolicitacao = mutation({
},
returns: v.id('solicitacoesAusencias'),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ausencias',
acao: 'criar'
});
// Validações
if (args.motivo.trim().length < 10) {
throw new Error('O motivo deve ter no mínimo 10 caracteres');
@@ -547,6 +582,11 @@ export const aprovar = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ausencias',
acao: 'aprovar'
});
const solicitacao = await ctx.db.get(args.solicitacaoId);
if (!solicitacao) {
throw new Error('Solicitação não encontrada');
@@ -710,6 +750,11 @@ export const reprovar = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ausencias',
acao: 'reprovar'
});
const solicitacao = await ctx.db.get(args.solicitacaoId);
if (!solicitacao) {
throw new Error('Solicitação não encontrada');
@@ -866,6 +911,11 @@ export const marcarComoLida = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ausencias',
acao: 'criar'
});
await ctx.db.patch(args.notificacaoId, {
lida: true
});

View File

@@ -76,6 +76,11 @@ function agruparPorSolicitacao(registros: Array<Doc<'ferias'>>): Array<{
export const listarTodas = query({
args: {},
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'listar'
});
const todasFerias = await ctx.db.query('ferias').collect();
const periodosComDetalhes = await Promise.all(
@@ -146,6 +151,11 @@ export const listarMinhasSolicitacoes = query({
_refresh: v.optional(v.number()) // Parâmetro para forçar atualização no frontend
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'dashboard'
});
const todasFerias = await ctx.db
.query('ferias')
.withIndex('by_funcionario', (q) => q.eq('funcionarioId', args.funcionarioId))
@@ -180,6 +190,11 @@ export const listarMinhasSolicitacoes = query({
export const listarSolicitacoesSubordinados = query({
args: { gestorId: v.id('usuarios') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'dashboard'
});
// Buscar times onde o usuário é gestor
const timesGestor = await ctx.db
.query('times')
@@ -259,6 +274,11 @@ export const obterDetalhes = query({
feriasId: v.id('ferias')
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'ver'
});
const ferias = await ctx.db.get(args.feriasId);
if (!ferias) return null;
@@ -333,6 +353,11 @@ export const criarSolicitacao = mutation({
},
returns: v.array(v.id('ferias')),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'criar'
});
if (args.periodos.length === 0) {
throw new Error('É necessário adicionar pelo menos 1 período');
}
@@ -394,6 +419,11 @@ export const aprovar = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'aprovar'
});
// Buscar o registro específico
const registro = await ctx.db.get(args.feriasId);
@@ -503,6 +533,11 @@ export const reprovar = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'reprovar'
});
// Buscar o registro específico
const registro = await ctx.db.get(args.feriasId);
@@ -565,6 +600,11 @@ export const ajustarEAprovar = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'aprovar'
});
// Buscar o registro específico
const registroAntigo = await ctx.db.get(args.feriasId);
@@ -676,6 +716,11 @@ export const verificarStatusFerias = query({
args: { funcionarioId: v.id('funcionarios') },
returns: v.union(v.literal('ativo'), v.literal('em_ferias')),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'ver'
});
const hoje = new Date();
hoje.setHours(0, 0, 0, 0);
@@ -721,6 +766,11 @@ export const verificarStatusFerias = query({
export const obterNotificacoesNaoLidas = query({
args: { usuarioId: v.id('usuarios') },
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'dashboard'
});
return await ctx.db
.query('notificacoesFerias')
.withIndex('by_destinatario_and_lida', (q) =>
@@ -735,6 +785,10 @@ export const marcarComoLida = mutation({
args: { notificacaoId: v.id('notificacoesFerias') },
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'dashboard'
});
await ctx.db.patch(args.notificacaoId, { lida: true });
return null;
}
@@ -755,6 +809,11 @@ export const atualizarStatus = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'editar_status'
});
// Buscar o registro específico
const registro = await ctx.db.get(args.feriasId);
@@ -1184,6 +1243,11 @@ export const atualizarMeuStatus = mutation({
args: {},
returns: v.null(),
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ferias',
acao: 'atualizar_status'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario || !usuario.funcionarioId) {
throw new Error('Usuário não encontrado ou não possui funcionário associado');

View File

@@ -55,12 +55,48 @@ const PERMISSOES_BASE = {
acao: 'aprovar',
descricao: 'Aprovar férias de funcionários'
},
{
nome: 'ferias.reprovar',
recurso: 'ferias',
acao: 'reprovar',
descricao: 'Reprovar férias de funcionários'
},
{
nome: 'ferias.dashboard',
recurso: 'ferias',
acao: 'dashboard',
descricao: 'Acessar o painel de férias de funcionários'
},
{
nome: 'ferias.listar',
recurso: 'ferias',
acao: 'listar',
descricao: 'Listar solicitações e períodos de férias'
},
{
nome: 'ferias.criar',
recurso: 'ferias',
acao: 'criar',
descricao: 'Criar solicitações de férias'
},
{
nome: 'ferias.editar_status',
recurso: 'ferias',
acao: 'editar_status',
descricao: 'Editar/cancelar status de solicitações de férias'
},
{
nome: 'ferias.atualizar_status',
recurso: 'ferias',
acao: 'atualizar_status',
descricao: 'Atualizar status automático de férias (administração)'
},
{
nome: 'ferias.ver',
recurso: 'ferias',
acao: 'ver',
descricao: 'Visualizar detalhes de uma solicitação/período de férias'
},
// Atestados e Licenças
{
nome: 'atestados_licencas.listar',

View File

@@ -321,6 +321,11 @@ function validarAcelerometro(
export const generateUploadUrl = mutation({
args: {},
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'registrar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -543,6 +548,11 @@ export const registrarPonto = mutation({
justificativa: v.optional(v.string())
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'registrar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -921,6 +931,15 @@ export const listarRegistrosDia = query({
_refresh: v.optional(v.number()) // Parâmetro usado pelo frontend para forçar refresh
},
handler: async (ctx, args) => {
try {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'ver'
});
} catch {
return [];
}
const usuario = await getCurrentUserFunction(ctx);
if (!usuario || !usuario.funcionarioId) {
return [];
@@ -967,6 +986,11 @@ export const obterSaldoDiario = query({
data: v.string() // YYYY-MM-DD
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
// Buscar banco de horas do dia
const bancoHoras = await ctx.db
.query('bancoHoras')
@@ -1007,15 +1031,22 @@ export const listarRegistrosPeriodo = query({
dataFim: v.string() // YYYY-MM-DD
},
handler: async (ctx, args) => {
try {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'ver'
});
} catch {
return [];
}
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
console.warn('[listarRegistrosPeriodo] Usuário não autenticado');
return [];
}
// Verificar permissão (RH ou TI)
// Por enquanto, permitir se tiver funcionarioId ou for admin
// TODO: Implementar verificação de permissão adequada
// Permissão já verificada acima (ponto.ver)
// Validar formato das datas
if (!args.dataInicio || !args.dataFim) {
@@ -1185,6 +1216,22 @@ export const obterEstatisticas = query({
funcionarioId: v.optional(v.id('funcionarios'))
},
handler: async (ctx, args) => {
try {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'ver'
});
} catch {
return {
totalRegistros: 0,
dentroDoPrazo: 0,
foraDoPrazo: 0,
totalFuncionarios: 0,
funcionariosDentroPrazo: 0,
funcionariosForaPrazo: 0
};
}
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
// Retornar estatísticas zeradas quando não autenticado
@@ -1198,7 +1245,7 @@ export const obterEstatisticas = query({
};
}
// TODO: Verificar permissão (RH ou TI)
// Permissão já verificada acima (ponto.ver)
let registros = await ctx.db
.query('registrosPonto')
@@ -1245,6 +1292,11 @@ export const obterRegistro = query({
registroId: v.id('registrosPonto')
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -1255,11 +1307,7 @@ export const obterRegistro = query({
throw new Error('Registro não encontrado');
}
// Verificar se o usuário tem permissão (próprio registro ou RH/TI)
if (registro.funcionarioId !== usuario.funcionarioId) {
// TODO: Verificar se é RH ou TI
// Por enquanto, permitir
}
// Permissão já verificada acima (ponto.ver)
const funcionario = await ctx.db.get(registro.funcionarioId);
let simbolo = null;
@@ -1813,6 +1861,20 @@ export const obterHistoricoESaldoDia = query({
_refresh: v.optional(v.number()) // Parâmetro usado pelo frontend para forçar refresh
},
handler: async (ctx, args) => {
try {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'ver'
});
} catch {
return {
registros: [],
cargaHorariaDiaria: 0,
horasTrabalhadas: 0,
saldoMinutos: 0
};
}
const usuario = await getCurrentUserFunction(ctx);
if (!usuario || !usuario.funcionarioId) {
console.warn('[obterHistoricoESaldoDia] Usuário não autenticado ou sem funcionarioId');
@@ -1825,10 +1887,7 @@ export const obterHistoricoESaldoDia = query({
};
}
// Verificar se é o próprio funcionário ou tem permissão
if (usuario.funcionarioId !== args.funcionarioId) {
// TODO: Verificar permissão de RH
}
// Permissão já verificada acima (ponto.ver)
// Buscar registros do dia
const registros = await ctx.db
@@ -1890,15 +1949,17 @@ export const obterBancoHorasFuncionario = query({
funcionarioId: v.id('funcionarios')
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// Verificar se é o próprio funcionário ou tem permissão
if (usuario.funcionarioId !== args.funcionarioId) {
// TODO: Verificar permissão de RH
}
// Permissão já verificada acima (banco_horas.ver)
// Buscar todos os registros de banco de horas do funcionário
const bancosHoras = await ctx.db
@@ -2056,15 +2117,17 @@ export const obterBancoHorasMensal = query({
mes: v.string() // YYYY-MM
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// Verificar se é o próprio funcionário ou tem permissão
if (usuario.funcionarioId !== args.funcionarioId) {
// TODO: Verificar permissão de RH
}
// Permissão já verificada acima (banco_horas.ver)
const bancoMensal = await ctx.db
.query('bancoHorasMensal')
@@ -2119,15 +2182,17 @@ export const listarHistoricoMensal = query({
mesFim: v.optional(v.string()) // YYYY-MM
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// Verificar se é o próprio funcionário ou tem permissão
if (usuario.funcionarioId !== args.funcionarioId) {
// TODO: Verificar permissão de RH
}
// Permissão já verificada acima (banco_horas.ver)
let query = ctx.db
.query('bancoHorasMensal')
@@ -2242,15 +2307,17 @@ export const verificarAlertasBancoHoras = query({
funcionarioId: v.id('funcionarios')
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// Verificar se é o próprio funcionário ou tem permissão
if (usuario.funcionarioId !== args.funcionarioId) {
// TODO: Verificar permissão de RH
}
// Permissão já verificada acima (banco_horas.ver)
// Buscar banco de horas mensal mais recente
const hoje = new Date();
@@ -2356,6 +2423,11 @@ export const editarRegistroPonto = mutation({
observacoes: v.optional(v.string())
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'editar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -2441,6 +2513,11 @@ export const ajustarBancoHoras = mutation({
ajusteMinutos: v.number()
}),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ajustar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -2564,6 +2641,11 @@ export const listarHomologacoes = query({
funcionarioId: v.optional(v.id('funcionarios'))
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'editar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -2650,6 +2732,11 @@ export const excluirHomologacao = mutation({
homologacaoId: v.id('homologacoesPonto')
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'editar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -2694,6 +2781,11 @@ export const excluirHomologacao = mutation({
export const obterMotivosAtestados = query({
args: {},
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ajustar'
});
// Buscar tipos de atestados e declarações
const atestados = await ctx.db.query('atestados').collect();
const tiposUnicos = new Set<string>();
@@ -2733,6 +2825,11 @@ export const criarDispensaRegistro = mutation({
isento: v.boolean()
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'editar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -2780,6 +2877,11 @@ export const removerDispensaRegistro = mutation({
dispensaId: v.id('dispensasRegistro')
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'editar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -2814,6 +2916,11 @@ export const listarDispensas = query({
apenasAtivas: v.optional(v.boolean())
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'editar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -2917,12 +3024,17 @@ export const obterEstatisticasBancoHorasGerencial = query({
funcionarioId: v.optional(v.id('funcionarios'))
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// TODO: Verificar permissão de RH/TI
// Permissão já verificada acima (banco_horas.ver)
// Buscar todos os bancos de horas do mês
let bancosMensais = await ctx.db
@@ -2997,15 +3109,17 @@ export const listarHistoricoAlteracoesBancoHoras = query({
mes: v.optional(v.string()) // YYYY-MM - se fornecido, filtra por mês
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// Verificar se é o próprio funcionário ou tem permissão
if (usuario.funcionarioId !== args.funcionarioId) {
// TODO: Verificar permissão de RH
}
// Permissão já verificada acima (banco_horas.ver)
// Buscar homologações do funcionário
let homologacoes = await ctx.db
@@ -3089,6 +3203,11 @@ export const verificarDispensaAtiva = query({
minuto: v.optional(v.number())
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'ponto',
acao: 'ver'
});
const dispensas = await ctx.db
.query('dispensasRegistro')
.withIndex('by_funcionario', (q) => q.eq('funcionarioId', args.funcionarioId))
@@ -3217,15 +3336,17 @@ export const obterBancoHorasCompleto = query({
)
}),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// Verificar se é o próprio funcionário ou tem permissão
if (usuario.funcionarioId !== args.funcionarioId) {
// TODO: Verificar permissão de RH
}
// Permissão já verificada acima (banco_horas.ver)
const bancoHoras = await ctx.db
.query('bancoHoras')
@@ -3314,15 +3435,17 @@ export const listarAjustesBancoHoras = query({
})
),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// Verificar se é o próprio funcionário ou tem permissão
if (usuario.funcionarioId !== args.funcionarioId) {
// TODO: Verificar permissão de RH
}
// Permissão já verificada acima (banco_horas.ver)
let query = ctx.db
.query('ajustesBancoHoras')
@@ -3402,6 +3525,11 @@ export const listarInconsistenciasBancoHoras = query({
})
),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -3492,12 +3620,17 @@ export const obterConfiguracaoBancoHoras = query({
v.null()
),
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'configurar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// TODO: Verificar permissão de TI
// Permissão já verificada acima (banco_horas.configurar)
const config = await ctx.db.query('configuracaoBancoHoras').order('desc').first();
@@ -3540,12 +3673,17 @@ export const obterAlertasConfigurados = query({
})
),
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'configurar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// TODO: Verificar permissão de TI
// Permissão já verificada acima (banco_horas.configurar)
// Retornar todos os alertas (ativos e inativos) para permitir edição
const alertas = await ctx.db.query('alertasBancoHoras').collect();
@@ -3591,15 +3729,17 @@ export const verificarInconsistencias = query({
})
),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ver'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// Verificar se é o próprio funcionário ou tem permissão
if (usuario.funcionarioId !== args.funcionarioId) {
// TODO: Verificar permissão de RH
}
// Permissão já verificada acima (banco_horas.ver)
let query = ctx.db
.query('inconsistenciasBancoHoras')
@@ -3650,6 +3790,11 @@ export const criarAjusteBancoHoras = mutation({
success: v.boolean()
}),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ajustar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -3745,6 +3890,11 @@ export const resolverInconsistencia = mutation({
success: v.boolean()
}),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'ajustar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -3794,12 +3944,17 @@ export const atualizarConfiguracaoBancoHoras = mutation({
configId: v.id('configuracaoBancoHoras')
}),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'configurar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// TODO: Verificar permissão de TI
// Permissão já verificada acima (banco_horas.configurar)
// Buscar configuração existente ou criar nova
const configExistente = await ctx.db.query('configuracaoBancoHoras').order('desc').first();
@@ -3854,12 +4009,17 @@ export const criarAlertaBancoHoras = mutation({
alertaId: v.id('alertasBancoHoras')
}),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'configurar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// TODO: Verificar permissão de TI
// Permissão já verificada acima (banco_horas.configurar)
// Verificar se já existe alerta do mesmo tipo
const alertaExistente = await ctx.db
@@ -3907,12 +4067,17 @@ export const atualizarConfiguracaoAlerta = mutation({
success: v.boolean()
}),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'configurar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
}
// TODO: Verificar permissão de TI
// Permissão já verificada acima (banco_horas.configurar)
const alerta = await ctx.db.get(args.alertaId);
if (!alerta) {
@@ -3952,6 +4117,11 @@ export const recalcularBancoHoras = mutation({
diasRecalculados: v.number()
}),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'configurar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');
@@ -4329,6 +4499,11 @@ export const inicializarAlertasPadrao = mutation({
alertasCriados: v.number()
}),
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'banco_horas',
acao: 'configurar'
});
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
throw new Error('Usuário não autenticado');

View File

@@ -1,5 +1,6 @@
import { v } from 'convex/values';
import { mutation, query } from './_generated/server';
import { internal } from './_generated/api';
import { simboloTipo } from './tables/funcionarios';
export const getAll = query({
@@ -17,6 +18,10 @@ export const getAll = query({
})
),
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'simbolos',
acao: 'listar'
});
return await ctx.db.query('simbolos').collect();
}
});
@@ -39,6 +44,10 @@ export const getById = query({
v.null()
),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'simbolos',
acao: 'ver'
});
return await ctx.db.get(args.id);
}
});
@@ -53,6 +62,11 @@ export const create = mutation({
valor: v.optional(v.string())
},
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'simbolos',
acao: 'criar'
});
let refValor = args.refValor;
let vencValor = args.vencValor;
let valor = args.valor ?? '';
@@ -90,6 +104,10 @@ export const remove = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'simbolos',
acao: 'excluir'
});
await ctx.db.delete(args.id);
return null;
}
@@ -107,6 +125,11 @@ export const update = mutation({
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'simbolos',
acao: 'editar'
});
let refValor = args.refValor;
let vencValor = args.vencValor;
let valor = args.valor ?? '';
@@ -149,6 +172,11 @@ export const removerDuplicados = mutation({
mantidos: v.number()
}),
handler: async (ctx) => {
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
recurso: 'simbolos',
acao: 'excluir'
});
const todosSimbolos = await ctx.db.query('simbolos').collect();
// Agrupar símbolos por nome