feat: supabase schema migrations + kong gateway config

This commit is contained in:
2026-06-16 19:06:50 +02:00
parent 1c798efe15
commit d32ce26d9e
4 changed files with 140 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
_format_version: "2.1"
services:
- name: postgrest
url: http://rest:3000
routes:
- name: rest-v1
paths:
- /rest/v1/
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<'EOSQL'
-- Create authenticator role (no-login, used by PostgREST)
DO $$
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'authenticator') THEN
CREATE ROLE authenticator NOLOGIN;
END IF;
END
$$;
-- Grant authenticator usage on public schema and read access to all tables
GRANT USAGE ON SCHEMA public TO authenticator;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO authenticator;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO authenticator;
EOSQL
+103
View File
@@ -0,0 +1,103 @@
-- ============================================================
-- willhaben-tracker — initial schema migration
-- ============================================================
-- -----------------------------------------------------------
-- 1. users (whitelisted Telegram users)
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS users (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
telegram_id bigint UNIQUE NOT NULL,
username text,
first_name text,
is_active boolean NOT NULL DEFAULT true,
created_at timestamptz NOT NULL DEFAULT now()
);
-- -----------------------------------------------------------
-- 2. search_queries (saved searches per user)
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS search_queries (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid REFERENCES users(id) ON DELETE CASCADE NOT NULL,
keyword text NOT NULL,
interval_minutes int NOT NULL DEFAULT 60,
is_active boolean NOT NULL DEFAULT true,
last_scraped_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now()
);
-- -----------------------------------------------------------
-- 3. ads (raw ad snapshots, globally deduplicated by wh_ad_id)
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS ads (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
wh_ad_id text UNIQUE NOT NULL,
raw_json jsonb NOT NULL,
title text NOT NULL,
price numeric,
location text,
url text,
published_at timestamptz,
first_seen_at timestamptz NOT NULL DEFAULT now()
);
-- -----------------------------------------------------------
-- 4. query_ads (junction: which query found which ad)
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS query_ads (
search_query_id uuid REFERENCES search_queries(id) ON DELETE CASCADE NOT NULL,
ad_id uuid REFERENCES ads(id) ON DELETE CASCADE NOT NULL,
first_seen_at timestamptz NOT NULL DEFAULT now(),
is_notified boolean NOT NULL DEFAULT false,
PRIMARY KEY (search_query_id, ad_id)
);
-- -----------------------------------------------------------
-- 5. notifications (audit log of sent Telegram messages)
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS notifications (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid REFERENCES users(id) ON DELETE CASCADE NOT NULL,
ad_id uuid REFERENCES ads(id) ON DELETE SET NULL,
message_id int,
sent_at timestamptz NOT NULL DEFAULT now()
);
-- -----------------------------------------------------------
-- 6. scrape_logs (worker health / debugging)
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS scrape_logs (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
search_query_id uuid REFERENCES search_queries(id) ON DELETE CASCADE NOT NULL,
status text NOT NULL CHECK (status IN ('success', 'error', 'rate_limited')),
ads_found int NOT NULL DEFAULT 0,
new_ads int NOT NULL DEFAULT 0,
error_message text,
scraped_at timestamptz NOT NULL DEFAULT now()
);
-- ============================================================
-- Indexes
-- ============================================================
-- Users: fast lookup by telegram_id (unique constraint already implies an index)
-- Search queries: user membership lookups
CREATE INDEX IF NOT EXISTS idx_search_queries_user_id ON search_queries(user_id);
-- Scheduler polling: active queries ordered by last scraped time
CREATE INDEX IF NOT EXISTS idx_search_queries_active_scraped
ON search_queries(is_active, last_scraped_at) WHERE is_active = true;
-- Notifier lookups: un-notified ads per query
CREATE INDEX IF NOT EXISTS idx_query_ads_notified
ON query_ads(search_query_id, is_notified) WHERE is_notified = false;
-- Notifications: recent messages per user
CREATE INDEX IF NOT EXISTS idx_notifications_user_sent
ON notifications(user_id, sent_at DESC);
-- Scrape logs: latest runs per query
CREATE INDEX IF NOT EXISTS idx_scrape_logs_query_at
ON scrape_logs(search_query_id, scraped_at DESC);
+8
View File
@@ -0,0 +1,8 @@
-- ============================================================
-- post-boot — runs after all migrations have been applied.
-- Grants INSERT/UPDATE to authenticator on user-facing tables.
-- (Run after 01-init.sql so tables exist.)
-- ============================================================
GRANT INSERT, UPDATE ON search_queries TO authenticator;
GRANT INSERT, UPDATE ON notifications TO authenticator;