// server.js (Node/Express - exemplo) import express from "express"; import helmet from "helmet"; import rateLimit from "express-rate-limit"; import session from "express-session"; import bcrypt from "bcrypt"; import nodemailer from "nodemailer"; import path from "path"; import fs from "fs"; const app = express(); app.use(helmet()); app.use(express.urlencoded({ extended: false })); app.use(express.json()); // Rate limiting para proteger brute-force app.use(rateLimit({ windowMs: 15*60*1000, max: 100 })); // Sessões (em produção use store como Redis) app.use(session({ secret: process.env.SESSION_SECRET || "troque_isto_por_variavel_ambiente", resave: false, saveUninitialized: false, cookie: { httpOnly: true, secure: true, sameSite: "lax" } })); // -- Senha mestre (hash) armazenada no servidor (ou DB) const PASSWORD_HASH = process.env.PASSWORD_HASH || bcrypt.hashSync("senha-de-exemplo", 10); // formulário de login app.get("/login", (req,res)=>{ res.sendFile(path.join(__dirname,"/public/login.html")); }); // processa senha app.post("/login", async (req,res)=>{ const { password, email } = req.body; if (!password) return res.status(400).send("Missing"); const ok = await bcrypt.compare(password, PASSWORD_HASH); if (!ok) return res.status(401).send("Senha incorreta"); // marca sessão como autenticada req.session.authenticated = true; // opcional: salvar e-mail no DB / enviar para proprietário if (email && /\S+@\S+\.\S+/.test(email)) { // aqui: adicionar à lista (arquivo, DB ou API de mailing list) fs.appendFileSync("./subscritos.txt", `${new Date().toISOString()} ${email}\n`); // enviar notificação por e-mail (exemplo nodemailer) // configure SMTP via env vars const transporter = nodemailer.createTransport({ /* SMTP config */ }); transporter.sendMail({ from: 'site@example.com', to: process.env.OWNER_EMAIL, subject: 'Novo acesso: ' + email, text: `Usuário ${email} entrou em ${new Date().toISOString()}` }).catch(console.error); } res.redirect("/loja"); }); // rota protegida: serve o site só se autenticado function ensureAuth(req,res,next){ if (req.session && req.session.authenticated) return next(); res.redirect("/login"); } app.get("/loja", ensureAuth, (req,res)=>{ res.sendFile(path.join(__dirname,"/protected/index.html")); }); // servir capas protegidas por rota que verifica sessão app.get("/capas/:file", ensureAuth, (req,res)=>{ const filePath = path.join(__dirname, "protected_assets", req.params.file); if (!fs.existsSync(filePath)) return res.status(404).send("Not found"); // stream do ficheiro — impede listagem pública res.sendFile(filePath); }); app.listen(3000, ()=>console.log("rodando 3000"));