- 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 — внешние скрипты аналитики
77 lines
3.0 KiB
Python
77 lines
3.0 KiB
Python
"""
|
|
Базовый класс для всех проверок 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}",
|
|
)
|