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">
import { useConvexClient } from "convex-svelte";
import { useQuery } from "convex-svelte";
import { api } from "@sgse-app/backend/convex/_generated/api";
import { onMount } from "svelte";
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
let heartbeatInterval: ReturnType<typeof setInterval> | null = null;
@@ -13,6 +18,8 @@
// Detectar atividade do usuário
function handleActivity() {
if (!usuarioAutenticado) return;
lastActivity = Date.now();
// Limpar timeout de inatividade anterior
@@ -22,16 +29,29 @@
// Configurar novo timeout (5 minutos)
inactivityTimeout = setTimeout(() => {
client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" });
if (usuarioAutenticado) {
client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" });
}
}, 5 * 60 * 1000);
}
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" });
// Heartbeat a cada 30 segundos
// Heartbeat a cada 30 segundos (apenas se autenticado)
heartbeatInterval = setInterval(() => {
if (!usuarioAutenticado) {
if (heartbeatInterval) {
clearInterval(heartbeatInterval);
heartbeatInterval = null;
}
return;
}
const timeSinceLastActivity = Date.now() - lastActivity;
// Se houve atividade nos últimos 5 minutos, manter online
@@ -47,10 +67,14 @@
});
// Configurar timeout inicial de inatividade
handleActivity();
if (usuarioAutenticado) {
handleActivity();
}
// Detectar quando a aba fica inativa/ativa
function handleVisibilityChange() {
if (!usuarioAutenticado) return;
if (document.hidden) {
// Aba ficou inativa
client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" });
@@ -65,8 +89,10 @@
// Cleanup
return () => {
// Marcar como offline ao desmontar
client.mutation(api.chat.atualizarStatusPresenca, { status: "offline" });
// Marcar como offline ao desmontar (apenas se autenticado)
if (usuarioAutenticado) {
client.mutation(api.chat.atualizarStatusPresenca, { status: "offline" });
}
if (heartbeatInterval) {
clearInterval(heartbeatInterval);
@@ -86,4 +112,3 @@
</script>
<!-- Componente invisível - apenas lógica -->

View File

@@ -125,11 +125,23 @@
const funcionarioIdDisponivel = $derived(currentUser?.data?.funcionarioId ?? 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
const funcionarioQuery = useQuery(api.funcionarios.getCurrent, {});
const timesSubordinadosQuery = useQuery(api.times.listarSubordinadosDoGestorAtual, {});
const chamadosQuery = useQuery(api.chamados.listarChamadosUsuario, {});
const funcionarioQuery = useQuery(
api.funcionarios.getCurrent,
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
// Usamos uma chave estável baseada no ID para evitar recriação desnecessária