Programação Por Equipe DevBras

Capa do artigo: Template de admin grátis em produção: o que apagar e proteger antes de publicar

Template de admin grátis em produção: o que apagar e proteger antes de publicar

O template traz telas bonitas, rotas abertas, usuário de exemplo e bibliotecas antigas. Veja como transformar a casca num painel de verdade: inventário, bloqueio por padrão e teste sem login.

O painel da transportadora ficou pronto em três dias. Menu lateral, gráficos, tabela com busca, tela de login elegante. Na reunião, o cliente digitou /pages/tables/data.html por curiosidade, sem estar logado, e a página abriu. Depois testou /admin/usuarios numa aba anônima e viu a lista com e-mails de verdade. O template estava ótimo. O sistema não existia.

A resposta curta: use o template como camada visual e nada mais. Apague todas as páginas e rotas de demonstração, faça o servidor negar acesso por padrão e liberar só o que foi explicitamente autorizado, troque os dados de exemplo por dados reais e teste cada URL sem sessão antes de publicar. A tela de login que vem no kit geralmente é só HTML que leva ao painel; ela não confere nada.

Por que o template parece mais pronto do que é

Um template de admin é feito para vender a si mesmo numa demo. Ele precisa abrir todas as telas sem servidor, sem banco e sem cadastro. Por isso o botão "Entrar" é um link para index.html, os gráficos leem números fixos de um arquivo JavaScript e as tabelas vêm preenchidas com nomes fictícios.

Quando a equipe copia a pasta inteira para o projeto e serve tudo como arquivo estático, essas dezenas de páginas viram URLs públicas. Algumas mostram só lorem ipsum. Outras foram adaptadas às pressas para buscar dado real via API, e a API foi escrita assumindo que "só quem passou pelo login chega aqui". Ninguém passou pelo login: o navegador pediu a URL e o servidor entregou.

Há ainda o que vem junto e ninguém olha: versões antigas de jQuery, plugins de tabela e de gráfico copiados para vendor/, sem gerenciador de pacotes que avise sobre falha de segurança. E acessibilidade não é garantida: menus que só abrem no mouse são comuns.

Como transformar o template num painel de verdade

  1. Faça o inventário. Liste cada página do kit e marque: vai usar, vai adaptar ou vai apagar. O que não for usado sai do repositório, não só do menu.
  2. Separe os arquivos visuais. CSS, fontes, ícones e scripts ficam numa pasta de assets pública. Páginas HTML do kit não são servidas diretamente; elas viram templates renderizados pelo servidor ou componentes do seu front.
  3. Negue por padrão. Todo o prefixo do painel passa por um middleware que exige sessão. A exceção é a tela de login e os assets.
  4. Autorize por papel na API. Esconder o item do menu não protege a rota. Cada endpoint confere se aquele usuário pode fazer aquela ação.
  5. Troque os dados de exemplo. Gráficos e cartões de resumo leem números reais ou somem. Número de mentira em painel de produção vira decisão errada.
  6. Atualize ou substitua as bibliotecas. Passe as dependências para o package.json e rode npm audit. Plugin abandonado sai.
  7. Teste sem login e com o usuário errado. Antes de cada deploy, não depois da reunião com o cliente.

Negar por padrão no Express

No painel da transportadora, o backend é Node.js com Express. O erro original era um express.static apontando para a pasta inteira do template. A correção serve só os assets em público e coloca o resto atrás da sessão:

const path = require('path');
const express = require('express');
const session = require('express-session');

const app = express();
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: { httpOnly: true, secure: true, sameSite: 'lax' },
}));

// só CSS, JS, fontes e imagens do tema são públicos
app.use('/assets', express.static('tema/assets'));

app.get('/login', (req, res) =>
  res.sendFile(path.join(__dirname, 'views', 'login.html')));
app.post('/login', express.urlencoded({ extended: false }), require('./rotas/login'));

function exigirLogin(req, res, next) {
  if (!req.session.userId) return res.redirect('/login');
  next();
}

function exigirPapel(papel) {
  return (req, res, next) =>
    req.session.papel === papel ? next() : res.status(403).send('Sem permissão');
}

// tudo o que vem depois daqui exige sessão
app.use(exigirLogin);

app.get('/', require('./rotas/painel'));
app.get('/admin/usuarios', exigirPapel('admin'), require('./rotas/usuarios'));
app.get('/api/entregas', require('./rotas/entregas'));

app.use((req, res) => res.status(404).send('Não encontrado'));

app.listen(3000);

A ordem importa. O app.use(exigirLogin) fica antes de qualquer rota do painel, então uma rota nova esquecida nasce protegida. As únicas exceções estão acima dele, à vista de quem revisa o código. Com Apache ou Nginx servindo o tema, a lógica é a mesma: a raiz pública é a pasta de assets, não a pasta do kit. Se uma página aparecer com erro 403 depois disso, o guia de erro 403 no Apache ajuda a separar permissão de configuração.

Caçar o que sobrou da demonstração

Antes de publicar, procure resquícios do kit nas views e nos scripts:

grep -rniE "lorem|john doe|admin@|password|demo" views/ public/ tema/

Cada resultado é uma tela que ninguém revisou, um usuário de exemplo ou um texto de placeholder que vai aparecer para o cliente. Apague também o README e as páginas de documentação do tema que tenham ido parar dentro da pasta servida.

Testar cada URL sem sessão

for rota in / /admin/usuarios /api/entregas /pages/tables/data.html /index2.html; do
  printf '%s ' "$rota"
  curl -s -o /dev/null -w '%{http_code}\n' "https://painel.exemplo.com.br$rota"
done

A saída esperada é algo como / 302, /admin/usuarios 302, /api/entregas 302 e 404 para as páginas do kit. Qualquer 200 sem sessão numa rota do painel é um vazamento. Repita o teste com o cookie de um usuário comum e confirme que /admin/usuarios responde 403.

Visual que todo mundo consegue usar

Abra o painel e navegue só com Tab, Enter e Esc. O menu lateral abre? O foco aparece? Os submenus fecham? Muitos temas usam div com evento de clique no lugar de botão, e quem usa teclado ou leitor de tela fica preso. Se o tema tiver um modo escuro, confira o contraste do texto cinza nos dois modos.

Erros comuns

  • Servir a pasta inteira do template. Páginas de demonstração viram URLs públicas, e algumas acabam ligadas a dados reais.
  • Confiar na tela de login do kit. Ela costuma ser um link estilizado; sem verificação no servidor, qualquer URL interna abre.
  • Proteger só o menu. Quem digita a URL ou chama a API direto ignora o item escondido.
  • Deixar o usuário e a senha de exemplo. Credenciais de demo são públicas, estão na documentação do tema.
  • Manter gráficos com dados fictícios. O cliente decide com base em número inventado e perde a confiança no sistema quando descobre.
  • Ignorar as bibliotecas da pasta vendor. Versões antigas com falhas conhecidas ficam no ar sem ninguém saber.

Checklist

  • As páginas não usadas do template foram apagadas do repositório.
  • Só a pasta de assets é servida como estático.
  • O middleware de sessão vem antes de todas as rotas do painel.
  • Cada endpoint de API confere papel ou permissão, não só sessão.
  • Nenhum usuário, senha ou e-mail de exemplo sobrou no banco ou no código.
  • Gráficos e totais leem dados reais.
  • Dependências do tema passaram por npm audit ou foram substituídas.
  • O teste com curl sem sessão não retorna 200 em nenhuma rota interna.

Para a parte de quem pode ver o quê, quando o tema é pago e vem com telas de perfis e permissões, veja tema admin pago não traz a regra. E agora abra uma aba anônima e digite três URLs internas do seu painel: alguma delas abre dado sem pedir login?

Avalie este artigo

Referência: https://colorlib.com/wp/free-bootstrap-admin-dashboard-templates/