diff --git a/packages/supabase/bitnami-values.yaml b/packages/supabase/bitnami-values.yaml index 2577ebfd7..db07bdca1 100644 --- a/packages/supabase/bitnami-values.yaml +++ b/packages/supabase/bitnami-values.yaml @@ -178,10 +178,23 @@ postgresql: enabled: ###ZARF_VAR_ENABLE_POSTGRES### image: tag: 15.1.1-debian-12-r24 + debug: true primary: resourcesPreset: "none" podLabels: sidecar.istio.io/inject: "false" + initdb: + scripts: + 0000000000000000_migrate.sh: | + ###ZARF_VAR_MIGRATION_SCRIPT### + + 20240322174520_api_sql_schema.sql: | + ###ZARF_VAR_API_SQL_SCHEMA### + + 20240322174521_ui_sql_schema.sql: | + ###ZARF_VAR_UI_SQL_SCHEMA### + + commonAnnotations: helm.sh/resource-policy: keep ## @param postgresql.postgresqlSharedPreloadLibraries Set the shared_preload_libraries parameter in postgresql.conf diff --git a/packages/supabase/migrations/20240322174520_api_sql_schema.sql b/packages/supabase/migrations/20240322174520_api_sql_schema.sql new file mode 100644 index 000000000..25d8f92bf --- /dev/null +++ b/packages/supabase/migrations/20240322174520_api_sql_schema.sql @@ -0,0 +1,18 @@ +-- Create a table to store the OpenAI File Objects +create table + file_objects ( + id uuid primary key DEFAULT uuid_generate_v4(), + bytes int, + created_at bigint, + filename text, + object text, + purpose text, + status text, + status_details text + ); + +-- storage bucket for the files +insert into storage.buckets + (id, name, public) +values + ('file_bucket', 'files', true); diff --git a/packages/supabase/migrations/20240322174521_ui_sql_schema.sql b/packages/supabase/migrations/20240322174521_ui_sql_schema.sql new file mode 100644 index 000000000..ce4438a5b --- /dev/null +++ b/packages/supabase/migrations/20240322174521_ui_sql_schema.sql @@ -0,0 +1,188 @@ +create table conversations ( + id uuid primary key DEFAULT uuid_generate_v4(), + user_id uuid references auth.users not null, + label text, + inserted_at timestamp with time zone default timezone('utc'::text, now()) not null +); + + +create table messages ( + id uuid primary key DEFAULT uuid_generate_v4(), + user_id uuid references auth.users not null, + conversation_id uuid references conversations on delete cascade not null, + role text check (role in ('system', 'user', 'assistant', 'function', 'data', 'tool')), + content text, + inserted_at timestamp with time zone default timezone('utc'::text, now()) not null +); + +-- Create a table for public profiles +create table profiles ( + id uuid references auth.users not null primary key, + updated_at timestamp with time zone, + username text unique, + full_name text, + avatar_url text, + website text, + + constraint username_length check (char_length(username) >= 3) +); + +alter table conversations enable row level security; + +alter table messages enable row level security; + +alter table profiles enable row level security; + +-- Policies for conversations +create policy "Individuals can create conversations." on conversations for + insert with check (auth.uid() = user_id); +create policy "Individuals can view their own conversations. " on conversations for + select using (auth.uid() = user_id); +create policy "Individuals can update their own conversations." on conversations for + update using (auth.uid() = user_id); +create policy "Individuals can delete their own conversations." on conversations for + delete using (auth.uid() = user_id); + +-- Policies for messages +create policy "Individuals can view their own messages." on messages for + select using (auth.uid() = user_id); +create policy "Individuals can create messages." on messages for + insert with check (auth.uid() = user_id); +create policy "Individuals can update their own messages." on messages for + update using (auth.uid() = user_id); +create policy "Individuals can delete their own messages." on messages for + delete using (auth.uid() = user_id); + +-- Policies for profiles +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 (auth.uid() = id); + +create policy "Users can update own profile." on profiles + for update using (auth.uid() = id); + +-- Set up access controls for storage. +-- See https://supabase.com/docs/guides/storage/security/access-control#policy-examples for more details. +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 their own avatar." on storage.objects + for update using (auth.uid() = owner) with check (bucket_id = 'avatars'); + + +-- 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. +create function public.handle_new_user() +returns trigger as $$ +begin + insert into public.profiles (id, full_name, avatar_url) + values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url'); + return new; +end; +$$ language plpgsql security definer; +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'); + +alter table conversations enable row level security; + +alter table messages enable row level security; + +alter table profiles enable row level security; + +-- Policies for conversations +create policy "Individuals can create conversations." on conversations for + insert with check (auth.uid() = user_id); +create policy "Individuals can view their own conversations. " on conversations for + select using (auth.uid() = user_id); +create policy "Individuals can update their own conversations." on conversations for + update using (auth.uid() = user_id); +create policy "Individuals can delete their own conversations." on conversations for + delete using (auth.uid() = user_id); + +-- Policies for messages +create policy "Individuals can view their own messages." on messages for + select using (auth.uid() = user_id); +create policy "Individuals can create messages." on messages for + insert with check (auth.uid() = user_id); +create policy "Individuals can update their own messages." on messages for + update using (auth.uid() = user_id); +create policy "Individuals can delete their own messages." on messages for + delete using (auth.uid() = user_id); + +-- Policies for profiles +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 (auth.uid() = id); + +create policy "Users can update own profile." on profiles + for update using (auth.uid() = id); + +-- Set up access controls for storage. +-- See https://supabase.com/docs/guides/storage/security/access-control#policy-examples for more details. +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 their own avatar." on storage.objects + for update using (auth.uid() = owner) with check (bucket_id = 'avatars'); + + +-- Policies for assistants +CREATE POLICY "Individuals can view their own assistants." ON assistants +FOR SELECT USING ((metadata ->> 'created_by') = auth.uid()::text); +create policy "Individuals can create assistants." on assistants for + insert with check ((metadata ->> 'created_by') = auth.uid()::text); +create policy "Individuals can update their own assistants." on assistants for +update using ((metadata ->> 'created_by') = auth.uid()::text); +create policy "Individuals can delete their own assistants." on assistants for + delete using ((metadata ->> 'created_by') = auth.uid()::text); + + +-- 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. +create function public.handle_new_user() +returns trigger as $$ +begin + insert into public.profiles (id, full_name, avatar_url) + values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url'); + return new; +end; +$$ language plpgsql security definer; +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 TABLE Assistants ( + id uuid PRIMARY KEY DEFAULT uuid_generate_v4(), + object text CHECK (object in ('assistant')), + name VARCHAR(255), + description VARCHAR(512), + model VARCHAR(255) NOT NULL, + instructions TEXT, + tools jsonb, + tool_resources jsonb, + metadata jsonb, + temperature FLOAT, + top_p FLOAT, + response_format jsonb, + created_at timestamp with time zone default timezone('utc'::text, now()) not null +); diff --git a/packages/supabase/migrations/migrate.sh b/packages/supabase/migrations/migrate.sh new file mode 100644 index 000000000..d9ecfa65c --- /dev/null +++ b/packages/supabase/migrations/migrate.sh @@ -0,0 +1,43 @@ + #!/bin/bash + # Copyright VMware, Inc. + # SPDX-License-Identifier: APACHE-2.0 + + # shellcheck disable=SC1090,SC1091 + set -eu + + . /opt/bitnami/scripts/libpostgresql.sh + . /opt/bitnami/scripts/postgresql-env.sh + + ## + ## Script adapted from upstream migrate.sh + ## https://github.com/supabase/postgres/blob/develop/migrations/db/migrate.sh + ## + + export PGDATABASE="${POSTGRESQL_DB:-postgres}" + export PGHOST="${POSTGRES_HOST:-localhost}" + export PGPORT="${POSTGRESQL_PORT_NUMBER:-5432}" + if [[ "$POSTGRESQL_USERNAME" = "postgres" ]]; then + export PGPASSWORD="${POSTGRESQL_PASSWORD:-}" + else + export PGPASSWORD="${POSTGRESQL_POSTGRES_PASSWORD:-}" + fi + + for sql in /opt/bitnami/supabase-postgres/migrations/*.sql; do + echo "$0: running $sql" + psql -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U postgres -f "$sql" + done + + for sql in /opt/bitnami/supabase-postgres/migrations/db/init-scripts/*.sql; do + echo "$0: running $sql" + psql -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U postgres -f "$sql" + done + echo "Configuring supabase_admin user" + psql -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U postgres -c "ALTER USER supabase_admin WITH PASSWORD '$PGPASSWORD'" + # run migrations as super user - postgres user demoted in post-setup + for sql in /opt/bitnami/supabase-postgres/migrations/db/migrations/*.sql; do + echo "$0: running $sql" + psql -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U supabase_admin -f "$sql" + done + + # once done with everything, reset stats from init + psql -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U supabase_admin -c 'SELECT extensions.pg_stat_statements_reset(); SELECT pg_stat_reset();' || true diff --git a/packages/supabase/zarf.yaml b/packages/supabase/zarf.yaml index 2acebddc3..61fcf9f10 100644 --- a/packages/supabase/zarf.yaml +++ b/packages/supabase/zarf.yaml @@ -21,6 +21,19 @@ constants: value: "https://keycloak.admin.uds.dev/realms/uds" variables: + - name: UI_SQL_SCHEMA + type: file + default: "migrations/20240322174521_ui_sql_schema.sql" + autoIndent: true + - name: API_SQL_SCHEMA + type: file + default: "migrations/20240322174520_api_sql_schema.sql" + autoIndent: true + - name: MIGRATION_SCRIPT + type: file + default: "migrations/migrate.sh" + autoIndent: true + - name: ENABLE_AUTH description: 'Enable Supabases built-in authentication and authorization parts' default: "true" @@ -32,10 +45,10 @@ variables: default: "true" - name: ENABLE_REST description: 'Enable the autogenerated high level rest API for interacting with the database' - default: "true" + default: "true" - name: ENABLE_STORAGE description: 'Enable the Supabase object store' - default: "true" + default: "true" - name: ENABLE_STUDIO description: 'Enable the dashboard for managing Supabase, this dashboard depends on and sits atop other Supabase components' default: "true" @@ -95,6 +108,13 @@ components: - docker.io/bitnami/supabase-storage:0.48.4-debian-12-r0 - docker.io/bitnami/supabase-studio:0.24.3-debian-12-r0 - docker.io/bitnami/kong:3.6.1-debian-12-r13 + files: + - source: migrations/migrate.sh + target: migrations/migrate.sh + - source: migrations/20240322174521_ui_sql_schema.sql + target: migrations/20240322174521_ui_sql_schema.sql + - source: migrations/20240322174520_api_sql_schema.sql + target: migrations/20240322174520_api_sql_schema.sql - name: supabase-post-process description: "Perform necessary post processing here" required: true @@ -114,4 +134,4 @@ components: - name: supabase-manifests namespace: leapfrogai files: - - "manifests/declarative-conf-configmap.yaml" \ No newline at end of file + - "manifests/declarative-conf-configmap.yaml"