From 5010087b4f1e8f3e2ba80387ccde0b91aaa8a726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Sat, 25 Jul 2026 00:25:01 +0300 Subject: [PATCH] =?UTF-8?q?fix(=D1=80=D0=B5=D0=BA=D0=BB=D0=B0=D0=BC=D0=B0)?= =?UTF-8?q?:=20GRANT=20crm=5Fsupplier=5Fworker=20=D0=BD=D0=B0=20ad=5Fcampa?= =?UTF-8?q?igns/ad=5Fcampaign=5Fads=20+=20ad=5Fsettings=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D0=B4=D0=B5=D1=84=D0=BE=D0=BB=D1=82=D1=83=20=E2=80=94=20=D0=B8?= =?UTF-8?q?=D0=BD=D0=B0=D1=87=D0=B5=20=D0=B4=D0=B6=D0=BE=D0=B1=D1=8B=20?= =?UTF-8?q?=D0=94=D0=B8=D1=80=D0=B5=D0=BA=D1=82=D0=B0=20=D0=BF=D0=B0=D0=B4?= =?UTF-8?q?=D0=B0=D1=8E=D1=82=20permission=20denied=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B4=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- app/app/Jobs/ChargeCampaignSpendJob.php | 2 +- ...0400_grant_supplier_worker_advertising.php | 44 +++++++++++++++++++ db/CHANGELOG_schema.md | 28 ++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 app/database/migrations/2026_07_25_100400_grant_supplier_worker_advertising.php diff --git a/app/app/Jobs/ChargeCampaignSpendJob.php b/app/app/Jobs/ChargeCampaignSpendJob.php index 342ff4fe..3def97a3 100644 --- a/app/app/Jobs/ChargeCampaignSpendJob.php +++ b/app/app/Jobs/ChargeCampaignSpendJob.php @@ -59,7 +59,7 @@ class ChargeCampaignSpendJob implements ShouldQueue $stopAll = app(AdStopAllService::class); $date = Carbon::now()->subDay()->toDateString(); - $markup = new AdMarkup((string) (DB::connection('pgsql_supplier')->table('ad_settings')->value('markup_percent') ?? '30.00')); + $markup = new AdMarkup((string) (DB::table('ad_settings')->value('markup_percent') ?? '30.00')); $direct = new YandexDirectClient( $this->configString('services.yandex_direct.base_url'), $this->configString('services.yandex_direct.token'), diff --git a/app/database/migrations/2026_07_25_100400_grant_supplier_worker_advertising.php b/app/database/migrations/2026_07_25_100400_grant_supplier_worker_advertising.php new file mode 100644 index 00000000..3621d507 --- /dev/null +++ b/app/database/migrations/2026_07_25_100400_grant_supplier_worker_advertising.php @@ -0,0 +1,44 @@ + параллельно с боевым main. Их прежние номера (v8.59–v8.62) **столкнулись** с боевыми (автоподбор), > поэтому при сведении они перенумерованы. Содержание не менялось. +## v8.94 (2026-07-25) — GRANT crm_supplier_worker на ad_campaigns/ad_campaign_ads — доступ ночных джобов Директа + +rls-reviewer подтвердил дыру: три ночных джоба Директа (Charge/SyncAudience/ +SyncModeration) перечисляют и обновляют `ad_campaigns`/`ad_campaign_ads` +через соединение `pgsql_supplier` (роль `crm_supplier_worker`, BYPASSRLS). +BYPASSRLS снимает RLS-политику, но НЕ заменяет табличную привилегию — без +GRANT на проде было бы `permission denied for table ad_campaigns/ +ad_campaign_ads` (тот же класс сбоя, что sales_prospects 19.07): + +```sql +GRANT SELECT, UPDATE ON ad_campaigns TO crm_supplier_worker; +GRANT SELECT, UPDATE ON ad_campaign_ads TO crm_supplier_worker; +``` + +SELECT — чтение всеми тремя джобами; UPDATE — запись `moderation_status` +через SyncCampaignModerationJob. Миграция +`app/database/migrations/2026_07_25_100400_grant_supplier_worker_advertising.php` +(`down()` — симметричный REVOKE), гард на существование роли (на dev/тест +роли нет), прогнана на `liderra_testing` — DONE. + +Той же задачей `ChargeCampaignSpendJob` переведён на чтение `ad_settings` +(наценка) по ДЕФОЛТНОМУ соединению вместо `pgsql_supplier` — таблица +глобальная, без RLS, `crm_app_user` уже имеет `SELECT` из миграции +2026_07_24_100300; отдельный supplier-грант не нужен. + +Структурно: 0 новых таблиц/колонок/индексов, +2 GRANT-выражения. +Функций/триггеров без изменений. + ## v8.93 (2026-07-25) — Яндекс-канал, Часть B1, Task 5 — GRANT crm_admin_user на ad_* + модели Eloquent Закрывает совет B-adv-1 из RLS-ревью Части A: будущему админ-экрану