Skip to content

Fix/login bloqueio proposital - #32

Merged
sousa7tz merged 9 commits into
mainfrom
fix/login-bloqueio-proposital
Oct 6, 2026
Merged

sousa7tz merged 9 commits into
mainfrom
fix/login-bloqueio-proposital

Conversation

@andynnnfw

Copy link
Copy Markdown
Contributor

No description provided.

- src/Controllers/ErrorController.php: novo backLink() decide o destino do botao de voltar (lojista logado vai ao painel, visitante vai a home publica) e handle() entrega backUrl e backLabel as views
- views/errors/400.php, 401.php, 403.php, 429.php, 502.php, 503.php: link fixo Voltar ao Painel trocado por backUrl e backLabel
- views/errors/404.php: mesmo link calculado e texto sem citar o dashboard
- views/errors/default.php: mesmo link calculado e texto volte para o inicio
- views/errors/500.php: mesmo link calculado e codigo do erro impresso com e()
- tests/Feature/ErrorPagesTest.php: novo, cobre 404 de visitante e de lojista, depois do logout, 429 da consulta publica, 403 e a ausencia de link fixo nas views
- CLAUDE.md: secao Erros explica as variaveis do botao de voltar

Task 39 do backlog.
- src/Support/helpers.php: nova funcao format_document (11 digitos vira CPF, 14 vira CNPJ, outro tamanho sai so com os digitos)
- tests/Unit/HelpersTest.php: novo, cobre CPF, CNPJ, valor ja formatado, tamanho desconhecido e nulo
- src/Support/SessionGuard.php: passwordSignature gera a assinatura guardada na sessao e passwordChanged diz se a sessao foi aberta com uma senha que nao e mais a da conta
- tests/Unit/SessionGuardTest.php: sessao com senha antiga deixa de valer e sessao sem assinatura nao e derrubada
- src/Controllers/MerchantController.php: renderProfile, handleProfile e handlePasswordChange (exige a senha atual, limite de 5 erros em 15 min); login grava password_sig e authGuard derruba sessao aberta com senha antiga; tamanho minimo da senha vira constante
- src/Models/MerchantModel.php: findProfile, updateProfile e updatePasswordHash; findById traz o password_hash
- views/merchant/profile.php: nova tela com os formularios de dados da loja e de troca de senha
- views/partials/merchant-header.php: item Perfil no menu
- views/partials/flash.php: mensagens perfil_atualizado, senha_alterada, senha_atual_incorreta e muitas_tentativas
- public/index.php: rota merchant/profile
- public/css/components.css: estilo de campo desabilitado
- tests/Feature/ProfileTest.php: novo, 12 testes do fluxo de perfil e senha

Task 20 do backlog.
- CLAUDE.md: secao da sessao explica o password_sig, nova secao Perfil e format_document na lista de helpers
- README.md: feature Perfil, rota merchant/profile e roadmap atualizado
- docs/db/schema-explanation.md: bucket password_change em rate_limit_hits
…_close

- tests/Support/HttpTestCase.php: novo fromIp() faz as requisicoes chegarem como outro cliente (X-Forwarded-For, com o servidor de teste confiando no 127.0.0.1 via TRUSTED_PROXIES); curl_close trocado por unset, porque virou aviso de obsoleto no PHP 8.5
- src/Support/ClientIp.php: novo rateLimitKey (ipv4 e o proprio endereco, ipv6 e a rede /64, ipv4 escrito como ipv6 volta a ser ipv4)
- src/Support/RateLimiter.php: novo clientKey() para usar nos buckets; comentario dos buckets atualizado
- src/Controllers/CustomerController.php: consulta publica de saldo usa clientKey no limite por ip
- tests/Unit/ClientIpTest.php: tres testes da chave do limite
- src/Controllers/MerchantController.php: handleLogin conta os erros no bucket login_pair (e-mail + ip, 5 em 15 min) e no login_ip (20 em 15 min somando as contas); o bucket login_email deixa de existir, entao errar a senha de uma loja nao tranca mais a dona; login certo zera so o par
- tests/Feature/LoginLockoutTest.php: novo, 9 testes (estranho bloqueado e dona entrando, ataque de varios ips, senha certa apos o bloqueio, outra conta no mesmo ip, acerto zera a contagem, maiusculas no e-mail, limite por ip, rede ipv6 e chave gravada como hash)

Task 38 do backlog.
- CLAUDE.md: secao Limite de tentativas com a regra nova, clientKey e o motivo de nunca bloquear so pelo e-mail
- README.md: features e seguranca descrevem o bloqueio por e-mail + ip
- docs/db/schema-explanation.md: buckets login_pair e login_ip e o conteudo de key_hash
- docs/operacao.md: TRUSTED_PROXIES obrigatorio atras de proxy por causa do login
@andynnnfw andynnnfw self-assigned this Oct 6, 2026

@sousa7tz sousa7tz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revisado. Trocar o bloqueio só por e-mail por e-mail + IP (5) e só por IP (20) fecha o bloqueio proposital da dona da conta. A chave /64 para IPv6, com o caso ::ffff: tratado, está certa, e o fromIp() com TRUSTED_PROXIES=127.0.0.1 nos testes de fluxo ficou limpo.

Observação para o backlog, não bloqueia: sem teto por conta, um ataque distribuído ganha 5 tentativas por IP em cada conta. Um teto alto por conta (com captcha ou aviso por e-mail) fecharia isso sem voltar a trancar a dona.

Aprovado.

@sousa7tz
sousa7tz merged commit d4885f3 into main Oct 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants