test(tradein/auth): сторож не должен зеленеть от съехавшей области (#2715)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 8s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 3m6s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 8s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 3m6s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
Ревью: `rglob` по несуществующему каталогу не падает — отдаёт пусто, нарушителей ноль, тест зелёный навсегда. Достаточно переложить файл в подкаталог tests/ (их восемь, и прецедент такого сторожа лежит именно в подкаталоге), чтобы `parents[1]` уехал и сторож замолчал. Ровно тот класс, от которого детектор уже защищён (test_detector_actually_detects), а область — нет. Одна строка: `_OWNER.exists()` в теле теста; проверено мутацией области — краснеет. Плюс слепые зоны названы и закреплены исполняемо: строковый доступ `getattr(mod, "verify_password")` и прямой `bcrypt.checkpw` в обход модуля сторож НЕ ловит. От намеренного обхода он не защищает и не может — только от нечаянного. Было требованием ревью назвать это в коде, а не подразумевать. Refs #2715
This commit is contained in:
parent
1dc3a08563
commit
3a7dbd4dda
1 changed files with 27 additions and 0 deletions
|
|
@ -20,6 +20,13 @@
|
|||
которую `grep 'verify_password('` не поймал бы вовсе — то есть ровно ту, ради
|
||||
которой сторож и написан.
|
||||
|
||||
ЧЕГО СТОРОЖ НЕ ВИДИТ, и это записано тут, а не подразумевается: строкового
|
||||
доступа (`getattr(mod, "verify_password")`) и обхода модуля целиком (прямой
|
||||
`bcrypt.checkpw`). От НАМЕРЕННОГО обхода он не защищает и не может — только от
|
||||
нечаянного, а нечаянный и есть частый случай. Обе непойманные формы закреплены
|
||||
исполняемо (`test_detector_blind_spots_are_known`), чтобы «не ловим» было
|
||||
проверенным фактом, а не обещанием в тексте.
|
||||
|
||||
Без БД и без сети — только чтение файлов.
|
||||
"""
|
||||
|
||||
|
|
@ -68,8 +75,28 @@ def test_detector_actually_detects() -> None:
|
|||
assert not _references_verify_password("# verify_password тут только в комментарии")
|
||||
|
||||
|
||||
def test_detector_blind_spots_are_known() -> None:
|
||||
"""Слепые зоны — зафиксированы, а не забыты.
|
||||
|
||||
Обе формы обходят сторож НАМЕРЕННЫМ усилием: строковый доступ к атрибуту и
|
||||
обход модуля целиком. Ловить их AST'ом можно было бы только ценой ложняков
|
||||
(любой `getattr` с любой строкой, любой вызов bcrypt), а цена ложняка —
|
||||
требование выключить сторож. Тест держит это знание исполняемым: захочет
|
||||
однажды детектор их ловить — покраснеет здесь и заставит осознанно
|
||||
переписать и этот тест, и текст модуля.
|
||||
"""
|
||||
assert not _references_verify_password('fn = getattr(password_mod, "verify_password")')
|
||||
assert not _references_verify_password("bcrypt.checkpw(plain.encode(), hashed.encode())")
|
||||
|
||||
|
||||
def test_sync_verify_password_is_called_from_one_place_only() -> None:
|
||||
"""В `app/` синхронную сверку не поминает никто, кроме её собственного модуля."""
|
||||
# Область сканирования жива. `rglob` по несуществующему каталогу не падает —
|
||||
# отдаёт пусто, нарушителей ноль, сторож зелен НАВСЕГДА. Достаточно
|
||||
# переложить этот файл в подкаталог tests/ (их уже восемь, и прецедент
|
||||
# такого сторожа лежит именно в подкаталоге), чтобы `parents[1]` уехал.
|
||||
assert _OWNER.exists(), f"область сканирования съехала: {_APP_DIR}"
|
||||
|
||||
offenders = [
|
||||
str(path.relative_to(_BACKEND_ROOT))
|
||||
for path in sorted(_APP_DIR.rglob("*.py"))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue