From a0b6ada0bdaa10130661abe7f6d41205a1874076 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 21:50:54 +0000 Subject: [PATCH] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/integrations/supabase/types.ts | 80 ++++++++++++ ...0_7a0d7831-98d0-45d0-bbe2-bca9bccddd29.sql | 117 ++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 supabase/migrations/20260423215050_7a0d7831-98d0-45d0-bbe2-bca9bccddd29.sql diff --git a/src/integrations/supabase/types.ts b/src/integrations/supabase/types.ts index de7924c..de641cc 100644 --- a/src/integrations/supabase/types.ts +++ b/src/integrations/supabase/types.ts @@ -2775,6 +2775,86 @@ export type Database = { } Relationships: [] } + public_page_sections: { + Row: { + content: Json + created_at: string + id: string + page_id: string + section_type: string + sort_order: number + updated_at: string + } + Insert: { + content?: Json + created_at?: string + id?: string + page_id: string + section_type: string + sort_order?: number + updated_at?: string + } + Update: { + content?: Json + created_at?: string + id?: string + page_id?: string + section_type?: string + sort_order?: number + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "public_page_sections_page_id_fkey" + columns: ["page_id"] + isOneToOne: false + referencedRelation: "public_pages" + referencedColumns: ["id"] + }, + ] + } + public_pages: { + Row: { + created_at: string + created_by: string | null + id: string + meta_description: string | null + published_at: string | null + show_in_nav: boolean + slug: string + sort_order: number + status: string + title: string + updated_at: string + } + Insert: { + created_at?: string + created_by?: string | null + id?: string + meta_description?: string | null + published_at?: string | null + show_in_nav?: boolean + slug: string + sort_order?: number + status?: string + title: string + updated_at?: string + } + Update: { + created_at?: string + created_by?: string | null + id?: string + meta_description?: string | null + published_at?: string | null + show_in_nav?: boolean + slug?: string + sort_order?: number + status?: string + title?: string + updated_at?: string + } + Relationships: [] + } smtp_settings: { Row: { created_at: string diff --git a/supabase/migrations/20260423215050_7a0d7831-98d0-45d0-bbe2-bca9bccddd29.sql b/supabase/migrations/20260423215050_7a0d7831-98d0-45d0-bbe2-bca9bccddd29.sql new file mode 100644 index 0000000..243e71e --- /dev/null +++ b/supabase/migrations/20260423215050_7a0d7831-98d0-45d0-bbe2-bca9bccddd29.sql @@ -0,0 +1,117 @@ + +-- Public pages CMS tables +CREATE TABLE public.public_pages ( + id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY, + slug TEXT NOT NULL UNIQUE, + title TEXT NOT NULL, + meta_description TEXT, + status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'published')), + sort_order INTEGER NOT NULL DEFAULT 0, + show_in_nav BOOLEAN NOT NULL DEFAULT true, + published_at TIMESTAMPTZ, + created_by UUID, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE INDEX idx_public_pages_slug ON public.public_pages(slug); +CREATE INDEX idx_public_pages_status ON public.public_pages(status); + +CREATE TABLE public.public_page_sections ( + id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY, + page_id UUID NOT NULL REFERENCES public.public_pages(id) ON DELETE CASCADE, + section_type TEXT NOT NULL CHECK (section_type IN ('hero','rich_text','feature_grid','cta','contact','faq')), + sort_order INTEGER NOT NULL DEFAULT 0, + content JSONB NOT NULL DEFAULT '{}'::jsonb, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE INDEX idx_public_page_sections_page_id ON public.public_page_sections(page_id); + +-- Triggers for updated_at +CREATE TRIGGER trg_public_pages_updated_at + BEFORE UPDATE ON public.public_pages + FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at(); + +CREATE TRIGGER trg_public_page_sections_updated_at + BEFORE UPDATE ON public.public_page_sections + FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at(); + +-- Enable RLS +ALTER TABLE public.public_pages ENABLE ROW LEVEL SECURITY; +ALTER TABLE public.public_page_sections ENABLE ROW LEVEL SECURITY; + +-- Public can read published pages +CREATE POLICY "Anyone can view published pages" + ON public.public_pages FOR SELECT + USING (status = 'published'); + +CREATE POLICY "Admins can view all pages" + ON public.public_pages FOR SELECT + TO authenticated + USING (public.is_admin(auth.uid())); + +CREATE POLICY "Admins can insert pages" + ON public.public_pages FOR INSERT + TO authenticated + WITH CHECK (public.is_admin(auth.uid())); + +CREATE POLICY "Admins can update pages" + ON public.public_pages FOR UPDATE + TO authenticated + USING (public.is_admin(auth.uid())); + +CREATE POLICY "Admins can delete pages" + ON public.public_pages FOR DELETE + TO authenticated + USING (public.is_admin(auth.uid())); + +-- Sections inherit access from page +CREATE POLICY "Anyone can view sections of published pages" + ON public.public_page_sections FOR SELECT + USING (EXISTS (SELECT 1 FROM public.public_pages p WHERE p.id = page_id AND p.status = 'published')); + +CREATE POLICY "Admins can view all sections" + ON public.public_page_sections FOR SELECT + TO authenticated + USING (public.is_admin(auth.uid())); + +CREATE POLICY "Admins can insert sections" + ON public.public_page_sections FOR INSERT + TO authenticated + WITH CHECK (public.is_admin(auth.uid())); + +CREATE POLICY "Admins can update sections" + ON public.public_page_sections FOR UPDATE + TO authenticated + USING (public.is_admin(auth.uid())); + +CREATE POLICY "Admins can delete sections" + ON public.public_page_sections FOR DELETE + TO authenticated + USING (public.is_admin(auth.uid())); + +-- Storage bucket for inline images +INSERT INTO storage.buckets (id, name, public) +VALUES ('public-page-images', 'public-page-images', true) +ON CONFLICT (id) DO NOTHING; + +CREATE POLICY "Public page images are publicly accessible" + ON storage.objects FOR SELECT + USING (bucket_id = 'public-page-images'); + +CREATE POLICY "Admins can upload public page images" + ON storage.objects FOR INSERT + TO authenticated + WITH CHECK (bucket_id = 'public-page-images' AND public.is_admin(auth.uid())); + +CREATE POLICY "Admins can update public page images" + ON storage.objects FOR UPDATE + TO authenticated + USING (bucket_id = 'public-page-images' AND public.is_admin(auth.uid())); + +CREATE POLICY "Admins can delete public page images" + ON storage.objects FOR DELETE + TO authenticated + USING (bucket_id = 'public-page-images' AND public.is_admin(auth.uid()));