Atualização de Read.me e \correção da autorização no primeiro login
This commit is contained in:
153
README.md
153
README.md
@@ -3360,3 +3360,156 @@ config/routes.rb # POST atualizar_logo
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary><strong>🩺 28/08/2026 — "A primeira vez que entra dá tela de erro" + os assets 404 que o Cloudflare escondia</strong></summary>
|
||||
|
||||
Dois problemas achados a partir de **um** relato ("a primeira vez que entra dá a
|
||||
tela de erro, em `/auth/login`"). O primeiro era o relatado; o segundo apareceu
|
||||
com o navegador aberto na mesma tela e era o mais grave dos dois.
|
||||
|
||||
| Sintoma na tela | Causa real | Onde se resolveu |
|
||||
|---|---|---|
|
||||
| Primeira entrada do dia parece falha do sistema | `devise.failure.unauthenticated` sai como `flash[:alert]` — vermelho, e **duas vezes** | `Users::SessionsController#new` |
|
||||
| Carrossel e editor de romaneio mortos no teste | `RAILS_ENV=production` + **nada no deploy pré-compilava assets** | `bin/docker-boot` (passo 5) |
|
||||
|
||||
## 1. O "erro" que era só o Devise pedindo login
|
||||
|
||||
Quem abre `teste.reemtransportes.com.br` deslogado — ou seja, **toda** primeira
|
||||
entrada — passa por `authenticate_user!`, que redireciona para `/auth/login`
|
||||
gravando `flash[:alert] = "Para continuar, faça login."`. Como `alert`, a
|
||||
mensagem saía **em vermelho e em dois lugares ao mesmo tempo**: o toast com
|
||||
triângulo de alerta no canto superior direito (`layouts/application.html.erb`) e
|
||||
a caixa vermelha acima do formulário (`devise/sessions/new.html.erb`).
|
||||
|
||||
Entrar no sistema pelo caminho normal ficava com a cara de sistema quebrado. E
|
||||
como na segunda visita a pessoa já está em `/auth/login` sem flash nenhum, a tela
|
||||
aparecia limpa — daí o "só na primeira vez", que fazia parecer bug intermitente.
|
||||
|
||||
A mensagem agora é **descartada**: a tela já é o formulário de login, o aviso não
|
||||
acrescenta nada.
|
||||
|
||||
```ruby
|
||||
# app/controllers/users/sessions_controller.rb
|
||||
flash.delete(:alert) if flash[:alert] == I18n.t('devise.failure.unauthenticated', default: nil)
|
||||
```
|
||||
|
||||
⚠️ **O filtro é pela mensagem exata, e não `flash.delete(:alert)` seco.** Senha
|
||||
errada, conta desativada e `timeout` ("Sua sessão expirou") chegam ao mesmo
|
||||
`#new` pelo mesmo caminho — essas **precisam** continuar vermelhas. Apagar o
|
||||
alerta inteiro no `new` deixaria a pessoa digitando a senha errada para sempre
|
||||
sem entender por quê.
|
||||
|
||||
## 2. Os assets 404 — e por que ninguém tinha visto
|
||||
|
||||
O console da tela de login acusava dois módulos:
|
||||
|
||||
```
|
||||
Failed to fetch dynamically imported module:
|
||||
/assets/controllers/carrossel_controller-913b47f7.js -> 404
|
||||
/assets/controllers/romaneio_controller-0105d794.js -> 404
|
||||
```
|
||||
|
||||
Não é pouco: `carrossel_controller` é a **paginação por tamanho de tela** (a
|
||||
regra 3 do `CLAUDE.md`) e `romaneio_controller` é o editor de romaneio inteiro.
|
||||
Os dois estavam mortos no ambiente de teste.
|
||||
|
||||
### O disfarce
|
||||
|
||||
À primeira vista pareciam só dois arquivos com problema — os outros dez
|
||||
controllers respondiam 200. **Não respondiam.** Os 200 vinham do **cache do
|
||||
Cloudflare**:
|
||||
|
||||
```
|
||||
$ curl -sI .../validacao_controller-ca4de84f.js
|
||||
cache-control: public, max-age=31536000, immutable
|
||||
age: 275844 # ~3,2 dias em cache
|
||||
cf-cache-status: HIT # ← nunca chegou no servidor
|
||||
```
|
||||
|
||||
Os assets saem com `max-age` de **um ano**. Os dez que "funcionavam" eram cópias
|
||||
guardadas na borda dias antes; os dois quebrados eram os dois arquivos alterados
|
||||
**depois** dessa fotografia. Batendo direto na origem (com querystring, para
|
||||
furar o cache), **todos** davam 404.
|
||||
|
||||
> **Lição de diagnóstico:** ao investigar asset em produção, olhe
|
||||
> `cf-cache-status` antes de concluir qualquer coisa. `HIT` não é prova de que o
|
||||
> servidor está servindo — é prova de que ele serviu **algum dia**.
|
||||
|
||||
### A causa
|
||||
|
||||
O corpo do 404 era `public/404.html`, ou seja, a requisição chegou no **roteador
|
||||
do Rails**: o servidor de assets do Propshaft nem estava montado. E a resposta do
|
||||
HTML não trazia o cabeçalho `Server-Timing`, que só existe em development
|
||||
(`config.server_timing`). Somando os dois: **o servidor roda
|
||||
`RAILS_ENV=production`**.
|
||||
|
||||
Em production o Propshaft **não compila sob demanda** — ele resolve o caminho
|
||||
pelo `public/assets/.manifest.json` e o arquivo digerido tem que existir em
|
||||
disco. E nada no deploy gerava isso:
|
||||
|
||||
- a linha `RUN bundle exec rails assets:precompile` do `Dockerfile` estava
|
||||
**comentada** (e não adiantaria descomentar: o compose monta `.:/app` por cima
|
||||
e apagaria o `public/assets` da imagem);
|
||||
- `bin/docker-boot` não tocava no assunto;
|
||||
- `/public/assets` é **gitignorado**.
|
||||
|
||||
Resultado: o que existia no servidor era o resto de algum `precompile` manual
|
||||
antigo. Todo JS alterado depois dele virava 404 silencioso — silencioso porque a
|
||||
tela **continua abrindo** (o Tailwind vem de CDN e os ícones são `public/`
|
||||
direto), só sem comportamento.
|
||||
|
||||
### A correção
|
||||
|
||||
Novo **passo 5** no `bin/docker-boot`, que roda em todo start de container — logo,
|
||||
em todo deploy:
|
||||
|
||||
```bash
|
||||
if [ "${RAILS_ENV:-development}" = "production" ]; then
|
||||
rm -rf public/assets tmp/cache/assets
|
||||
bundle exec rails assets:precompile
|
||||
else
|
||||
rm -rf public/assets # em dev o Propshaft calcula o digest ao vivo
|
||||
fi
|
||||
```
|
||||
|
||||
- **Limpa antes de pré-compilar**: sem isso um manifesto antigo convive com
|
||||
arquivos novos e a divergência volta na primeira alteração de JS. Assim
|
||||
manifesto e arquivos saem sempre da **mesma execução**. (`rm -rf` em vez de
|
||||
`rails assets:clobber`: faz o mesmo sem pagar outro boot do Rails.)
|
||||
- **Falha não derruba o boot**: `exit 1` aqui viraria loop de reinício com o
|
||||
`restart: unless-stopped` e deixaria todo mundo de fora. O erro é gritado no
|
||||
log — o que não podia continuar é a falha **muda**.
|
||||
- **Em development apaga `public/assets`**: sobra de precompile faz o Propshaft
|
||||
voltar a resolver pelo manifesto, e aí alteração de JS só aparece depois de
|
||||
recompilar — parece cache do navegador quando não é.
|
||||
|
||||
### Como conferir depois do deploy
|
||||
|
||||
```bash
|
||||
# 1. os assets do HTML respondem na ORIGEM (querystring fura o cache do CDN)
|
||||
curl -s https://teste.reemtransportes.com.br/auth/login \
|
||||
| grep -o '/assets/controllers/[a-z_]*-[a-f0-9]*\.js' | sort -u \
|
||||
| while read a; do
|
||||
printf "%s -> " "$a"
|
||||
curl -s -o /dev/null -w "%{http_code}\n" "https://teste.reemtransportes.com.br$a?cb=$RANDOM"
|
||||
done
|
||||
|
||||
# 2. o passo apareceu no log do boot
|
||||
docker compose logs app | grep '\[boot\] assets'
|
||||
```
|
||||
|
||||
Todos têm que responder **200**. Se algum der 404, o `precompile` não rodou ou
|
||||
falhou — o log do passo 5 diz qual dos dois.
|
||||
|
||||
## 📂 Arquivos
|
||||
|
||||
```
|
||||
app/controllers/users/sessions_controller.rb # descarta o "faça login" vermelho
|
||||
bin/docker-boot # passo 5: clobber + precompile
|
||||
Dockerfile # tira a linha de precompile morta e explica por quê
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Reference in New Issue
Block a user