feat: add user authentication and validation checks in query handlers

- Implemented user authentication checks in the `getAll` and `listarRegistrosPeriodo` query handlers, returning empty arrays for unauthenticated users.
- Enhanced date validation in `listarRegistrosPeriodo` to ensure correct date formats before processing.
- Updated the `obterEstatisticas` query to return zeroed statistics for unauthenticated users, improving data security and user experience.
This commit is contained in:
2025-11-22 22:33:44 -03:00
parent aeaa3c903f
commit 5b41d35b6f
2 changed files with 50 additions and 13 deletions

View File

@@ -47,11 +47,24 @@ const regimeTrabalhoValidator = v.optional(
export const getAll = query({ export const getAll = query({
args: {}, args: {},
handler: async (ctx) => { handler: async (ctx) => {
// Verificar autenticação primeiro
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
// Retornar array vazio quando não autenticado
return [];
}
// Autorização: listar funcionários // Autorização: listar funcionários
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, { try {
recurso: 'funcionarios', await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
acao: 'listar' recurso: 'funcionarios',
}); acao: 'listar'
});
} catch (error) {
// Se não tiver permissão, retornar array vazio
return [];
}
const funcionarios = await ctx.db.query('funcionarios').collect(); const funcionarios = await ctx.db.query('funcionarios').collect();
// Retornar apenas os campos necessários para listagem // Retornar apenas os campos necessários para listagem
return funcionarios.map((f) => ({ return funcionarios.map((f) => ({

View File

@@ -862,15 +862,24 @@ export const listarRegistrosPeriodo = query({
handler: async (ctx, args) => { handler: async (ctx, args) => {
const usuario = await getCurrentUserFunction(ctx); const usuario = await getCurrentUserFunction(ctx);
if (!usuario) { if (!usuario) {
throw new Error('Usuário não autenticado'); // Retornar array vazio quando não autenticado
return [];
} }
// Verificar permissão (RH ou TI) // Verificar permissão (RH ou TI)
// Por enquanto, permitir se tiver funcionarioId ou for admin // Por enquanto, permitir se tiver funcionarioId ou for admin
// TODO: Implementar verificação de permissão adequada // TODO: Implementar verificação de permissão adequada
const dataFim = new Date(args.dataFim); // Validar formato das datas
dataFim.setHours(23, 59, 59, 999); if (!args.dataInicio || !args.dataFim) {
return [];
}
// Validar formato YYYY-MM-DD
const dataInicioRegex = /^\d{4}-\d{2}-\d{2}$/;
if (!dataInicioRegex.test(args.dataInicio) || !dataInicioRegex.test(args.dataFim)) {
return [];
}
let registrosFiltrados; let registrosFiltrados;
@@ -885,19 +894,26 @@ export const listarRegistrosPeriodo = query({
.withIndex('by_funcionario_data', (q) => q.eq('funcionarioId', funcionarioId)) .withIndex('by_funcionario_data', (q) => q.eq('funcionarioId', funcionarioId))
.collect(); .collect();
// Filtrar por período de data // Filtrar por período de data usando comparação de strings (formato YYYY-MM-DD)
registrosFiltrados = todosRegistrosFuncionario.filter((r) => { registrosFiltrados = todosRegistrosFuncionario.filter((r) => {
const dataRegistro = new Date(r.data); // Comparação de strings funciona para formato YYYY-MM-DD
return dataRegistro >= new Date(args.dataInicio) && dataRegistro <= dataFim; return r.data >= args.dataInicio && r.data <= args.dataFim;
}); });
} else { } else {
// Se não há funcionário especificado, buscar todos e filtrar (menos eficiente, mas necessário) // Se não há funcionário especificado, buscar todos e filtrar (menos eficiente, mas necessário)
// Usar comparação de strings diretamente para datas no formato YYYY-MM-DD
const registros = await ctx.db const registros = await ctx.db
.query('registrosPonto') .query('registrosPonto')
.withIndex('by_data', (q) => q.gte('data', args.dataInicio).lte('data', args.dataFim)) .withIndex('by_data', (q) =>
q.gte('data', args.dataInicio).lte('data', args.dataFim)
)
.collect(); .collect();
registrosFiltrados = registros; // Garantir que as datas estão no formato correto e filtrar novamente para garantir
registrosFiltrados = registros.filter((r) => {
// Comparação de strings funciona para formato YYYY-MM-DD
return r.data >= args.dataInicio && r.data <= args.dataFim;
});
} }
// Buscar informações dos funcionários // Buscar informações dos funcionários
@@ -964,7 +980,15 @@ export const obterEstatisticas = query({
handler: async (ctx, args) => { handler: async (ctx, args) => {
const usuario = await getCurrentUserFunction(ctx); const usuario = await getCurrentUserFunction(ctx);
if (!usuario) { if (!usuario) {
throw new Error('Usuário não autenticado'); // Retornar estatísticas zeradas quando não autenticado
return {
totalRegistros: 0,
dentroDoPrazo: 0,
foraDoPrazo: 0,
totalFuncionarios: 0,
funcionariosDentroPrazo: 0,
funcionariosForaPrazo: 0,
};
} }
// TODO: Verificar permissão (RH ou TI) // TODO: Verificar permissão (RH ou TI)