Repository navigation
Fix/login bloqueio proposital - #32
Merged
Merged
Conversation
- 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
sousa7tz
approved these changes
Oct 6, 2026
sousa7tz
left a comment
Collaborator
There was a problem hiding this comment.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.