Files
site/apps/api/tests/modules/admin/test_service.py
T
влад 12c983c0fc Шхуна не тонет: security, infra и доки на русском.
Безопасность довёл до ума — Cursor-генерацию переписал руками.
IDOR закрыл, CSRF задушил, refresh rotation теперь как надо.
HSTS на staging, ENABLE_DOCS=false, install.env recovery протестил.

Backend:
- jwt_denylist + auth_epoch: мгновенный revoke access JWT (logout/block/reset)
- auth/admin/users: bump epoch, logout с Bearer, forgot_password skip для blocked
- install_secrets: путь всегда apps/api/data/secrets/ (bootstrap из корня не ломает Docker)
- seed: SEED_DEMO_USERS=false на prod/staging
- тесты: jwt revoke, integration, coverage gate 90%

Frontend:
- logout шлёт Bearer, обработка TOKEN_REVOKED
- guards TypeScript fix
- E2E: blocked user → 401 сразу после block

Infra:
- staging/prod compose, TLS nginx, deploy-скрипты
- k6 §17.2, backup/health/smoke scripts

Docs:
- docs/ на русском: project, security, deploy, release (старые md слили)
- README короткий + план ТЗ + стандартные логины dev

Код готов к плаванию. Капитан может идти писать фронт.
2026-07-15 00:06:13 +03:00

89 lines
2.9 KiB
Python

from unittest.mock import patch
from app.modules.admin.service import (
create_admin_user,
delete_admin_user,
get_server_log_tail,
patch_user,
reset_user_password,
)
from app.modules.users import repository
from app.modules.users.repository import create_user, get_user_by_email
from app.core.security import hash_password
def test_admin_cannot_self_demote():
admin = get_user_by_email("admin@compton.example")
try:
patch_user(admin, admin.id, "user", None)
assert False, "Expected self-demotion error"
except ValueError as exc:
assert str(exc) == "SELF_DEMOTION_FORBIDDEN"
def test_admin_can_promote_user():
admin = get_user_by_email("admin@compton.example")
regular = create_user("sample@example.com", hash_password("Valid123"), role="user", status="active")
result = patch_user(admin, regular.id, "admin", None)
assert result["role"] == "admin"
def test_last_admin_protected():
admin = get_user_by_email("admin@compton.example")
target = create_user("target@example.com", hash_password("Valid123"), role="admin", status="active")
with patch.object(repository, "count_admins", return_value=1):
try:
patch_user(admin, target.id, "user", None)
assert False, "Expected last-admin protection"
except ValueError as exc:
assert str(exc) == "LAST_ADMIN_PROTECTED"
def test_admin_cannot_self_block():
admin = get_user_by_email("admin@compton.example")
try:
patch_user(admin, admin.id, None, "blocked")
assert False, "Expected self-block error"
except ValueError as exc:
assert str(exc) == "SELF_BLOCK_FORBIDDEN"
def test_reset_user_password_revokes_sessions():
admin = get_user_by_email("admin@compton.example")
target = create_user("reset-pw@example.com", hash_password("Valid123"), status="active")
result = reset_user_password(admin, target.id, "NewValid123")
assert result["status"] == "ok"
def test_delete_admin_user_forbidden_for_self():
admin = get_user_by_email("admin@compton.example")
try:
delete_admin_user(admin, admin.id)
assert False, "Expected self-delete error"
except ValueError as exc:
assert str(exc) == "SELF_DELETE_FORBIDDEN"
def test_create_admin_user_rejects_duplicate_email():
admin = get_user_by_email("admin@compton.example")
try:
create_admin_user(
admin,
email="user@compton.example",
password="Valid123",
role="user",
is_superuser=False,
status="active",
)
assert False, "Expected duplicate user error"
except ValueError as exc:
assert str(exc) == "USER_EXISTS"
def test_get_server_log_tail_empty_when_missing():
with patch("app.modules.admin.service.settings") as mock_settings:
mock_settings.server_log_path = "/tmp/compton-missing-log.txt"
payload = get_server_log_tail()
assert payload["lines"] == []