FEAT: configurar sessão, rotas de autenticação e processamento de CSV
- Adiciona/ativa express-session antes das rotas para permitir uso de req.session - Registra rotas de autenticação (/login, /auth/callback) e middleware de proteção - Serve assets estáticos em /public - Implementa upload/processing CSV (ViaCEP -> Google geocoding, consulta Geogrid, cache de coordenadas) - Adiciona endpoints de status/download e tratamento de retries/backoff para chamadas externas - Melhora logs e handling de erros
This commit is contained in:
parent
46d66f9c1b
commit
67a0a83a99
15
app.js
15
app.js
@ -8,11 +8,13 @@ const csv = require("csv-parser");
|
|||||||
const fastCsv = require("fast-csv");
|
const fastCsv = require("fast-csv");
|
||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const cors = require("cors");
|
const cors = require("cors");
|
||||||
|
const session = require("express-session"); // adiciona session
|
||||||
const { geocodeWithGoogle } = require("./service/geocodeService");
|
const { geocodeWithGoogle } = require("./service/geocodeService");
|
||||||
const { fetchJson } = require("./service/fetchService");
|
const { fetchJson } = require("./service/fetchService");
|
||||||
const { BASE_BACKOFF_MS, MAX_RETRIES, REQUEST_DELAY_MS, sleep } = require("./service/retryService");
|
const { BASE_BACKOFF_MS, MAX_RETRIES, REQUEST_DELAY_MS, sleep } = require("./service/retryService");
|
||||||
const { API_URL, HEADERS } = require("./config/apiConfig");
|
const { API_URL, HEADERS } = require("./config/apiConfig");
|
||||||
const { normalizePartnerSigla } = require("./service/normalizeService");
|
const { normalizePartnerSigla } = require("./service/normalizeService");
|
||||||
|
const authRoutes = require("./routes/authRoutes.js");
|
||||||
|
|
||||||
function createApp() {
|
function createApp() {
|
||||||
const upload = multer({ dest: "uploads/" });
|
const upload = multer({ dest: "uploads/" });
|
||||||
@ -21,6 +23,19 @@ function createApp() {
|
|||||||
app.use(express.static(path.join(__dirname, "public")));
|
app.use(express.static(path.join(__dirname, "public")));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
|
// session deve ser configurada antes de usar req.session nas rotas/middleware
|
||||||
|
app.use(
|
||||||
|
session({
|
||||||
|
secret: process.env.SESSION_SECRET || "change-me",
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: false,
|
||||||
|
cookie: {
|
||||||
|
// ajuste conforme produção (secure: true se rodando em HTTPS)
|
||||||
|
maxAge: 24 * 60 * 60 * 1000,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
async function getMinDistance(lat, lon) {
|
async function getMinDistance(lat, lon) {
|
||||||
// tenta várias vezes com backoff exponencial; trata 429 usando Retry-After se disponível
|
// tenta várias vezes com backoff exponencial; trata 429 usando Retry-After se disponível
|
||||||
let attempt = 0;
|
let attempt = 0;
|
||||||
|
|||||||
@ -1,35 +1,32 @@
|
|||||||
import express from "express";
|
const express = require("express");
|
||||||
import {getAuthUrl, getTokenFomCode} from "../service/authService.js";
|
const { getAuthUrl, getTokenFromCode } = require("../service/authService");
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
// Rota para iniciar o fluxo de autenticação
|
// Rota para iniciar o fluxo de autenticação
|
||||||
|
|
||||||
router.get("/login", (req, res) => {
|
router.get("/login", (req, res) => {
|
||||||
const authUrl = getAuthUrl();
|
const authUrl = getAuthUrl();
|
||||||
return res.redirect(authUrl);
|
return res.redirect(authUrl);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Rota de callback após autenticação
|
// Rota de callback após autenticação
|
||||||
|
|
||||||
router.get("/auth/callback", async (req, res) => {
|
router.get("/auth/callback", async (req, res) => {
|
||||||
const code = req.query.code;
|
const code = req.query.code;
|
||||||
|
|
||||||
if (!code) {
|
if (!code) {
|
||||||
return res.status(400).send("Código de autenticação não fornecido.");
|
return res.status(400).send("Código de autenticação não fornecido.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const tokens = await getTokenFomCode(code);
|
const tokens = await getTokenFromCode(code);
|
||||||
// Armazena os tokens na sessão do usuário
|
// Armazena os tokens na sessão do usuário
|
||||||
req.session.tokens = tokens;
|
if (!req.session) req.session = {};
|
||||||
return res.redirect("/public/index.html");
|
req.session.tokens = tokens;
|
||||||
} catch (error) {
|
return res.redirect("/public/index.html");
|
||||||
console.error("Erro ao obter tokens:", error);
|
} catch (error) {
|
||||||
return res.status(500).send("Erro ao processar a autenticação.");
|
console.error("Erro ao obter tokens:", error);
|
||||||
}
|
return res.status(500).send("Erro ao processar a autenticação.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
})
|
module.exports = router;
|
||||||
|
|
||||||
export default router;
|
|
||||||
@ -1,6 +1,5 @@
|
|||||||
import axios from "axios";
|
const axios = require("axios");
|
||||||
import dotenv from "dotenv";
|
require("dotenv").config();
|
||||||
dotenv.config();
|
|
||||||
|
|
||||||
const tenantId = process.env.OAUTH_TENANT_ID;
|
const tenantId = process.env.OAUTH_TENANT_ID;
|
||||||
const clientId = process.env.OAUTH_CLIENT_ID;
|
const clientId = process.env.OAUTH_CLIENT_ID;
|
||||||
@ -8,7 +7,7 @@ const clientSecret = process.env.OAUTH_CLIENT_SECRET;
|
|||||||
const redirectUri = process.env.OAUTH_REDIRECT_URI;
|
const redirectUri = process.env.OAUTH_REDIRECT_URI;
|
||||||
|
|
||||||
// Função que gera o link de login para o usuário
|
// Função que gera o link de login para o usuário
|
||||||
export function getAuthUrl() {
|
function getAuthUrl() {
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
client_id: clientId,
|
client_id: clientId,
|
||||||
response_type: "code",
|
response_type: "code",
|
||||||
@ -22,7 +21,7 @@ export function getAuthUrl() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Troca o "authorization code" por tokens
|
// Troca o "authorization code" por tokens
|
||||||
export async function getTokenFromCode(authCode) {
|
async function getTokenFromCode(authCode) {
|
||||||
const url = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
|
const url = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
@ -34,6 +33,10 @@ export async function getTokenFromCode(authCode) {
|
|||||||
client_secret: clientSecret,
|
client_secret: clientSecret,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await axios.post(url, params);
|
const response = await axios.post(url, params.toString(), {
|
||||||
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||||
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { getAuthUrl, getTokenFromCode };
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user