feat: implement user authentication checks in PresenceManager and perfil pages

- Added authentication verification in the PresenceManager component to manage user presence status based on authentication state.
- Updated the perfil page to conditionally execute queries only if the user is authenticated, enhancing security and performance.
- Introduced derived variables to track user authentication status, ensuring that presence management and data fetching are only performed for logged-in users.
This commit is contained in:
2025-11-22 22:25:40 -03:00
parent 031552c836
commit aeaa3c903f
2 changed files with 48 additions and 11 deletions

View File

@@ -1,10 +1,15 @@
<script lang="ts"> <script lang="ts">
import { useConvexClient } from "convex-svelte"; import { useConvexClient } from "convex-svelte";
import { useQuery } from "convex-svelte";
import { api } from "@sgse-app/backend/convex/_generated/api"; import { api } from "@sgse-app/backend/convex/_generated/api";
import { onMount } from "svelte"; import { onMount } from "svelte";
const client = useConvexClient(); const client = useConvexClient();
// Verificar se o usuário está autenticado antes de gerenciar presença
const currentUser = useQuery(api.auth.getCurrentUser, {});
const usuarioAutenticado = $derived(currentUser?.data !== null && currentUser?.data !== undefined);
// Token é passado automaticamente via interceptadores em +layout.svelte // Token é passado automaticamente via interceptadores em +layout.svelte
let heartbeatInterval: ReturnType<typeof setInterval> | null = null; let heartbeatInterval: ReturnType<typeof setInterval> | null = null;
@@ -13,6 +18,8 @@
// Detectar atividade do usuário // Detectar atividade do usuário
function handleActivity() { function handleActivity() {
if (!usuarioAutenticado) return;
lastActivity = Date.now(); lastActivity = Date.now();
// Limpar timeout de inatividade anterior // Limpar timeout de inatividade anterior
@@ -22,16 +29,29 @@
// Configurar novo timeout (5 minutos) // Configurar novo timeout (5 minutos)
inactivityTimeout = setTimeout(() => { inactivityTimeout = setTimeout(() => {
if (usuarioAutenticado) {
client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" }); client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" });
}
}, 5 * 60 * 1000); }, 5 * 60 * 1000);
} }
onMount(() => { onMount(() => {
// Configurar como online ao montar // Só configurar presença se usuário estiver autenticado
if (!usuarioAutenticado) return;
// Configurar como online ao montar (apenas se autenticado)
client.mutation(api.chat.atualizarStatusPresenca, { status: "online" }); client.mutation(api.chat.atualizarStatusPresenca, { status: "online" });
// Heartbeat a cada 30 segundos // Heartbeat a cada 30 segundos (apenas se autenticado)
heartbeatInterval = setInterval(() => { heartbeatInterval = setInterval(() => {
if (!usuarioAutenticado) {
if (heartbeatInterval) {
clearInterval(heartbeatInterval);
heartbeatInterval = null;
}
return;
}
const timeSinceLastActivity = Date.now() - lastActivity; const timeSinceLastActivity = Date.now() - lastActivity;
// Se houve atividade nos últimos 5 minutos, manter online // Se houve atividade nos últimos 5 minutos, manter online
@@ -47,10 +67,14 @@
}); });
// Configurar timeout inicial de inatividade // Configurar timeout inicial de inatividade
if (usuarioAutenticado) {
handleActivity(); handleActivity();
}
// Detectar quando a aba fica inativa/ativa // Detectar quando a aba fica inativa/ativa
function handleVisibilityChange() { function handleVisibilityChange() {
if (!usuarioAutenticado) return;
if (document.hidden) { if (document.hidden) {
// Aba ficou inativa // Aba ficou inativa
client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" }); client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" });
@@ -65,8 +89,10 @@
// Cleanup // Cleanup
return () => { return () => {
// Marcar como offline ao desmontar // Marcar como offline ao desmontar (apenas se autenticado)
if (usuarioAutenticado) {
client.mutation(api.chat.atualizarStatusPresenca, { status: "offline" }); client.mutation(api.chat.atualizarStatusPresenca, { status: "offline" });
}
if (heartbeatInterval) { if (heartbeatInterval) {
clearInterval(heartbeatInterval); clearInterval(heartbeatInterval);
@@ -86,4 +112,3 @@
</script> </script>
<!-- Componente invisível - apenas lógica --> <!-- Componente invisível - apenas lógica -->

View File

@@ -125,11 +125,23 @@
const funcionarioIdDisponivel = $derived(currentUser?.data?.funcionarioId ?? null); const funcionarioIdDisponivel = $derived(currentUser?.data?.funcionarioId ?? null);
const gestorIdDisponivel = $derived(currentUser?.data?._id ?? null); const gestorIdDisponivel = $derived(currentUser?.data?._id ?? null);
// ✅ CORRIGIDO: Queries no nível superior (sem argumentos) sempre criadas // Verificar autenticação antes de executar queries
const usuarioAutenticado = $derived(currentUser?.data !== null && currentUser?.data !== undefined);
// ✅ CORRIGIDO: Queries condicionais - só executar se usuário estiver autenticado
// Queries que não requerem argumentos são criadas uma vez // Queries que não requerem argumentos são criadas uma vez
const funcionarioQuery = useQuery(api.funcionarios.getCurrent, {}); const funcionarioQuery = useQuery(
const timesSubordinadosQuery = useQuery(api.times.listarSubordinadosDoGestorAtual, {}); api.funcionarios.getCurrent,
const chamadosQuery = useQuery(api.chamados.listarChamadosUsuario, {}); usuarioAutenticado ? {} : 'skip'
);
const timesSubordinadosQuery = useQuery(
api.times.listarSubordinadosDoGestorAtual,
usuarioAutenticado ? {} : 'skip'
);
const chamadosQuery = useQuery(
api.chamados.listarChamadosUsuario,
usuarioAutenticado ? {} : 'skip'
);
// ✅ CORRIGIDO: Queries com argumentos obrigatórios usando $derived.by para estabilidade // ✅ CORRIGIDO: Queries com argumentos obrigatórios usando $derived.by para estabilidade
// Usamos uma chave estável baseada no ID para evitar recriação desnecessária // Usamos uma chave estável baseada no ID para evitar recriação desnecessária