reset sb local environment

This commit is contained in:
Jordi Enric
2024-05-03 03:14:17 +02:00
parent ce59e46502
commit bc34355133
13 changed files with 979 additions and 3 deletions
+4
View File
@@ -0,0 +1,4 @@
# Supabase
.branches
.temp
.env
+149
View File
@@ -0,0 +1,149 @@
# A string used to distinguish different Supabase projects on the same host. Defaults to the
# working directory name when running `supabase init`.
project_id = "zenblog"
[api]
enabled = true
# Port to use for the API URL.
port = 54321
# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API
# endpoints. public and storage are always included.
schemas = ["public", "storage", "graphql_public"]
# Extra schemas to add to the search_path of every request. public is always included.
extra_search_path = ["public", "extensions"]
# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size
# for accidental or malicious requests.
max_rows = 1000
[db]
# Port to use for the local database URL.
port = 54322
# Port used by db diff command to initialize the shadow database.
shadow_port = 54320
# The database major version to use. This has to be the same as your remote database's. Run `SHOW
# server_version;` on the remote database to check.
major_version = 15
[db.pooler]
enabled = false
# Port to use for the local connection pooler.
port = 54329
# Specifies when a server connection can be reused by other clients.
# Configure one of the supported pooler modes: `transaction`, `session`.
pool_mode = "transaction"
# How many server connections to allow per user/database pair.
default_pool_size = 20
# Maximum number of client connections allowed.
max_client_conn = 100
[realtime]
enabled = true
# Bind realtime via either IPv4 or IPv6. (default: IPv6)
# ip_version = "IPv6"
[studio]
enabled = true
# Port to use for Supabase Studio.
port = 54323
# External URL of the API server that frontend connects to.
api_url = "http://127.0.0.1"
# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they
# are monitored, and you can view the emails that would have been sent from the web interface.
[inbucket]
enabled = true
# Port to use for the email testing server web interface.
port = 54324
# Uncomment to expose additional ports for testing user applications that send emails.
# smtp_port = 54325
# pop3_port = 54326
[storage]
enabled = true
# The maximum file size allowed (e.g. "5MB", "500KB").
file_size_limit = "50MiB"
[auth]
enabled = true
# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used
# in emails.
site_url = "http://127.0.0.1:3000"
# A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
additional_redirect_urls = ["https://127.0.0.1:3000"]
# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week).
jwt_expiry = 3600
# If disabled, the refresh token will never expire.
enable_refresh_token_rotation = true
# Allows refresh tokens to be reused after expiry, up to the specified interval in seconds.
# Requires enable_refresh_token_rotation = true.
refresh_token_reuse_interval = 10
# Allow/disallow new user signups to your project.
enable_signup = true
[auth.email]
# Allow/disallow new user signups via email to your project.
enable_signup = true
# If enabled, a user will be required to confirm any email change on both the old, and new email
# addresses. If disabled, only the new email is required to confirm.
double_confirm_changes = true
# If enabled, users need to confirm their email address before signing in.
enable_confirmations = true
# Uncomment to customize email template
# [auth.email.template.invite]
# subject = "You have been invited"
# content_path = "./supabase/templates/invite.html"
[auth.sms]
# Allow/disallow new user signups via SMS to your project.
enable_signup = true
# If enabled, users need to confirm their phone number before signing in.
enable_confirmations = false
# Template for sending OTP to users
template = "Your code is {{ .Code }} ."
# Use pre-defined map of phone number to OTP for testing.
[auth.sms.test_otp]
# 4152127777 = "123456"
# Configure one of the supported SMS providers: `twilio`, `twilio_verify`, `messagebird`, `textlocal`, `vonage`.
[auth.sms.twilio]
enabled = false
account_sid = ""
message_service_sid = ""
# DO NOT commit your Twilio auth token to git. Use environment variable substitution instead:
auth_token = "env(SUPABASE_AUTH_SMS_TWILIO_AUTH_TOKEN)"
# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,
# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin`, `notion`, `twitch`,
# `twitter`, `slack`, `spotify`, `workos`, `zoom`.
[auth.external.apple]
enabled = false
client_id = ""
# DO NOT commit your OAuth provider secret to git. Use environment variable substitution instead:
secret = "env(SUPABASE_AUTH_EXTERNAL_APPLE_SECRET)"
# Overrides the default auth redirectUrl.
redirect_uri = ""
# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure,
# or any other third-party OIDC providers.
url = ""
[analytics]
enabled = false
port = 54327
vector_port = 54328
# Configure one of the supported backends: `postgres`, `bigquery`.
backend = "postgres"
# Experimental features may be deprecated any time
[experimental]
# Configures Postgres storage engine to use OrioleDB (S3)
orioledb_version = ""
# Configures S3 bucket URL, eg. <bucket>.s3-accelerate.amazonaws.com
s3_host = "env(S3_HOST)"
# Configures S3 bucket region, eg. us-east-1
s3_region = "env(S3_REGION)"
# Configures AWS_ACCESS_KEY_ID for S3 bucket
s3_access_key = "env(S3_ACCESS_KEY)"
# Configures AWS_SECRET_ACCESS_KEY for S3 bucket
s3_secret_key = "env(S3_SECRET_KEY)"
View File
+13 -3
View File
@@ -40,6 +40,8 @@ max_client_conn = 100
enabled = true
# Bind realtime via either IPv4 or IPv6. (default: IPv6)
# ip_version = "IPv6"
# The maximum length in bytes of HTTP request headers. (default: 4096)
# max_header_length = 4096
[studio]
enabled = true
@@ -79,6 +81,8 @@ enable_refresh_token_rotation = true
refresh_token_reuse_interval = 10
# Allow/disallow new user signups to your project.
enable_signup = true
# Allow/disallow testing manual linking of accounts
enable_manual_linking = false
[auth.email]
# Allow/disallow new user signups via email to your project.
@@ -87,7 +91,7 @@ enable_signup = true
# addresses. If disabled, only the new email is required to confirm.
double_confirm_changes = true
# If enabled, users need to confirm their email address before signing in.
enable_confirmations = true
enable_confirmations = false
# Uncomment to customize email template
# [auth.email.template.invite]
@@ -106,6 +110,12 @@ template = "Your code is {{ .Code }} ."
[auth.sms.test_otp]
# 4152127777 = "123456"
# This hook runs before a token is issued and allows you to add additional claims based on the authentication method used.
[auth.hook.custom_access_token]
# enabled = true
# uri = "pg-functions://<database>/<schema>/<hook_name>"
# Configure one of the supported SMS providers: `twilio`, `twilio_verify`, `messagebird`, `textlocal`, `vonage`.
[auth.sms.twilio]
enabled = false
@@ -115,7 +125,7 @@ message_service_sid = ""
auth_token = "env(SUPABASE_AUTH_SMS_TWILIO_AUTH_TOKEN)"
# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,
# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin`, `notion`, `twitch`,
# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin_oidc`, `notion`, `twitch`,
# `twitter`, `slack`, `spotify`, `workos`, `zoom`.
[auth.external.apple]
enabled = false
@@ -139,7 +149,7 @@ backend = "postgres"
[experimental]
# Configures Postgres storage engine to use OrioleDB (S3)
orioledb_version = ""
# Configures S3 bucket URL, eg. <bucket>.s3-accelerate.amazonaws.com
# Configures S3 bucket URL, eg. <bucket_name>.s3-<region>.amazonaws.com
s3_host = "env(S3_HOST)"
# Configures S3 bucket region, eg. us-east-1
s3_region = "env(S3_REGION)"
@@ -0,0 +1,732 @@
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
CREATE EXTENSION IF NOT EXISTS "pg_net" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "pgsodium" WITH SCHEMA "pgsodium";
CREATE SCHEMA IF NOT EXISTS "stripe";
ALTER SCHEMA "stripe" OWNER TO "postgres";
CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "pgcrypto" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "pgjwt" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "supabase_vault" WITH SCHEMA "vault";
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA "extensions";
CREATE OR REPLACE FUNCTION "public"."generate_random_string"("length" integer) RETURNS "text"
LANGUAGE "plpgsql"
AS $$
DECLARE
chars text := 'abcdefghijklmnopqrstuvwxyz';
result text := '';
i int := 1;
BEGIN
FOR i IN 1..length LOOP
result := result || substr(chars, floor(random() * length(chars) + 1)::int, 1);
END LOOP;
RETURN result;
END;
$$;
ALTER FUNCTION "public"."generate_random_string"("length" integer) OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."generate_slug"("title" "text") RETURNS "text"
LANGUAGE "plpgsql"
AS $$
DECLARE
slug_text text;
normalized_title text;
BEGIN
-- Normalize the title by removing special characters and converting to lowercase
normalized_title := lower(regexp_replace(title, '[^\w\s]', '', 'g'));
-- Replace spaces with dashes to create the slug
slug_text := regexp_replace(normalized_title, '\s+', '-', 'g');
-- Ensure the slug is unique in the articles table
WHILE EXISTS(SELECT 1 FROM articles WHERE slug = slug_text) LOOP
slug_text := slug_text || '-' || substring(md5(random()::text), 1, 4);
END LOOP;
RETURN slug_text;
END;
$$;
ALTER FUNCTION "public"."generate_slug"("title" "text") OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."is_blog_owner"("blog_id" "uuid", "given_user_id" "uuid") RETURNS boolean
LANGUAGE "plpgsql"
AS $$
BEGIN
RETURN EXISTS (
SELECT 1
FROM public.blogs
WHERE id = blog_id AND user_id = given_user_id
);
END;
$$;
ALTER FUNCTION "public"."is_blog_owner"("blog_id" "uuid", "given_user_id" "uuid") OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."requesting_user_id"() RETURNS "text"
LANGUAGE "sql" STABLE
AS $$
select nullif(current_setting('request.jwt.claims', true)::json->>'sub', '')::text;
$$;
ALTER FUNCTION "public"."requesting_user_id"() OWNER TO "postgres";
SET default_tablespace = '';
SET default_table_access_method = "heap";
CREATE TABLE IF NOT EXISTS "public"."blog_tags" (
"id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
"blog_id" "uuid" NOT NULL,
"name" "text" NOT NULL,
"slug" "text" NOT NULL,
"created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"description" "text"
);
ALTER TABLE "public"."blog_tags" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."blogs" (
"id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
"created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"title" "text" NOT NULL,
"emoji" "text" NOT NULL,
"description" "text",
"user_id" "uuid" DEFAULT "auth"."uid"() NOT NULL,
"slug" "text" NOT NULL,
CONSTRAINT "blogs_slug_check" CHECK (("length"("slug") < 50))
);
ALTER TABLE "public"."blogs" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."feedback" (
"id" bigint NOT NULL,
"created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"feedback" "text",
"user_email" "text"
);
ALTER TABLE "public"."feedback" OWNER TO "postgres";
ALTER TABLE "public"."feedback" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY (
SEQUENCE NAME "public"."feedback_id_seq"
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1
);
CREATE TABLE IF NOT EXISTS "public"."homepage_signup" (
"id" bigint NOT NULL,
"created_at" timestamp with time zone DEFAULT "now"(),
"name" "text" NOT NULL,
"email" "text" NOT NULL
);
ALTER TABLE "public"."homepage_signup" OWNER TO "postgres";
ALTER TABLE "public"."homepage_signup" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY (
SEQUENCE NAME "public"."homepage_signup_id_seq"
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1
);
CREATE TABLE IF NOT EXISTS "public"."post_tags" (
"id" bigint NOT NULL,
"created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"post_id" "uuid" NOT NULL,
"tag_id" "uuid" NOT NULL,
"blog_id" "uuid" NOT NULL
);
ALTER TABLE "public"."post_tags" OWNER TO "postgres";
ALTER TABLE "public"."post_tags" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY (
SEQUENCE NAME "public"."post_tags_id_seq"
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1
);
CREATE OR REPLACE VIEW "public"."post_tags_with_tags" AS
SELECT "pt"."id",
"pt"."created_at",
"pt"."post_id",
"pt"."tag_id",
"bt"."name" AS "tag_name",
"bt"."slug" AS "tag_slug",
"bt"."description" AS "tag_description"
FROM ("public"."post_tags" "pt"
LEFT JOIN "public"."blog_tags" "bt" ON (("pt"."tag_id" = "bt"."id")));
ALTER TABLE "public"."post_tags_with_tags" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."posts" (
"created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"user_id" "uuid" DEFAULT "auth"."uid"() NOT NULL,
"blog_id" "uuid" NOT NULL,
"title" "text" NOT NULL,
"published" boolean DEFAULT false NOT NULL,
"content" "jsonb" DEFAULT '{}'::"jsonb" NOT NULL,
"updated_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"slug" "text" NOT NULL,
"id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
"cover_image" "text",
"metadata" "jsonb"[],
"deleted" boolean DEFAULT false NOT NULL,
"published_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."posts" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."subscriptions" (
"created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"user_id" "uuid" NOT NULL,
"status" "text" NOT NULL,
"stripe_subscription_id" "text" NOT NULL,
"subscription" "jsonb" NOT NULL
);
ALTER TABLE "public"."subscriptions" OWNER TO "postgres";
CREATE OR REPLACE VIEW "public"."posts_with_blog_and_subscription_status" AS
SELECT "p"."created_at",
"p"."blog_id",
"p"."title",
"p"."published",
"p"."content",
"p"."updated_at",
"p"."slug",
"p"."id" AS "post_id",
"p"."cover_image",
"p"."metadata",
"p"."deleted",
COALESCE("array_agg"("bt"."name") FILTER (WHERE ("bt"."id" IS NOT NULL)), '{}'::"text"[]) AS "tags",
"s"."status" AS "subscription_status"
FROM (((("public"."posts" "p"
LEFT JOIN "public"."blogs" "b" ON (("p"."blog_id" = "b"."id")))
LEFT JOIN "public"."subscriptions" "s" ON (("b"."user_id" = "s"."user_id")))
LEFT JOIN "public"."post_tags" "pt" ON (("p"."id" = "pt"."post_id")))
LEFT JOIN "public"."blog_tags" "bt" ON (("pt"."tag_id" = "bt"."id")))
GROUP BY "p"."created_at", "p"."blog_id", "p"."title", "p"."published", "p"."content", "p"."updated_at", "p"."slug", "p"."id", "p"."cover_image", "p"."metadata", "p"."deleted", "p"."user_id", "s"."status"
ORDER BY "p"."created_at" DESC;
ALTER TABLE "public"."posts_with_blog_and_subscription_status" OWNER TO "postgres";
CREATE OR REPLACE VIEW "public"."posts_with_blog_and_subscription_status_v2" AS
SELECT "p"."created_at",
"p"."blog_id",
"p"."title",
"p"."published",
"p"."published_at",
"p"."content",
"p"."updated_at",
"p"."slug",
"p"."id" AS "post_id",
"p"."cover_image",
"p"."metadata",
"p"."deleted",
COALESCE("array_agg"("bt"."name") FILTER (WHERE ("bt"."id" IS NOT NULL)), '{}'::"text"[]) AS "tags",
"s"."status" AS "subscription_status"
FROM (((("public"."posts" "p"
LEFT JOIN "public"."blogs" "b" ON (("p"."blog_id" = "b"."id")))
LEFT JOIN "public"."subscriptions" "s" ON (("b"."user_id" = "s"."user_id")))
LEFT JOIN "public"."post_tags" "pt" ON (("p"."id" = "pt"."post_id")))
LEFT JOIN "public"."blog_tags" "bt" ON (("pt"."tag_id" = "bt"."id")))
GROUP BY "p"."created_at", "p"."blog_id", "p"."title", "p"."published", "p"."published_at", "p"."content", "p"."updated_at", "p"."slug", "p"."id", "p"."cover_image", "p"."metadata", "p"."deleted", "p"."user_id", "s"."status"
ORDER BY "p"."created_at" DESC;
ALTER TABLE "public"."posts_with_blog_and_subscription_status_v2" OWNER TO "postgres";
CREATE OR REPLACE VIEW "public"."posts_with_tags" AS
SELECT "p"."created_at",
"p"."blog_id",
"p"."title",
"p"."published",
"p"."content",
"p"."updated_at",
"p"."slug",
"p"."id" AS "post_id",
"p"."cover_image",
"p"."metadata",
"p"."deleted",
COALESCE("array_agg"("bt"."name") FILTER (WHERE ("bt"."id" IS NOT NULL)), '{}'::"text"[]) AS "tags"
FROM (("public"."posts" "p"
LEFT JOIN "public"."post_tags" "pt" ON (("p"."id" = "pt"."post_id")))
LEFT JOIN "public"."blog_tags" "bt" ON (("pt"."tag_id" = "bt"."id")))
GROUP BY "p"."created_at", "p"."blog_id", "p"."title", "p"."published", "p"."content", "p"."updated_at", "p"."slug", "p"."id", "p"."cover_image", "p"."metadata", "p"."deleted", "p"."user_id"
ORDER BY "p"."created_at" DESC;
ALTER TABLE "public"."posts_with_tags" OWNER TO "postgres";
CREATE OR REPLACE VIEW "public"."posts_with_tags_v2" AS
SELECT "p"."created_at",
"p"."blog_id",
"p"."title",
"p"."published",
"p"."content",
"p"."updated_at",
"p"."slug",
"p"."id" AS "post_id",
"p"."cover_image",
"p"."metadata",
"p"."deleted",
"p"."published_at",
COALESCE("array_agg"("bt"."name") FILTER (WHERE ("bt"."id" IS NOT NULL)), '{}'::"text"[]) AS "tags"
FROM (("public"."posts" "p"
LEFT JOIN "public"."post_tags" "pt" ON (("p"."id" = "pt"."post_id")))
LEFT JOIN "public"."blog_tags" "bt" ON (("pt"."tag_id" = "bt"."id")))
GROUP BY "p"."created_at", "p"."blog_id", "p"."title", "p"."published", "p"."content", "p"."updated_at", "p"."slug", "p"."id", "p"."cover_image", "p"."metadata", "p"."deleted", "p"."user_id", "p"."published_at"
ORDER BY "p"."created_at" DESC;
ALTER TABLE "public"."posts_with_tags_v2" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."prices" (
"id" bigint NOT NULL,
"created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"price" "jsonb" NOT NULL,
"stripe_price_id" "text" NOT NULL
);
ALTER TABLE "public"."prices" OWNER TO "postgres";
ALTER TABLE "public"."prices" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY (
SEQUENCE NAME "public"."prices_id_seq"
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1
);
CREATE TABLE IF NOT EXISTS "public"."products" (
"id" bigint NOT NULL,
"created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"product" "jsonb" NOT NULL,
"stripe_product_id" "text" NOT NULL
);
ALTER TABLE "public"."products" OWNER TO "postgres";
ALTER TABLE "public"."products" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY (
SEQUENCE NAME "public"."products_id_seq"
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1
);
CREATE OR REPLACE VIEW "public"."public_posts_v1" AS
SELECT "p"."created_at",
"p"."blog_id",
"p"."title",
"p"."published",
"p"."published_at",
"p"."content",
"p"."updated_at",
"p"."slug",
"p"."id" AS "post_id",
"p"."cover_image",
"p"."metadata",
"p"."deleted",
COALESCE("array_agg"("bt"."name") FILTER (WHERE ("bt"."id" IS NOT NULL)), '{}'::"text"[]) AS "tags",
"s"."status" AS "subscription_status",
"b"."slug" AS "blog_slug"
FROM (((("public"."posts" "p"
LEFT JOIN "public"."blogs" "b" ON (("p"."blog_id" = "b"."id")))
LEFT JOIN "public"."subscriptions" "s" ON (("b"."user_id" = "s"."user_id")))
LEFT JOIN "public"."post_tags" "pt" ON (("p"."id" = "pt"."post_id")))
LEFT JOIN "public"."blog_tags" "bt" ON (("pt"."tag_id" = "bt"."id")))
GROUP BY "p"."created_at", "p"."blog_id", "p"."title", "p"."published", "p"."published_at", "p"."content", "p"."updated_at", "p"."slug", "p"."id", "p"."cover_image", "p"."metadata", "p"."deleted", "p"."user_id", "s"."status", "b"."slug"
ORDER BY "p"."created_at" DESC;
ALTER TABLE "public"."public_posts_v1" OWNER TO "postgres";
CREATE OR REPLACE VIEW "public"."tag_usage_count_v2" AS
SELECT "bt"."id" AS "tag_id",
"bt"."blog_id",
"bt"."name" AS "tag_name",
"bt"."slug",
"bt"."created_at",
"bt"."updated_at",
"count"("pt"."post_id") AS "post_count"
FROM ("public"."blog_tags" "bt"
LEFT JOIN "public"."post_tags" "pt" ON (("bt"."id" = "pt"."tag_id")))
GROUP BY "bt"."id", "bt"."blog_id", "bt"."name", "bt"."slug", "bt"."created_at", "bt"."updated_at";
ALTER TABLE "public"."tag_usage_count_v2" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."teams" (
"created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"owner_id" "uuid",
"name" "text" NOT NULL,
"ref" "text" DEFAULT "public"."generate_random_string"(20),
"id" bigint NOT NULL
);
ALTER TABLE "public"."teams" OWNER TO "postgres";
ALTER TABLE "public"."teams" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY (
SEQUENCE NAME "public"."teams_id_seq"
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1
);
CREATE OR REPLACE VIEW "public"."users" AS
SELECT "users"."instance_id",
"users"."id",
"users"."aud",
"users"."role",
"users"."email",
"users"."encrypted_password",
"users"."email_confirmed_at",
"users"."invited_at",
"users"."confirmation_token",
"users"."confirmation_sent_at",
"users"."recovery_token",
"users"."recovery_sent_at",
"users"."email_change_token_new",
"users"."email_change",
"users"."email_change_sent_at",
"users"."last_sign_in_at",
"users"."raw_app_meta_data",
"users"."raw_user_meta_data",
"users"."is_super_admin",
"users"."created_at",
"users"."updated_at",
"users"."phone",
"users"."phone_confirmed_at",
"users"."phone_change",
"users"."phone_change_token",
"users"."phone_change_sent_at",
"users"."confirmed_at",
"users"."email_change_token_current",
"users"."email_change_confirm_status",
"users"."banned_until",
"users"."reauthentication_token",
"users"."reauthentication_sent_at",
"users"."is_sso_user",
"users"."deleted_at"
FROM "auth"."users";
ALTER TABLE "public"."users" OWNER TO "postgres";
ALTER TABLE ONLY "public"."blogs"
ADD CONSTRAINT "blogs_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."blogs"
ADD CONSTRAINT "blogs_slug_key" UNIQUE ("slug");
ALTER TABLE ONLY "public"."blog_tags"
ADD CONSTRAINT "categories_blog_id_slug_key" UNIQUE ("blog_id", "slug");
ALTER TABLE ONLY "public"."blog_tags"
ADD CONSTRAINT "categories_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."feedback"
ADD CONSTRAINT "feedback_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."homepage_signup"
ADD CONSTRAINT "homepage_signup_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."post_tags"
ADD CONSTRAINT "post_categories_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."posts"
ADD CONSTRAINT "posts_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."prices"
ADD CONSTRAINT "prices_pkey" PRIMARY KEY ("id", "stripe_price_id");
ALTER TABLE ONLY "public"."prices"
ADD CONSTRAINT "prices_stripe_price_id_key" UNIQUE ("stripe_price_id");
ALTER TABLE ONLY "public"."products"
ADD CONSTRAINT "products_pkey" PRIMARY KEY ("id", "stripe_product_id");
ALTER TABLE ONLY "public"."products"
ADD CONSTRAINT "products_stripe_product_id_key" UNIQUE ("stripe_product_id");
ALTER TABLE ONLY "public"."subscriptions"
ADD CONSTRAINT "subscriptions_pkey" PRIMARY KEY ("stripe_subscription_id");
ALTER TABLE ONLY "public"."subscriptions"
ADD CONSTRAINT "subscriptions_stripe_subscription_id_key" UNIQUE ("stripe_subscription_id");
ALTER TABLE ONLY "public"."subscriptions"
ADD CONSTRAINT "subscriptions_user_id_key" UNIQUE ("user_id");
ALTER TABLE ONLY "public"."teams"
ADD CONSTRAINT "teams_id_key" UNIQUE ("id");
ALTER TABLE ONLY "public"."teams"
ADD CONSTRAINT "teams_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."teams"
ADD CONSTRAINT "teams_ref_key" UNIQUE ("ref");
ALTER TABLE ONLY "public"."post_tags"
ADD CONSTRAINT "unique_post_tag_blog_combination" UNIQUE ("post_id", "tag_id", "blog_id");
CREATE INDEX "posts_slug_blog_id_idx" ON "public"."posts" USING "btree" ("slug", "blog_id");
CREATE INDEX "posts_slug_idx" ON "public"."posts" USING "btree" ("slug");
CREATE UNIQUE INDEX "unique_slug_per_user_blog_constraint" ON "public"."posts" USING "btree" ("slug", "user_id", "blog_id");
ALTER TABLE ONLY "public"."blog_tags"
ADD CONSTRAINT "blog_tags_blog_id_fkey" FOREIGN KEY ("blog_id") REFERENCES "public"."blogs"("id") ON DELETE CASCADE;
ALTER TABLE ONLY "public"."blogs"
ADD CONSTRAINT "blogs_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id");
ALTER TABLE ONLY "public"."post_tags"
ADD CONSTRAINT "post_tags_blog_id_fkey" FOREIGN KEY ("blog_id") REFERENCES "public"."blogs"("id");
ALTER TABLE ONLY "public"."post_tags"
ADD CONSTRAINT "post_tags_post_id_fkey" FOREIGN KEY ("post_id") REFERENCES "public"."posts"("id");
ALTER TABLE ONLY "public"."post_tags"
ADD CONSTRAINT "post_tags_tag_id_fkey" FOREIGN KEY ("tag_id") REFERENCES "public"."blog_tags"("id");
ALTER TABLE ONLY "public"."posts"
ADD CONSTRAINT "posts_blog_id_fkey" FOREIGN KEY ("blog_id") REFERENCES "public"."blogs"("id") ON DELETE CASCADE;
ALTER TABLE ONLY "public"."posts"
ADD CONSTRAINT "public_posts_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id");
ALTER TABLE ONLY "public"."teams"
ADD CONSTRAINT "public_teams_owner_id_fkey" FOREIGN KEY ("owner_id") REFERENCES "auth"."users"("id");
ALTER TABLE ONLY "public"."subscriptions"
ADD CONSTRAINT "subscriptions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id");
CREATE POLICY "Enable INSERT access for all users" ON "public"."homepage_signup" FOR INSERT TO "anon" WITH CHECK (true);
CREATE POLICY "Enable insert for authenticated users only" ON "public"."feedback" FOR INSERT TO "authenticated" WITH CHECK (true);
CREATE POLICY "Enable insert for owners" ON "public"."teams" FOR INSERT TO "authenticated" WITH CHECK (("auth"."uid"() = "owner_id"));
CREATE POLICY "Enable read access for all users" ON "public"."blogs" FOR SELECT TO "anon" USING (true);
CREATE POLICY "Enable read access for all users" ON "public"."prices" FOR SELECT USING (true);
CREATE POLICY "Enable read access for all users" ON "public"."products" FOR SELECT USING (true);
CREATE POLICY "Enable read access for all users" ON "public"."teams" FOR SELECT USING (true);
CREATE POLICY "authed_read_posts" ON "public"."posts" FOR SELECT TO "authenticated" USING ("public"."is_blog_owner"("blog_id", "auth"."uid"()));
ALTER TABLE "public"."blog_tags" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."blogs" ENABLE ROW LEVEL SECURITY;
CREATE POLICY "delete_post_tag" ON "public"."post_tags" FOR DELETE TO "authenticated" USING ("public"."is_blog_owner"("blog_id", "auth"."uid"()));
CREATE POLICY "delete_tags" ON "public"."blog_tags" FOR DELETE USING ("public"."is_blog_owner"("blog_id", "auth"."uid"()));
ALTER TABLE "public"."feedback" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."homepage_signup" ENABLE ROW LEVEL SECURITY;
CREATE POLICY "insert_post_tag" ON "public"."post_tags" FOR INSERT TO "authenticated" WITH CHECK ("public"."is_blog_owner"("blog_id", "auth"."uid"()));
CREATE POLICY "insert_posts" ON "public"."posts" FOR INSERT TO "authenticated" WITH CHECK ("public"."is_blog_owner"("blog_id", "auth"."uid"()));
CREATE POLICY "insert_tags" ON "public"."blog_tags" FOR INSERT WITH CHECK ("public"."is_blog_owner"("blog_id", "auth"."uid"()));
ALTER TABLE "public"."post_tags" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."posts" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."prices" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."products" ENABLE ROW LEVEL SECURITY;
CREATE POLICY "read_post_tags" ON "public"."post_tags" FOR SELECT USING (true);
CREATE POLICY "read_posts" ON "public"."posts" FOR SELECT TO "anon" USING ((("published" = true) AND ("deleted" = false)));
CREATE POLICY "select subscription" ON "public"."subscriptions" FOR SELECT TO "authenticated" USING (("auth"."uid"() = "user_id"));
CREATE POLICY "select_categories_policy" ON "public"."blog_tags" FOR SELECT USING (true);
ALTER TABLE "public"."subscriptions" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."teams" ENABLE ROW LEVEL SECURITY;
CREATE POLICY "update_post_tags" ON "public"."post_tags" FOR UPDATE TO "authenticated" USING ("public"."is_blog_owner"("blog_id", "auth"."uid"())) WITH CHECK (true);
CREATE POLICY "update_posts" ON "public"."posts" FOR UPDATE TO "authenticated" USING ("public"."is_blog_owner"("blog_id", "auth"."uid"()));
CREATE POLICY "update_tags" ON "public"."blog_tags" FOR UPDATE USING ("public"."is_blog_owner"("blog_id", "auth"."uid"()));
CREATE POLICY "users can crud their blogs" ON "public"."blogs" TO "authenticated" USING (("auth"."uid"() = "user_id"));
ALTER PUBLICATION "supabase_realtime" OWNER TO "postgres";
REVOKE USAGE ON SCHEMA "public" FROM PUBLIC;
GRANT USAGE ON SCHEMA "public" TO "postgres";
GRANT USAGE ON SCHEMA "public" TO "anon";
GRANT USAGE ON SCHEMA "public" TO "authenticated";
GRANT USAGE ON SCHEMA "public" TO "service_role";
GRANT ALL ON FUNCTION "public"."generate_random_string"("length" integer) TO "anon";
GRANT ALL ON FUNCTION "public"."generate_random_string"("length" integer) TO "authenticated";
GRANT ALL ON FUNCTION "public"."generate_random_string"("length" integer) TO "service_role";
GRANT ALL ON FUNCTION "public"."generate_slug"("title" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."generate_slug"("title" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."generate_slug"("title" "text") TO "service_role";
GRANT ALL ON FUNCTION "public"."is_blog_owner"("blog_id" "uuid", "given_user_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."is_blog_owner"("blog_id" "uuid", "given_user_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."is_blog_owner"("blog_id" "uuid", "given_user_id" "uuid") TO "service_role";
GRANT ALL ON FUNCTION "public"."requesting_user_id"() TO "anon";
GRANT ALL ON FUNCTION "public"."requesting_user_id"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."requesting_user_id"() TO "service_role";
GRANT ALL ON TABLE "public"."blog_tags" TO "anon";
GRANT ALL ON TABLE "public"."blog_tags" TO "authenticated";
GRANT ALL ON TABLE "public"."blog_tags" TO "service_role";
GRANT ALL ON TABLE "public"."blogs" TO "anon";
GRANT ALL ON TABLE "public"."blogs" TO "authenticated";
GRANT ALL ON TABLE "public"."blogs" TO "service_role";
GRANT ALL ON TABLE "public"."feedback" TO "anon";
GRANT ALL ON TABLE "public"."feedback" TO "authenticated";
GRANT ALL ON TABLE "public"."feedback" TO "service_role";
GRANT ALL ON SEQUENCE "public"."feedback_id_seq" TO "anon";
GRANT ALL ON SEQUENCE "public"."feedback_id_seq" TO "authenticated";
GRANT ALL ON SEQUENCE "public"."feedback_id_seq" TO "service_role";
GRANT ALL ON TABLE "public"."homepage_signup" TO "anon";
GRANT ALL ON TABLE "public"."homepage_signup" TO "authenticated";
GRANT ALL ON TABLE "public"."homepage_signup" TO "service_role";
GRANT ALL ON SEQUENCE "public"."homepage_signup_id_seq" TO "anon";
GRANT ALL ON SEQUENCE "public"."homepage_signup_id_seq" TO "authenticated";
GRANT ALL ON SEQUENCE "public"."homepage_signup_id_seq" TO "service_role";
GRANT ALL ON TABLE "public"."post_tags" TO "anon";
GRANT ALL ON TABLE "public"."post_tags" TO "authenticated";
GRANT ALL ON TABLE "public"."post_tags" TO "service_role";
GRANT ALL ON SEQUENCE "public"."post_tags_id_seq" TO "anon";
GRANT ALL ON SEQUENCE "public"."post_tags_id_seq" TO "authenticated";
GRANT ALL ON SEQUENCE "public"."post_tags_id_seq" TO "service_role";
GRANT ALL ON TABLE "public"."post_tags_with_tags" TO "anon";
GRANT ALL ON TABLE "public"."post_tags_with_tags" TO "authenticated";
GRANT ALL ON TABLE "public"."post_tags_with_tags" TO "service_role";
GRANT ALL ON TABLE "public"."posts" TO "anon";
GRANT ALL ON TABLE "public"."posts" TO "authenticated";
GRANT ALL ON TABLE "public"."posts" TO "service_role";
GRANT ALL ON TABLE "public"."subscriptions" TO "anon";
GRANT ALL ON TABLE "public"."subscriptions" TO "authenticated";
GRANT ALL ON TABLE "public"."subscriptions" TO "service_role";
GRANT ALL ON TABLE "public"."posts_with_blog_and_subscription_status" TO "anon";
GRANT ALL ON TABLE "public"."posts_with_blog_and_subscription_status" TO "authenticated";
GRANT ALL ON TABLE "public"."posts_with_blog_and_subscription_status" TO "service_role";
GRANT ALL ON TABLE "public"."posts_with_blog_and_subscription_status_v2" TO "anon";
GRANT ALL ON TABLE "public"."posts_with_blog_and_subscription_status_v2" TO "authenticated";
GRANT ALL ON TABLE "public"."posts_with_blog_and_subscription_status_v2" TO "service_role";
GRANT ALL ON TABLE "public"."posts_with_tags" TO "anon";
GRANT ALL ON TABLE "public"."posts_with_tags" TO "authenticated";
GRANT ALL ON TABLE "public"."posts_with_tags" TO "service_role";
GRANT ALL ON TABLE "public"."posts_with_tags_v2" TO "anon";
GRANT ALL ON TABLE "public"."posts_with_tags_v2" TO "authenticated";
GRANT ALL ON TABLE "public"."posts_with_tags_v2" TO "service_role";
GRANT ALL ON TABLE "public"."prices" TO "anon";
GRANT ALL ON TABLE "public"."prices" TO "authenticated";
GRANT ALL ON TABLE "public"."prices" TO "service_role";
GRANT ALL ON SEQUENCE "public"."prices_id_seq" TO "anon";
GRANT ALL ON SEQUENCE "public"."prices_id_seq" TO "authenticated";
GRANT ALL ON SEQUENCE "public"."prices_id_seq" TO "service_role";
GRANT ALL ON TABLE "public"."products" TO "anon";
GRANT ALL ON TABLE "public"."products" TO "authenticated";
GRANT ALL ON TABLE "public"."products" TO "service_role";
GRANT ALL ON SEQUENCE "public"."products_id_seq" TO "anon";
GRANT ALL ON SEQUENCE "public"."products_id_seq" TO "authenticated";
GRANT ALL ON SEQUENCE "public"."products_id_seq" TO "service_role";
GRANT ALL ON TABLE "public"."public_posts_v1" TO "anon";
GRANT ALL ON TABLE "public"."public_posts_v1" TO "authenticated";
GRANT ALL ON TABLE "public"."public_posts_v1" TO "service_role";
GRANT ALL ON TABLE "public"."tag_usage_count_v2" TO "anon";
GRANT ALL ON TABLE "public"."tag_usage_count_v2" TO "authenticated";
GRANT ALL ON TABLE "public"."tag_usage_count_v2" TO "service_role";
GRANT ALL ON TABLE "public"."teams" TO "anon";
GRANT ALL ON TABLE "public"."teams" TO "authenticated";
GRANT ALL ON TABLE "public"."teams" TO "service_role";
GRANT ALL ON SEQUENCE "public"."teams_id_seq" TO "anon";
GRANT ALL ON SEQUENCE "public"."teams_id_seq" TO "authenticated";
GRANT ALL ON SEQUENCE "public"."teams_id_seq" TO "service_role";
GRANT ALL ON TABLE "public"."users" TO "anon";
GRANT ALL ON TABLE "public"."users" TO "authenticated";
GRANT ALL ON TABLE "public"."users" TO "service_role";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "service_role";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "service_role";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "service_role";
RESET ALL;
@@ -0,0 +1,81 @@
set check_function_bodies = off;
CREATE OR REPLACE FUNCTION storage.extension(name text)
RETURNS text
LANGUAGE plpgsql
AS $function$
DECLARE
_parts text[];
_filename text;
BEGIN
select string_to_array(name, '/') into _parts;
select _parts[array_length(_parts,1)] into _filename;
-- @todo return the last part instead of 2
return split_part(_filename, '.', 2);
END
$function$
;
CREATE OR REPLACE FUNCTION storage.filename(name text)
RETURNS text
LANGUAGE plpgsql
AS $function$
DECLARE
_parts text[];
BEGIN
select string_to_array(name, '/') into _parts;
return _parts[array_length(_parts,1)];
END
$function$
;
CREATE OR REPLACE FUNCTION storage.foldername(name text)
RETURNS text[]
LANGUAGE plpgsql
AS $function$
DECLARE
_parts text[];
BEGIN
select string_to_array(name, '/') into _parts;
return _parts[1:array_length(_parts,1)-1];
END
$function$
;
create policy "ALLOW ALL IN public 1ffg0oo_0"
on "storage"."objects"
as permissive
for select
to public
using (true);
create policy "ALLOW ALL IN public 1ffg0oo_1"
on "storage"."objects"
as permissive
for insert
to public
with check (true);
create policy "Allow owners to delete"
on "storage"."objects"
as permissive
for delete
to authenticated
using ((EXISTS ( SELECT blogs.id
FROM blogs
WHERE ((blogs.user_id = ( SELECT auth.uid() AS uid)) AND (split_part(objects.name, '/'::text, 1) = (blogs.id)::text)))));
create policy "Allow owners to insert"
on "storage"."objects"
as permissive
for insert
to authenticated
with check ((EXISTS ( SELECT blogs.id
FROM blogs
WHERE ((blogs.user_id = ( SELECT auth.uid() AS uid)) AND (split_part(objects.name, '/'::text, 1) = (blogs.id)::text)))));