Подтверждённый голос
Номер талона нормализуется, HMAC-хеш сверяется с хранилищем, код допускается только один раз. Открытый номер в JSON не записывается.
Короткая карта текущей реализации: от клика по звезде до файлового хранилища, видимого счётчика и JSON-LD. Здесь же — честное ревью без изменения рабочего кода.
Главный принцип: браузер только показывает интерфейс. Проверка, расчёт и запись выполняются PHP на сервере.
Не переносить логику между файлами без причины: сейчас у каждого участка есть понятный владелец.
| Файл | Что делает | Можно редактировать вручную? |
|---|---|---|
| includes/rating.php | Конфигурация страниц, базовые значения и сборка Product/LocalBusiness JSON-LD. | Да, осторожно. Путь страницы должен точно совпадать с SCRIPT_NAME. |
| includes/rating-widget.php | Единая HTML-разметка модалки и её доступные состояния. | Да, но одновременно проверять CSS и JS-селекторы. |
| includes/rating-service.php | Хранилище, расчёт, HMAC, cookie, origin и защита от повторов. | Только как backend-код; не дублировать в JavaScript. |
| includes/client-ip.php | Единый доверенный resolver IP для рейтинга и почтовой формы; знает актуальный адрес KillBot. | При смене прокси обновлять только список PROJECT_TRUSTED_PROXY_IPS. |
| rating-vote.php | Публичный POST-only JSON endpoint голосования. | Менять только вместе с интеграционным тестом ответов и кодов ошибок. |
| includes/rating-data.json | Подтверждённые/неподтверждённые голоса, HMAC талонов и попытки. | Нет. Не хранить здесь открытые номера; перед правкой делать резервную копию. |
| js/jquery.validationEngine-ru.js | Исходный клиентский owner интерфейса рейтинга; при сборке входит в общий runtime. | Да, затем обязательно пересобрать runtime-common.min.js. |
| css/main.min.css | Owner визуального блока SHARED RATING MODAL REDESIGN. | Да, с проверкой desktop/mobile и состояний модалки. |
Подтверждённый голос влияет полностью; голос без талона учитывается с минимальным весом.
Номер талона нормализуется, HMAC-хеш сверяется с хранилищем, код допускается только один раз. Открытый номер в JSON не записывается.
Сохраняется отдельно и добавляет всего одну сотую обычного веса к средней оценке. При этом видимое количество оценок увеличивается на один.
На той же услуге голос блокируется на 7 дней при совпадении HMAC-хеша реального IP или подписанного HttpOnly cookie. За KillBot адрес берётся из X-Forwarded-For только при доверенном REMOTE_ADDR.
Не более восьми попыток с одного IP-хеша за час. Просроченные попытки удаляются при следующей записи.
flock не позволяет двум PHP-процессам одновременно перезаписывать JSON.
Серверный aggregate — единственный источник значений при загрузке. Ручная синхронизация каждой страницы не нужна.
rating_get_aggregate() возвращает среднюю и число голосов один раз на запрос страницы.
Эти значения одновременно попадают в модалку, badge «Оценки» в футере и AggregateRating.
Ответ endpoint обновляет все видимые значения и JSON-LD в текущем DOM; после перезагрузки источник снова сервер.
На текущем объёме система работоспособна. Критических блокеров по выполненному smoke-тесту нет.
Интерфейс, футер и schema используют один aggregate. Это снижает риск расхождений и избавляет от ручного редактирования счётчиков.
POST-only endpoint, проверка источника, суточный HMAC-токен, ограничение размера запроса, подписанная cookie и отсутствие открытых IP/талонов в хранилище.
При недоступном JSON страница сохраняет базовую оценку, а некорректное хранилище не перезаписывается пустыми данными.
Клиентская логика работает и корректно попадает в общий runtime, но jquery.validationEngine-ru.js имеет две несвязанные обязанности. При следующем отдельном рефакторинге рейтинг лучше вынести в собственный исходник и сохранить прежний порядок сборки.
Через обычный HTTP исходник не выдаётся, а каталог includes закрыт. Но при утечке исходников или резервной копии один секрет раскрывает токены и хеши. В будущем лучше брать его из закрытого серверного конфига вне репозитория.
flock защищает от параллельных запросов, но авария между ftruncate и fwrite может повредить файл. Следующий уровень защиты — временный файл, проверка и атомарная замена плюс резервная копия.
Каждый голос хранится отдельной записью и никогда не сворачивается. Сейчас файл небольшой, но при росте нужен порог размера и периодическая безопасная агрегация старых голосов.
Рейтинг и антиспам формы используют общий project_client_ip(). Для доверенного прокси 93.77.162.43 берётся первый валидный адрес из X-Forwarded-For; от любого другого отправителя этот заголовок игнорируется.
IP, cookie и токен хорошо останавливают обычные повторы, но не гарантируют защиту от автоматизации с ротацией адресов и cookie. Это соответствует выбранной лёгкой архитектуре без БД.
Неподтверждённая оценка добавляет единицу к ratingCount, но только 0,01 к весу средней. Это принято намеренно, однако является нестандартной интерпретацией агрегата и должно оставаться задокументированным.
Минимальный безопасный порядок изменения системы без ручной правки накопленных голосов.
Короткий обязательный чек-лист после любого изменения рейтинга.