Sessions 5-7a: 955 tests, deployment ready
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
-- ---------------------------------------------------------------
|
||||
-- 015 — Web push subscriptions + MFA tracking + grace period.
|
||||
--
|
||||
-- Three concerns bundled in one migration because they all surfaced
|
||||
-- in the Phase 5 PWA / payments / security pass:
|
||||
-- 1. push_subscriptions — per-user push endpoints from the browser
|
||||
-- 2. user_profiles.mfa_setup_prompted — track if we've already asked
|
||||
-- a paid user to enable MFA (so we only nag once)
|
||||
-- 3. user_profiles.grace_period_until — Stripe payment_failed grants
|
||||
-- a 48h grace before tier downgrades take effect
|
||||
-- ---------------------------------------------------------------
|
||||
|
||||
create table if not exists public.push_subscriptions (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
user_id uuid not null references auth.users(id) on delete cascade,
|
||||
endpoint text not null,
|
||||
keys_p256dh text not null,
|
||||
keys_auth text not null,
|
||||
-- One row per (user, endpoint). A user installing the PWA on two
|
||||
-- devices gets two rows. Re-subscribing on the same device upserts.
|
||||
sport_preferences text[] not null default '{nba,mlb,wnba,nfl,nhl,ncaab,ncaafb}',
|
||||
notify_on_resolution boolean not null default true,
|
||||
notify_on_cascade boolean not null default true,
|
||||
notify_on_cheatsheet boolean not null default true,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
unique (user_id, endpoint)
|
||||
);
|
||||
|
||||
create index if not exists idx_push_subscriptions_user on public.push_subscriptions(user_id);
|
||||
create index if not exists idx_push_subscriptions_sport on public.push_subscriptions using gin (sport_preferences);
|
||||
create index if not exists idx_push_subscriptions_resolution
|
||||
on public.push_subscriptions(notify_on_resolution) where notify_on_resolution = true;
|
||||
|
||||
drop trigger if exists set_push_subscriptions_updated_at on public.push_subscriptions;
|
||||
create trigger set_push_subscriptions_updated_at
|
||||
before update on public.push_subscriptions
|
||||
for each row execute function public.touch_updated_at();
|
||||
|
||||
alter table public.push_subscriptions enable row level security;
|
||||
|
||||
drop policy if exists "users manage own push subscriptions" on public.push_subscriptions;
|
||||
create policy "users manage own push subscriptions"
|
||||
on public.push_subscriptions for all
|
||||
using (auth.uid() = user_id)
|
||||
with check (auth.uid() = user_id);
|
||||
|
||||
-- ---------------------------------------------------------------
|
||||
-- user_profiles + users additions.
|
||||
--
|
||||
-- Two columns get added to BOTH tables because the codebase has two
|
||||
-- user-state tables in flight:
|
||||
-- public.users — Express backend / Stripe webhook writes here
|
||||
-- public.user_profiles — Next.js routes + AuthContext read here
|
||||
-- Unifying them is out of scope; keeping the columns in sync is the
|
||||
-- least-risk move.
|
||||
-- ---------------------------------------------------------------
|
||||
|
||||
alter table public.user_profiles
|
||||
add column if not exists mfa_setup_prompted boolean not null default false,
|
||||
add column if not exists grace_period_until timestamptz;
|
||||
|
||||
alter table public.users
|
||||
add column if not exists mfa_setup_prompted boolean not null default false,
|
||||
add column if not exists grace_period_until timestamptz;
|
||||
|
||||
create index if not exists idx_user_profiles_grace_period
|
||||
on public.user_profiles(grace_period_until)
|
||||
where grace_period_until is not null;
|
||||
|
||||
create index if not exists idx_users_grace_period
|
||||
on public.users(grace_period_until)
|
||||
where grace_period_until is not null;
|
||||
Reference in New Issue
Block a user