From 60faa0a123c7254a9e9f7541167809285bbb97f5 Mon Sep 17 00:00:00 2001 From: gibbyb Date: Wed, 9 Jul 2025 15:33:45 -0500 Subject: [PATCH] changes to deploy dev server --- scripts/supabase/db/schema.sql | 159 +++++++++--------- .../supabase/docker/docker-compose.dev.yml | 12 +- scripts/supabase/docker/docker-compose.s3.yml | 20 ++- scripts/supabase/docker/docker-compose.yml | 66 ++++---- 4 files changed, 134 insertions(+), 123 deletions(-) diff --git a/scripts/supabase/db/schema.sql b/scripts/supabase/db/schema.sql index d67a532..6dd67fd 100644 --- a/scripts/supabase/db/schema.sql +++ b/scripts/supabase/db/schema.sql @@ -1,4 +1,12 @@ --- Create a table for public profiles +create table statuses ( + id uuid default gen_random_uuid() primary key, + user_id uuid references auth.users on delete cascade not null, + updated_by_id uuid references auth.users on delete set null, + created_at timestamp with time zone default now() not null, + status text not null, + constraint status_length check (char_length(status) >= 3 and char_length(status) <= 80) +); + create table profiles ( id uuid references auth.users on delete cascade not null primary key, updated_at timestamp with time zone, @@ -6,30 +14,51 @@ create table profiles ( full_name text, avatar_url text, provider text, - + current_status_id uuid references statuses(id) on delete set null, constraint full_name_length check (char_length(full_name) >= 3 and char_length(full_name) <= 50) ); --- Set up Row Level Security (RLS) --- See https://supabase.com/docs/guides/auth/row-level-security for more details. + alter table profiles enable row level security; - create policy "Public profiles are viewable by everyone." on profiles for select using (true); - create policy "Users can insert their own profile." on profiles for insert with check ((select auth.uid()) = id); - create policy "Users can update own profile." on profiles for update using ((select auth.uid()) = id); --- This trigger automatically creates a profile entry when a new user signs up via Supabase Auth. --- See https://supabase.com/docs/guides/auth/managing-user-data#using-triggers for more details. +-- set up row level security (rls) for statuses +alter table statuses + enable row level security; + +-- policies for statuses +create policy "Public statuses are viewable by everyone." on statuses + for select using (true); +create policy "Authenticated users can insert statuses for any user." + on public.statuses + for insert + with check ( + (select auth.role()) = 'authenticated' + ); +create policy "Authenticated users can update statuses for any user." + on public.statuses + for update + using ( + (select auth.role()) = 'authenticated' + ) + with check ( + (select auth.role()) = 'authenticated' + ); + +-- function to handle new user creation create function public.handle_new_user() returns trigger set search_path = '' as $$ +declare + new_status_id uuid; begin + -- first create the profile insert into public.profiles (id, email, full_name, avatar_url, provider, updated_at) values ( new.id, @@ -39,88 +68,68 @@ begin new.raw_user_meta_data->>'provider', now() ); + + -- then create the first status + insert into public.statuses (user_id, updated_by_id, status) + values ( + new.id, + new.id, + 'Just joined!' + ) returning id into new_status_id; + + -- update the profile with the current status + update public.profiles + set current_status_id = new_status_id + where id = new.id; + return new; end; $$ language plpgsql security definer; + +-- function to update profile when status changes +create function public.update_profile_current_status() +returns trigger +set search_path = '' +as $$ +begin + -- update the profile's current_status_id to the most recent status + update public.profiles + set current_status_id = ( + select id + from public.statuses + where user_id = new.user_id + order by created_at desc + limit 1 + ) + where id = new.user_id; + + return new; +end; +$$ language plpgsql security definer; + +-- triggers create trigger on_auth_user_created after insert on auth.users for each row execute procedure public.handle_new_user(); --- Set up Storage! -insert into storage.buckets (id, name) - values ('avatars', 'avatars'); +create trigger on_status_insert_or_update + after insert or update on public.statuses + for each row execute procedure public.update_profile_current_status(); --- Set up access controls for storage. --- See https://supabase.com/docs/guides/storage#policy-examples for more details. +-- set up storage with public access! +insert into storage.buckets (id, name, public) + values ('avatars', 'avatars', true); + +-- set up access controls for storage (adjusted for public access) create policy "Avatar images are publicly accessible." on storage.objects for select using (bucket_id = 'avatars'); - create policy "Anyone can upload an avatar." on storage.objects for insert with check (bucket_id = 'avatars'); - create policy "Anyone can update an avatar." on storage.objects for update using (bucket_id = 'avatars'); - create policy "Anyone can delete an avatar." on storage.objects for delete using (bucket_id = 'avatars'); --- Create a table for public statuses -CREATE TABLE statuses ( - id uuid DEFAULT gen_random_uuid() PRIMARY KEY, - user_id uuid REFERENCES public.profiles ON DELETE CASCADE NOT NULL, - updated_by_id uuid REFERENCES public.profiles ON DELETE SET NULL DEFAULT auth.uid(), - created_at timestamp with time zone DEFAULT now() NOT NULL, - status text NOT NULL, - CONSTRAINT status_length CHECK (char_length(status) >= 3 AND char_length(status) <= 80) -); - --- Set up Row Level Security (RLS) -ALTER TABLE statuses - ENABLE ROW LEVEL SECURITY; - --- Policies -CREATE POLICY "Public statuses are viewable by everyone." ON statuses - FOR SELECT USING (true); - --- RECREATE it using the recommended sub-select form -CREATE POLICY "Authenticated users can insert statuses for any user." - ON public.statuses - FOR INSERT - WITH CHECK ( - (SELECT auth.role()) = 'authenticated' - ); - --- ADD an UPDATE policy so anyone signed-in can update *any* status -CREATE POLICY "Authenticated users can update statuses for any user." - ON public.statuses - FOR UPDATE - USING ( - (SELECT auth.role()) = 'authenticated' - ) - WITH CHECK ( - (SELECT auth.role()) = 'authenticated' - ); - --- Function to add first status -CREATE FUNCTION public.handle_first_status() -RETURNS TRIGGER -SET search_path = '' -AS $$ -BEGIN - INSERT INTO public.statuses (user_id, updated_by_id, status) - VALUES ( - NEW.id, - NEW.id, - 'Just joined!' - ); - RETURN NEW; -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Create a separate trigger for the status -CREATE TRIGGER on_auth_user_created_add_status - AFTER INSERT ON auth.users - FOR EACH ROW EXECUTE PROCEDURE public.handle_first_status(); - +-- enable realtime alter publication supabase_realtime add table profiles; alter publication supabase_realtime add table statuses; diff --git a/scripts/supabase/docker/docker-compose.dev.yml b/scripts/supabase/docker/docker-compose.dev.yml index 85cb604..263afc7 100644 --- a/scripts/supabase/docker/docker-compose.dev.yml +++ b/scripts/supabase/docker/docker-compose.dev.yml @@ -1,23 +1,23 @@ networks: - supabase-network: - name: supabase-network + techtracker-dev: + name: techtracker-dev driver: bridge ipam: config: - - subnet: 172.20.0.0/16 + - subnet: 172.21.0.0/16 services: studio: build: context: . dockerfile: studio/Dockerfile target: dev - networks: [supabase-network] + networks: [techtracker-dev] ports: - 8082:8082 mail: - container_name: supabase-mail + container_name: ttsbd-supabase-mail image: inbucket/inbucket:3.0.3 - networks: [supabase-network] + networks: [techtracker-dev] ports: - '2500:2500' # SMTP - '9000:9000' # web interface diff --git a/scripts/supabase/docker/docker-compose.s3.yml b/scripts/supabase/docker/docker-compose.s3.yml index 18c7866..c0cd03a 100644 --- a/scripts/supabase/docker/docker-compose.s3.yml +++ b/scripts/supabase/docker/docker-compose.s3.yml @@ -1,15 +1,16 @@ networks: - supabase-network: - name: supabase-network + techtracker-dev: + name: techtracker-dev driver: bridge ipam: config: - - subnet: 172.20.0.0/16 + - subnet: 172.21.0.0/16 services: minio: image: minio/minio - networks: [supabase-network] + container_name: ttsbd-supabase-minio + networks: [techtracker-dev] ports: - '9000:9000' - '9001:9001' @@ -27,7 +28,8 @@ services: minio-createbucket: image: minio/mc - networks: [supabase-network] + container_name: ttsbd-supabase-minio-createbucket + networks: [techtracker-dev] depends_on: minio: condition: service_healthy @@ -39,9 +41,9 @@ services: " storage: - container_name: supabase-storage + container_name: ttsbd-supabase-storage image: supabase/storage-api:v1.11.13 - networks: [supabase-network] + networks: [techtracker-dev] depends_on: db: # Disable this if you are using an external Postgres database @@ -91,9 +93,9 @@ services: - ./volumes/storage:/var/lib/storage:z imgproxy: - container_name: supabase-imgproxy + container_name: ttsbd-supabase-imgproxy image: darthsim/imgproxy:v3.8.0 - networks: [supabase-network] + networks: [techtracker-dev] healthcheck: test: [ "CMD", "imgproxy", "health" ] timeout: 5s diff --git a/scripts/supabase/docker/docker-compose.yml b/scripts/supabase/docker/docker-compose.yml index 2136295..c4ddcc1 100644 --- a/scripts/supabase/docker/docker-compose.yml +++ b/scripts/supabase/docker/docker-compose.yml @@ -5,22 +5,22 @@ # Destroy: docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml down -v --remove-orphans # Reset everything: ./reset.sh -name: techtracker +name: techtracker-dev networks: - techtracker: - name: techtracker + techtracker-dev: + name: techtracker-dev driver: bridge ipam: config: - - subnet: 172.19.0.0/16 + - subnet: 172.21.0.0/16 services: studio: - container_name: supabase-studio + container_name: ttsbd-supabase-studio image: supabase/studio:2025.05.19-sha-3487831 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped healthcheck: test: @@ -59,9 +59,9 @@ services: # NEXT_ANALYTICS_BACKEND_PROVIDER: bigquery kong: - container_name: supabase-kong + container_name: ttsbd-supabase-kong image: kong:2.8.1 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped ports: - ${KONG_HTTP_PORT}:8000/tcp @@ -88,9 +88,9 @@ services: entrypoint: bash -c 'eval "echo \"$$(cat ~/temp.yml)\"" > ~/kong.yml && /docker-entrypoint.sh kong docker-start' auth: - container_name: supabase-auth + container_name: ttsbd-supabase-auth image: supabase/gotrue:v2.172.1 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped healthcheck: test: @@ -197,9 +197,9 @@ services: # GOTRUE_HOOK_SEND_EMAIL_SECRETS: "v1,whsec_VGhpcyBpcyBhbiBleGFtcGxlIG9mIGEgc2hvcnRlciBCYXNlNjQgc3RyaW5n" rest: - container_name: supabase-rest + container_name: ttsbd-supabase-rest image: postgrest/postgrest:v12.2.12 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped depends_on: db: @@ -222,9 +222,9 @@ services: realtime: # This container name looks inconsistent but is correct because realtime constructs tenant id by parsing the subdomain - container_name: realtime-dev.supabase-realtime + container_name: ttsbd-realtime-dev.supabase-realtime image: supabase/realtime:v2.34.47 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped depends_on: db: @@ -268,9 +268,9 @@ services: # To use S3 backed storage: docker compose -f docker-compose.yml -f docker-compose.s3.yml up storage: - container_name: supabase-storage + container_name: ttsbd-supabase-storage image: supabase/storage-api:v1.22.17 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped volumes: - ./volumes/storage:/var/lib/storage:z @@ -312,9 +312,9 @@ services: IMGPROXY_URL: http://imgproxy:5001 imgproxy: - container_name: supabase-imgproxy + container_name: ttsbd-supabase-imgproxy image: darthsim/imgproxy:v3.8.0 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped volumes: - ./volumes/storage:/var/lib/storage:z @@ -335,9 +335,9 @@ services: IMGPROXY_ENABLE_WEBP_DETECTION: ${IMGPROXY_ENABLE_WEBP_DETECTION} meta: - container_name: supabase-meta + container_name: ttsbd-supabase-meta image: supabase/postgres-meta:v0.89.0 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped depends_on: db: @@ -354,9 +354,9 @@ services: PG_META_DB_PASSWORD: ${POSTGRES_PASSWORD} functions: - container_name: supabase-edge-functions + container_name: ttsbd-supabase-edge-functions image: supabase/edge-runtime:v1.67.4 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped volumes: - ./volumes/functions:/home/deno/functions:Z @@ -379,12 +379,12 @@ services: ] analytics: - container_name: supabase-analytics + container_name: ttsbd-supabase-analytics image: supabase/logflare:1.12.0 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped - ports: - - 4000:4000 + #ports: + #- 4000:4000 # Uncomment to use Big Query backend for analytics # volumes: # - type: bind @@ -428,9 +428,9 @@ services: # Comment out everything below this point if you are using an external Postgres database db: - container_name: supabase-db + container_name: ttsbd-supabase-db image: supabase/postgres:15.8.1.060 - networks: [techtracker] + networks: [techtracker-dev] ports: - ${POSTGRES_PORT}:${POSTGRES_PORT} restart: unless-stopped @@ -490,9 +490,9 @@ services: ] vector: - container_name: supabase-vector + container_name: ttsbd-supabase-vector image: timberio/vector:0.28.1-alpine - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped volumes: - ./volumes/logs/vector.yml:/etc/vector/vector.yml:ro,z @@ -522,9 +522,9 @@ services: # Update the DATABASE_URL if you are using an external Postgres database supavisor: - container_name: supabase-pooler + container_name: ttsbd-supabase-pooler image: supabase/supavisor:2.5.1 - networks: [techtracker] + networks: [techtracker-dev] restart: unless-stopped ports: #- ${POSTGRES_PORT}:5432 @@ -576,4 +576,4 @@ services: volumes: db-config: - name: techtracker-config + name: techtracker-dev-config