added supabase

This commit is contained in:
Austin
2026-02-20 09:12:47 -06:00
parent ecbc399ec4
commit b54ad064ff
54 changed files with 3162 additions and 445 deletions
@@ -0,0 +1,38 @@
-- Create posts table
create table if not exists public.posts (
id text primary key, -- slug-based ID
title text not null,
date timestamptz not null,
excerpt text not null default '',
content text not null default '', -- raw markdown
content_html text not null default '', -- pre-rendered HTML
author text not null default '',
tags text[] not null default '{}',
cover_image text,
published boolean not null default false,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
-- Indexes
create index if not exists idx_posts_date on public.posts (date desc);
create index if not exists idx_posts_published on public.posts (published);
create index if not exists idx_posts_author on public.posts (author);
create index if not exists idx_posts_tags on public.posts using gin (tags);
-- Auto-update trigger for updated_at
create or replace function public.handle_updated_at()
returns trigger as $$
begin
new.updated_at = now();
return new;
end;
$$ language plpgsql;
create trigger on_posts_updated
before update on public.posts
for each row
execute function public.handle_updated_at();
-- Enable RLS
alter table public.posts enable row level security;
@@ -0,0 +1,15 @@
-- Create admin_users table
create table if not exists public.admin_users (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references auth.users(id) on delete cascade,
email text not null,
role text not null default 'editor' check (role in ('super_admin', 'admin', 'editor')),
created_at timestamptz not null default now(),
unique(user_id)
);
-- Index on user_id for fast lookups
create index if not exists idx_admin_users_user_id on public.admin_users (user_id);
-- Enable RLS
alter table public.admin_users enable row level security;
@@ -0,0 +1,35 @@
-- Create tables that were originally created via Supabase dashboard.
-- Using IF NOT EXISTS so this is safe to run on existing databases.
-- Comments table
create table if not exists public.comments (
id bigint generated always as identity primary key,
name text not null,
email text not null,
comment text not null,
post_id text not null,
created_at timestamptz not null default now()
);
alter table public.comments enable row level security;
-- Subscriptions table
create table if not exists public.subscriptions (
id bigint generated always as identity primary key,
email text not null unique,
created_at timestamptz not null default now()
);
alter table public.subscriptions enable row level security;
-- Authors table
create table if not exists public.authors (
name text primary key,
bio text not null default '',
x_link text,
fb_link text,
insta_link text,
pfp_link text
);
alter table public.authors enable row level security;
@@ -0,0 +1,151 @@
-- Helper function: check if current user is an admin
create or replace function public.is_admin()
returns boolean as $$
begin
return exists (
select 1 from public.admin_users
where user_id = auth.uid()
);
end;
$$ language plpgsql security definer;
-- Helper function: check if current user has a specific role or higher
create or replace function public.has_admin_role(required_role text)
returns boolean as $$
declare
user_role text;
begin
select role into user_role from public.admin_users
where user_id = auth.uid();
if user_role is null then
return false;
end if;
-- Role hierarchy: super_admin > admin > editor
if required_role = 'editor' then
return user_role in ('editor', 'admin', 'super_admin');
elsif required_role = 'admin' then
return user_role in ('admin', 'super_admin');
elsif required_role = 'super_admin' then
return user_role = 'super_admin';
end if;
return false;
end;
$$ language plpgsql security definer;
-- ============================================
-- POSTS policies (drop first in case of partial previous run)
-- ============================================
drop policy if exists "Public can read published posts" on public.posts;
drop policy if exists "Editors can insert posts" on public.posts;
drop policy if exists "Editors can update posts" on public.posts;
drop policy if exists "Admins can delete posts" on public.posts;
create policy "Public can read published posts"
on public.posts for select
using (published = true or public.is_admin());
create policy "Editors can insert posts"
on public.posts for insert
with check (public.has_admin_role('editor'));
create policy "Editors can update posts"
on public.posts for update
using (public.has_admin_role('editor'));
create policy "Admins can delete posts"
on public.posts for delete
using (public.has_admin_role('admin'));
-- ============================================
-- COMMENTS policies
-- ============================================
drop policy if exists "Public can read comments" on public.comments;
drop policy if exists "Public can insert comments" on public.comments;
drop policy if exists "Editors can delete comments" on public.comments;
drop policy if exists "Editors can update comments" on public.comments;
create policy "Public can read comments"
on public.comments for select
using (true);
create policy "Public can insert comments"
on public.comments for insert
with check (true);
create policy "Editors can delete comments"
on public.comments for delete
using (public.has_admin_role('editor'));
create policy "Editors can update comments"
on public.comments for update
using (public.has_admin_role('editor'));
-- ============================================
-- SUBSCRIPTIONS policies
-- ============================================
drop policy if exists "Public can insert subscriptions" on public.subscriptions;
drop policy if exists "Public can read subscriptions" on public.subscriptions;
drop policy if exists "Admins can delete subscriptions" on public.subscriptions;
create policy "Public can insert subscriptions"
on public.subscriptions for insert
with check (true);
create policy "Public can read subscriptions"
on public.subscriptions for select
using (true);
create policy "Admins can delete subscriptions"
on public.subscriptions for delete
using (public.has_admin_role('admin'));
-- ============================================
-- AUTHORS policies
-- ============================================
drop policy if exists "Public can read authors" on public.authors;
drop policy if exists "Admins can insert authors" on public.authors;
drop policy if exists "Admins can update authors" on public.authors;
drop policy if exists "Super admins can delete authors" on public.authors;
create policy "Public can read authors"
on public.authors for select
using (true);
create policy "Admins can insert authors"
on public.authors for insert
with check (public.has_admin_role('admin'));
create policy "Admins can update authors"
on public.authors for update
using (public.has_admin_role('admin'));
create policy "Super admins can delete authors"
on public.authors for delete
using (public.has_admin_role('super_admin'));
-- ============================================
-- ADMIN_USERS policies
-- ============================================
drop policy if exists "Admins can read admin users" on public.admin_users;
drop policy if exists "Super admins can insert admin users" on public.admin_users;
drop policy if exists "Super admins can update admin users" on public.admin_users;
drop policy if exists "Super admins can delete admin users" on public.admin_users;
create policy "Admins can read admin users"
on public.admin_users for select
using (public.is_admin());
create policy "Super admins can insert admin users"
on public.admin_users for insert
with check (public.has_admin_role('super_admin'));
create policy "Super admins can update admin users"
on public.admin_users for update
using (public.has_admin_role('super_admin'));
create policy "Super admins can delete admin users"
on public.admin_users for delete
using (public.has_admin_role('super_admin'));