feat: add initial database schema, indexes, and RLS policies
This commit is contained in:
128
supabase/migrations/20260808000001_initial_schema.sql
Normal file
128
supabase/migrations/20260808000001_initial_schema.sql
Normal file
@@ -0,0 +1,128 @@
|
||||
-- Products, services, availability schedule, bookings, inquiries, and the
|
||||
-- public booked_slots mirror. See docs/superpowers/specs/2026-08-08-phase2-backend-foundation-supabase-design.md.
|
||||
|
||||
create table public.products (
|
||||
id text primary key,
|
||||
name text not null,
|
||||
category text not null check (category in ('hair-care', 'extensions', 'tools', 'accessories')),
|
||||
price numeric not null,
|
||||
image text not null,
|
||||
description text not null,
|
||||
in_stock boolean not null default true
|
||||
);
|
||||
|
||||
create table public.services (
|
||||
id text primary key,
|
||||
name text not null,
|
||||
duration_minutes integer not null,
|
||||
price_from numeric not null,
|
||||
description text not null,
|
||||
image text not null
|
||||
);
|
||||
|
||||
create table public.schedule_template (
|
||||
id text primary key default 'default',
|
||||
working_days integer[] not null,
|
||||
start_time time not null,
|
||||
end_time time not null,
|
||||
slot_minutes integer not null
|
||||
);
|
||||
|
||||
create table public.schedule_exceptions (
|
||||
date date primary key,
|
||||
closed boolean not null,
|
||||
note text
|
||||
);
|
||||
|
||||
create table public.bookings (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
service_id text not null references public.services(id),
|
||||
date date not null,
|
||||
time text not null,
|
||||
contact_name text not null,
|
||||
contact_phone text not null,
|
||||
contact_email text not null,
|
||||
contact_notes text not null default '',
|
||||
status text not null default 'confirmed' check (status in ('confirmed', 'cancelled')),
|
||||
created_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
create index bookings_service_id_idx on public.bookings (service_id);
|
||||
|
||||
create table public.booked_slots (
|
||||
date date not null,
|
||||
time text not null,
|
||||
primary key (date, time)
|
||||
);
|
||||
|
||||
create table public.inquiries (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
product_id text not null references public.products(id),
|
||||
contact_name text not null,
|
||||
contact_email text not null,
|
||||
contact_notes text not null default '',
|
||||
status text not null default 'new' check (status in ('new', 'read')),
|
||||
created_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
create index inquiries_product_id_idx on public.inquiries (product_id);
|
||||
|
||||
-- Row Level Security
|
||||
|
||||
alter table public.products enable row level security;
|
||||
alter table public.services enable row level security;
|
||||
alter table public.schedule_template enable row level security;
|
||||
alter table public.schedule_exceptions enable row level security;
|
||||
alter table public.bookings enable row level security;
|
||||
alter table public.booked_slots enable row level security;
|
||||
alter table public.inquiries enable row level security;
|
||||
|
||||
-- products: public read, admin write
|
||||
create policy "products_public_read" on public.products
|
||||
for select using (true);
|
||||
create policy "products_admin_write" on public.products
|
||||
for all using ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid)
|
||||
with check ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid);
|
||||
|
||||
-- services: public read, admin write
|
||||
create policy "services_public_read" on public.services
|
||||
for select using (true);
|
||||
create policy "services_admin_write" on public.services
|
||||
for all using ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid)
|
||||
with check ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid);
|
||||
|
||||
-- schedule_template: public read, admin write
|
||||
create policy "schedule_template_public_read" on public.schedule_template
|
||||
for select using (true);
|
||||
create policy "schedule_template_admin_write" on public.schedule_template
|
||||
for all using ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid)
|
||||
with check ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid);
|
||||
|
||||
-- schedule_exceptions: public read, admin write
|
||||
create policy "schedule_exceptions_public_read" on public.schedule_exceptions
|
||||
for select using (true);
|
||||
create policy "schedule_exceptions_admin_write" on public.schedule_exceptions
|
||||
for all using ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid)
|
||||
with check ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid);
|
||||
|
||||
-- bookings: anyone can insert (submit a booking); only admin can read/update/delete
|
||||
create policy "bookings_public_insert" on public.bookings
|
||||
for insert with check (true);
|
||||
create policy "bookings_admin_all" on public.bookings
|
||||
for all using ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid)
|
||||
with check ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid);
|
||||
|
||||
-- booked_slots: public read; only admin policy exists for writes (in practice only
|
||||
-- the security-definer trigger in the next migration ever writes here)
|
||||
create policy "booked_slots_public_read" on public.booked_slots
|
||||
for select using (true);
|
||||
create policy "booked_slots_admin_write" on public.booked_slots
|
||||
for all using ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid)
|
||||
with check ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid);
|
||||
|
||||
-- inquiries: anyone can insert; only admin can read/update/delete
|
||||
create policy "inquiries_public_insert" on public.inquiries
|
||||
for insert with check (true);
|
||||
create policy "inquiries_admin_all" on public.inquiries
|
||||
for all using ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid)
|
||||
with check ((select auth.uid()) = '00000000-0000-0000-0000-000000000001'::uuid);
|
||||
Reference in New Issue
Block a user