- docker-compose.prod.yml: backend + worker добавлены в сеть gendesign_shared
(нужен прямой TCP к tradein-postgres для psycopg ETL)
- tradein-mvp/data/sql/101_gendesign_reader_role.sql: роль gendesign_reader
(LOGIN, SELECT на houses/house_sources/houses_price_dynamics/
house_reliability_checks/house_reviews; пароль через TRADEIN_READER_PASSWORD
bootstrap в deploy-tradein.yml)
- .forgejo/workflows/deploy-tradein.yml: bootstrap ALTER ROLE gendesign_reader
PASSWORD из env после миграций; warn (не exit 1) если переменная не задана
- backend/app/core/config.py: settings.tradein_database_url (env TRADEIN_DATABASE_URL)
- backend/app/services/etl/newbuilding_crossload.py: run_crossload() — psycopg
server-side cursor, batch 500, UPSERT ON CONFLICT (source, ext_house_id),
SAVEPOINT per-row; disabled-режим если url пуст
- backend/app/workers/tasks/etl_newbuilding_crossload.py: Celery task
- backend/app/workers/beat_schedule.py: nightly 03:30 МСК (00:30 UTC)
- backend/app/api/v1/admin_scrape.py: POST /admin/scrape/newbuilding-crossload
- backend/tests/services/test_newbuilding_crossload.py: 10 тестов без реальной БД
needs-human: TRADEIN_READER_PASSWORD → tradein .env.runtime;
TRADEIN_DATABASE_URL → gendesign backend/.env.runtime
44 lines
2.1 KiB
PL/PgSQL
44 lines
2.1 KiB
PL/PgSQL
-- 101_gendesign_reader_role.sql
|
|
-- Reader-роль для cross-load ETL gendesign → tradein (#976 950-E5).
|
|
-- Зеркало паттерна gendesign/data/sql/100_tradein_fdw_role.sql.
|
|
--
|
|
-- Роль gendesign_reader создаётся без пароля — пароль устанавливается
|
|
-- deploy-tradein.yml из env TRADEIN_READER_PASSWORD (bootstrap-шаг после миграций).
|
|
-- Никогда не embed password в SQL.
|
|
--
|
|
-- Доступ: ТОЛЬКО SELECT на houses, house_sources, houses_price_dynamics,
|
|
-- house_reliability_checks, house_reviews (источники cross-load ETL #976).
|
|
--
|
|
-- Идемпотентно: DO $$ IF NOT EXISTS — безопасно при повторном применении.
|
|
-- AUTO-APPLIED на прод при деплое через deploy-tradein.yml/_schema_migrations.
|
|
|
|
BEGIN;
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'gendesign_reader') THEN
|
|
CREATE ROLE gendesign_reader LOGIN;
|
|
END IF;
|
|
END$$;
|
|
|
|
COMMENT ON ROLE gendesign_reader IS
|
|
'Cross-load ETL reader from gendesign-backend (#976). '
|
|
'Password set by .forgejo/workflows/deploy-tradein.yml from env TRADEIN_READER_PASSWORD '
|
|
'post-migration step. Never embed password in SQL migrations.';
|
|
|
|
-- Defense-in-depth: явный REVOKE-периметр (любые PUBLIC-гранты игнорируются).
|
|
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM gendesign_reader;
|
|
REVOKE ALL ON ALL SEQUENCES IN SCHEMA public FROM gendesign_reader;
|
|
REVOKE ALL ON ALL FUNCTIONS IN SCHEMA public FROM gendesign_reader;
|
|
|
|
GRANT CONNECT ON DATABASE tradein TO gendesign_reader;
|
|
GRANT USAGE ON SCHEMA public TO gendesign_reader;
|
|
|
|
-- SELECT только на таблицах-источниках ETL #976 (не весь public).
|
|
GRANT SELECT ON houses TO gendesign_reader;
|
|
GRANT SELECT ON house_sources TO gendesign_reader;
|
|
GRANT SELECT ON houses_price_dynamics TO gendesign_reader;
|
|
GRANT SELECT ON house_reliability_checks TO gendesign_reader;
|
|
GRANT SELECT ON house_reviews TO gendesign_reader;
|
|
|
|
COMMIT;
|