From 986e37bf519a7940d7be6338188a0d5c6e221ec9 Mon Sep 17 00:00:00 2001 From: "gabriel.pereira" Date: Mon, 20 Oct 2025 10:04:41 -0300 Subject: [PATCH] =?UTF-8?q?FEAT:=20Implementar=20prote=C3=A7=C3=A3o=20de?= =?UTF-8?q?=20rotas=20e=20redirecionamento=20para=20login,=20al=C3=A9m=20d?= =?UTF-8?q?e=20melhorias=20na=20gest=C3=A3o=20de=20sess=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 34 ++++++++++++++++++++++++++++++++-- routes/authRoutes.js | 5 +++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 1cf810a..a7ff105 100644 --- a/app.js +++ b/app.js @@ -24,9 +24,9 @@ function createApp() { app.set("trust proxy", 1); app.use(cors()); - app.use(express.static(path.join(__dirname, "public"))); app.use(express.json()); + // session TEM que vir antes das rotas que usam req.session app.use( session({ secret: process.env.SESSION_SECRET || "change-me", @@ -34,12 +34,42 @@ function createApp() { saveUninitialized: false, cookie: { maxAge: 24 * 60 * 60 * 1000, - secure: process.env.NODE_ENV === "production", // true em produção HTTPS + secure: process.env.NODE_ENV === "production", sameSite: "lax", }, }) ); + // redirect raiz para /login + app.get("/", (req, res) => { + return res.redirect("/login"); + }); + + // middleware que protege rotas que exigem login + function requireAuth(req, res, next) { + if (req.session && req.session.user) return next(); + // se for chamada XHR, responda 401 em vez de redirect (útil para API) + if (req.xhr || req.headers.accept?.includes("application/json")) { + return res.status(401).json({ error: "not_authenticated" }); + } + return res.redirect("/login"); + } + + // monta rotas de autenticação públicas + app.use("/", authRoutes); + + // servir /public APENAS quando autenticado + app.use("/public", requireAuth, express.static(path.join(__dirname, "public"))); + + // proteger demais rotas (ex.: /upload, /consulta) + app.use((req, res, next) => { + // permissão liberada para rotas de auth já tratadas; proteger o resto + if (req.path.startsWith("/auth") || req.path === "/login") return next(); + return requireAuth(req, res, next); + }); + + ///////////////////////////////////////////////////// + async function getMinDistance(lat, lon) { // tenta várias vezes com backoff exponencial; trata 429 usando Retry-After se disponível let attempt = 0; diff --git a/routes/authRoutes.js b/routes/authRoutes.js index bd89c76..e56ff5b 100644 --- a/routes/authRoutes.js +++ b/routes/authRoutes.js @@ -21,11 +21,12 @@ router.get("/auth/callback", async (req, res) => { try { const tokens = await getTokenFromCode(code); - // garante que exista req.session e sempre grava tokens + // assegura sessão e marca usuário como autenticado if (!req.session) req.session = {}; req.session.tokens = tokens; + req.session.user = { authenticated: true }; // flag simples; adicione info real se quiser - // salva a sessão antes de redirecionar para evitar perda em stores assíncronas + // salva session antes do redirect req.session.save((err) => { if (err) { console.error("[auth callback] erro ao salvar sessão:", err);