🏗 Фаза 1-4: Архитектура, ядро, проверки, API, генератор отчетов
- scanner/engine.py — Playwright-движок сканирования - scanner/models.py — Pydantic модели - scanner/checks/ — 5 проверок (cookie, privacy, forms, server, external) - api/server.py — FastAPI REST API - reports/generator.py — PDF через WeasyPrint + Jinja2 - main.py — CLI + сервер Проверки: ✅ cookie_banner — поиск cookie-баннера ✅ privacy_link — проверка ссылки на политику ✅ form_checkbox — проверка чекбоксов согласия ✅ server_location — геолокация сервера (RФ или нет) ✅ external_scripts — внешние скрипты аналитики
This commit is contained in:
commit
de18090304
20 files changed
+1665
No files matched your search
@@ -0,0 +1,76 @@
|
||||
"""
|
||||
Базовый класс для всех проверок 152-ФЗ.
|
||||
Каждая проверка наследуется от этого класса и реализует метод check().
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from playwright.async_api import Page
|
||||
|
||||
from scanner.models import CheckResult, CheckStatus, RiskLevel
|
||||
|
||||
|
||||
class BaseCheck(ABC):
|
||||
"""Базовый класс для проверки соответствия 152-ФЗ."""
|
||||
|
||||
name: str = "base" # Уникальное имя (используется в реестре)
|
||||
title: str = "Base Check" # Отображаемое название
|
||||
description: str = "" # Описание что проверяет
|
||||
risk_on_fail: RiskLevel = RiskLevel.LOW # Уровень риска при провале
|
||||
default_weight: int = 10 # Вес (влияние на общий балл)
|
||||
|
||||
@abstractmethod
|
||||
async def check(self, page: Page, url: str) -> CheckResult:
|
||||
"""
|
||||
Выполнить проверку сайта.
|
||||
|
||||
Args:
|
||||
page: Playwright Page объект (сайт уже загружен)
|
||||
url: URL проверяемого сайта
|
||||
|
||||
Returns:
|
||||
CheckResult с результатом проверки
|
||||
"""
|
||||
pass
|
||||
|
||||
def _pass_result(self, message: str = "", details: dict = {}) -> CheckResult:
|
||||
"""Создать успешный результат."""
|
||||
return CheckResult(
|
||||
name=self.name,
|
||||
title=self.title,
|
||||
status=CheckStatus.PASS,
|
||||
risk_level=self.risk_on_fail,
|
||||
message=message or f"✓ {self.title} — проверено, нарушений не найдено",
|
||||
details=details,
|
||||
)
|
||||
|
||||
def _fail_result(self, message: str, details: dict = {}, risk_level: RiskLevel | None = None) -> CheckResult:
|
||||
"""Создать результат с провалом."""
|
||||
return CheckResult(
|
||||
name=self.name,
|
||||
title=self.title,
|
||||
status=CheckStatus.FAIL,
|
||||
risk_level=risk_level or self.risk_on_fail,
|
||||
message=f"✗ {message}",
|
||||
details=details,
|
||||
)
|
||||
|
||||
def _skip_result(self, message: str = "") -> CheckResult:
|
||||
"""Создать результат с пропуском."""
|
||||
return CheckResult(
|
||||
name=self.name,
|
||||
title=self.title,
|
||||
status=CheckStatus.SKIP,
|
||||
risk_level=RiskLevel.LOW,
|
||||
message=message or f"⏭ {self.title} — пропущено",
|
||||
)
|
||||
|
||||
def _error_result(self, message: str) -> CheckResult:
|
||||
"""Создать результат с ошибкой."""
|
||||
return CheckResult(
|
||||
name=self.name,
|
||||
title=self.title,
|
||||
status=CheckStatus.ERROR,
|
||||
risk_level=RiskLevel.HIGH,
|
||||
message=f"⚠ {message}",
|
||||
)
|
||||
Reference in new issue
Block a user