Skip to content

feat(permission-profiles): enforce per-screen authorization and check the account on every request - #49

Merged
MendesMat merged 5 commits into
mainfrom
feat/screen-access-and-account-check
Oct 13, 2026
Merged

MendesMat merged 5 commits into
mainfrom
feat/screen-access-and-account-check

Conversation

@MendesMat

@MendesMat MendesMat commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Closes #9

What

Puts the authorization barrier on the server: a group filter checks on every authenticated request that the account exists and is active, and RequireScreenAccess(screen, level) makes each endpoint declare the minimum level its operation needs (with an optional alternative screen for PERM-04). Both read the database on each request, with no cache.

Why

PERM-03, PERM-12, PERM-13 (the server decides, and a profile change counts from the next request), AUTH-18 (a deactivated account is refused even with a valid token), AUTH-27, API-11 (every endpoint declares screen and level), and the new rules AUTH-30 (order of refusals) and PERM-26 (the 403 message). Decision 24.

Tests

  • T01 — Deve responder sessão encerrada quando o usuário do token não existe mais
  • T02 — Deve recusar a próxima requisição de uma conta desativada, mesmo com token válido
  • T03 — Deve recusar a conta desativada também em me, sair e trocar a senha
  • T04 — Deve responder conta desativada antes de troca de senha obrigatória
  • T05 — Deve recusar quem não tem perfil numa rota que exige Leitor
  • T06 — Deve permitir Leitor numa rota que exige Leitor
  • T07 — Deve recusar Leitor numa rota que exige Editor
  • T08 — Deve permitir Editor numa rota que exige Editor
  • T09 — Deve recusar Editor numa rota que exige Gerenciador
  • T10 — Deve permitir Gerenciador numa rota que exige Gerenciador
  • T11 — Deve permitir Gerenciador numa rota que exige Leitor
  • T12 — Deve recusar quem tem nível só em outra tela
  • T13 — Deve responder troca de senha obrigatória antes de nível insuficiente
  • T14 — Deve permitir a rota da exceção com Leitor só em Usuários
  • T15 — Deve permitir a rota da exceção com Leitor só em Permissões
  • T16 — Deve recusar a rota da exceção sem nível em nenhuma das duas telas
  • T17 — Deve aplicar um nível rebaixado no perfil já na requisição seguinte, com o mesmo token
  • T18 — Deve aplicar um perfil recém-atribuído já na requisição seguinte, com o mesmo token
  • T19 — Deve exigir que toda rota de /api/v1 declare tela e nível, seja anônima ou esteja na lista de "só logado"
  • T20 — Deve responder sessão encerrada ao conferir a tela de um usuário que não existe mais (added during execution: a branch of CheckScreenAccessHandler written with the others)
  • T21 — Deve recusar como conta desativada uma conta ainda pendente (added in the review: the Pending branch of CheckAccountHandler had no test; Red shown by changing != Active to == Inactive)

T01, T02, T04, T05 and T14 had a Red (a compile error for a type that did not exist, or a wrong response). T03, T06–T13, T15–T18 and T20 passed at their first run, because an earlier cycle had already built the rule; the final report lists them as "sem Red", and mutations of the code (comparison operator, always allow, filter removed, alternative screen ignored) made the expected ones fail. T19 is a guard test and was born green; its Red was shown by removing me from the list.

How to test

From backend/ControlService, with Docker Desktop running:

powershell.exe -NoProfile -File check.ps1

Result: 0 warnings, 267 tests, 0 failures. No new endpoint is delivered, so the behavior is checked through the real pipeline by the integration tests, under /api/v1/test-only/ routes.

Checklist

  • Developed test-first: every behavior has a test that failed before the code existed (exceptions listed above)
  • check.ps1 passes locally: build without warnings and all tests
  • Nothing beyond the issue: no package, abstraction, migration or contract change it does not authorize
  • Documentation updated (docs/, README) when behavior or decisions changed
  • User-facing messages are verbatim from the feature document (CNV-16)

The group filter reads the user from the database on each request and
answers 401 account_inactive or session_expired (AUTH-18, AUTH-27). It runs
before the password-change filter, so a deactivated account is refused as
inactive first (AUTH-30).
RequireScreenAccess declares the screen and the minimum level of an
endpoint; its filter reads the effective level from the database on each
request and answers 403 forbidden below it (PERM-03, PERM-12, API-11).
…ry route

RequireScreenAccess takes a second screen for the exception of PERM-04.
A guard test fails the build when a /api/v1 route declares no screen and
level and is neither anonymous nor on the signed-in-only list (API-11).
A pending account counts as not active, as in RefreshSessionHandler
(AUTH-18, decision 21). Updates the test count of decision 26.
@MendesMat
MendesMat merged commit 29d121e into main Oct 13, 2026
5 checks passed
@MendesMat
MendesMat deleted the feat/screen-access-and-account-check branch October 13, 2026 23:04
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.

Enforce per-screen authorization and check the account on every request

1 participant