fix(реклама): GRANT crm_supplier_worker на ad_campaigns/ad_campaign_ads + ad_settings по дефолту — иначе джобы Директа падают permission denied на проде
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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'),
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// Джобы Директа (Charge/SyncAudience/SyncModeration) перечисляют и обновляют
|
||||
// ad_campaigns / ad_campaign_ads через соединение pgsql_supplier (роль
|
||||
// crm_supplier_worker, BYPASSRLS). BYPASSRLS обходит RLS-политику, но НЕ
|
||||
// заменяет табличную привилегию — без GRANT будет permission denied на проде
|
||||
// (как sales_prospects 19.07). SELECT — чтение всеми тремя джобами; UPDATE —
|
||||
// запись статусов модерации SyncCampaignModerationJob. Гард на существование
|
||||
// роли: на dev/test роли нет (DB_USERNAME=postgres superuser).
|
||||
DB::statement(<<<'SQL'
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'crm_supplier_worker') THEN
|
||||
GRANT SELECT, UPDATE ON ad_campaigns TO crm_supplier_worker;
|
||||
GRANT SELECT, UPDATE ON ad_campaign_ads TO crm_supplier_worker;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
SQL);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
DB::statement(<<<'SQL'
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'crm_supplier_worker') THEN
|
||||
REVOKE SELECT, UPDATE ON ad_campaigns FROM crm_supplier_worker;
|
||||
REVOKE SELECT, UPDATE ON ad_campaign_ads FROM crm_supplier_worker;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
SQL);
|
||||
}
|
||||
};
|
||||
@@ -8,6 +8,34 @@
|
||||
> параллельно с боевым 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: будущему админ-экрану
|
||||
|
||||
Reference in New Issue
Block a user