fix: desativar/rebaixar funcionario nao revogava sessao ativa (ate 12h)

Perfil e status ativo vinham so do cookie assinado (session.py), entao um
funcionario desativado (ATIVO=0) ou rebaixado (ADMIN->PADRAO) continuava
com acesso total ate o cookie expirar (ate 12h) - inclusive a
/funcionarios se era admin.

exigir_login (app/auth.py) agora reconfirma contra o banco a cada
requisicao quando o login nao e o da conta de bootstrap (ADMIN_USER do
.env, que nao tem linha em FUNCIONARIO_PAINEL e continua sempre admin via
variavel de ambiente): busca db_funcionarios.obter_por_login(login); se
nao existir mais ou ATIVO != 1, levanta NaoAutenticado (forca novo
login); caso contrario, monta o UsuarioLogado com o PERFIL atual do
banco, nao o do cookie - rebaixamento tambem passa a ter efeito imediato.

Testes de regressao em tests/test_auth.py:
- test_exigir_login_autentica_funcionario_ativo
- test_exigir_login_revoga_sessao_ao_desativar_funcionario
- test_exigir_admin_usa_perfil_atual_do_banco_nao_do_cookie
- test_exigir_login_conta_bootstrap_nao_consulta_banco

Ajustou tambem test_exigir_admin_rejeita_padrao (usava um login fake sem
linha em FUNCIONARIO_PAINEL, que agora conflita com a checagem nova -
passou a usar a fixture funcionario_teste). Suite inteira roda
147 passed apos a mudanca.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Gustavo
2026-08-13 21:18:58 -03:00
co-authored by Claude Sonnet 5
parent ba8ffaede7
commit e5f5d4211c
2 changed files with 61 additions and 3 deletions
+20 -1
View File
@@ -65,11 +65,30 @@ def autenticar_credenciais(usuario: str, senha: str) -> UsuarioLogado | None:
def exigir_login(request: Request) -> UsuarioLogado:
"""
Decodifica o cookie de sessão e, para logins que existem em
FUNCIONARIO_PAINEL, reconfirma ATIVO/PERFIL contra o banco a cada
requisição — o cookie assinado tem validade de até 12h e não é
revogado, então sem essa checagem desativar ou rebaixar um funcionário
não teria efeito imediato (continuaria com acesso até o cookie
expirar). A conta de bootstrap (ADMIN_USER do .env) não tem linha em
FUNCIONARIO_PAINEL e continua sempre admin via variável de ambiente,
sem consulta ao banco.
"""
token = request.cookies.get(session.SESSION_COOKIE_NAME)
dados = session.ler_token(token)
if dados is None:
raise NaoAutenticado(caminho_original=request.url.path)
return UsuarioLogado(login=dados["login"], nome=dados["nome"], perfil=dados["perfil"])
usuario_admin = os.environ.get("ADMIN_USER", "")
if usuario_admin and dados["login"] == usuario_admin:
return UsuarioLogado(login=dados["login"], nome=dados["nome"], perfil="ADMIN")
funcionario = db_funcionarios.obter_por_login(dados["login"])
if funcionario is None or not funcionario["ATIVO"]:
raise NaoAutenticado(caminho_original=request.url.path)
return UsuarioLogado(login=funcionario["LOGIN"], nome=funcionario["NOME"], perfil=funcionario["PERFIL"])
def exigir_admin(usuario: UsuarioLogado = Depends(exigir_login)) -> UsuarioLogado: