From 488ee2583067cb092a773509f8dc992af8430c7c Mon Sep 17 00:00:00 2001 From: Abdurrahman Rajab Date: Thu, 29 Jun 2023 19:45:41 +0300 Subject: [PATCH 01/83] chore: enable insert --- .../PolicyEditorModal.constants.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/studio/components/interfaces/Auth/Policies/PolicyEditorModal/PolicyEditorModal.constants.ts b/studio/components/interfaces/Auth/Policies/PolicyEditorModal/PolicyEditorModal.constants.ts index a24711e35e9..fcd6e52a190 100644 --- a/studio/components/interfaces/Auth/Policies/PolicyEditorModal/PolicyEditorModal.constants.ts +++ b/studio/components/interfaces/Auth/Policies/PolicyEditorModal/PolicyEditorModal.constants.ts @@ -83,5 +83,21 @@ FOR DELETE USING ( check: '', command: 'DELETE', roles: [], + }, { + id: 'policy-5', + templateName: 'Enable insert access for users based on their user ID *', + description: + 'This policy assumes that your table has a column "user_id", and allows users to insert rows which the "user_id" column matches their ID', + statement: ` +CREATE POLICY "policy_name" +ON ${schema}.${table} +FOR INSERT USING ( + auth.uid() = user_id +);`.trim(), + name: 'Enable insert for users based on user_id', + definition: 'auth.uid() = user_id', + check: '', + command: 'INSERT', + roles: [], }, ] From 99228d9a2f0f9a3913a5fbafa5f08f7a6d1dd9e6 Mon Sep 17 00:00:00 2001 From: Denis Grafov Date: Mon, 3 Jul 2023 16:22:46 +0400 Subject: [PATCH 02/83] Update storage_management.mdx --- apps/docs/components/MDX/storage_management.mdx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/docs/components/MDX/storage_management.mdx b/apps/docs/components/MDX/storage_management.mdx index ce28a1684c8..94aaa57a999 100644 --- a/apps/docs/components/MDX/storage_management.mdx +++ b/apps/docs/components/MDX/storage_management.mdx @@ -61,13 +61,16 @@ as $$ declare status int; content text; + avatar_name text; begin if coalesce(old.avatar_url, '') <> '' and (tg_op = 'DELETE' or (old.avatar_url <> new.avatar_url)) then + -- extract avatar name + avatar_name := substring(old.avatar_url from '/([^\/]+)\?.*$'); select into status, content result.status, result.content - from public.delete_avatar(old.avatar_url) as result; + from public.delete_avatar(avatar_name) as result; if status <> 200 then raise warning 'Could not delete avatar: % %', status, content; end if; From d0d295da9ecc2f0396e70080c53ea35cc7f8216f Mon Sep 17 00:00:00 2001 From: Zach Blume Date: Wed, 5 Jul 2023 20:16:46 -0400 Subject: [PATCH 03/83] Speed up `docker compose down` for postgREST --- docker/docker-compose.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index fcb3c55d83c..38000962786 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -127,6 +127,10 @@ services: PGRST_DB_ANON_ROLE: anon PGRST_JWT_SECRET: ${JWT_SECRET} PGRST_DB_USE_LEGACY_GUCS: "false" + # The following explicit command quickens the `docker compose down` command from 10s to 0.3s: + # https://github.com/PostgREST/postgrest/issues/2851 + command: + command: "postgrest" realtime: container_name: realtime-dev.supabase-realtime From 310bcfe84c72024eac3b39fa3fa9e87844a125cf Mon Sep 17 00:00:00 2001 From: Zach Blume Date: Fri, 7 Jul 2023 16:52:17 -0400 Subject: [PATCH 04/83] Remove comment, simplify command --- docker/docker-compose.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 38000962786..fedb2609ac1 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -127,10 +127,7 @@ services: PGRST_DB_ANON_ROLE: anon PGRST_JWT_SECRET: ${JWT_SECRET} PGRST_DB_USE_LEGACY_GUCS: "false" - # The following explicit command quickens the `docker compose down` command from 10s to 0.3s: - # https://github.com/PostgREST/postgrest/issues/2851 - command: - command: "postgrest" + command: "postgrest" realtime: container_name: realtime-dev.supabase-realtime From cd9b301220c9f44e2c361c0b85c27b7f04ddaadf Mon Sep 17 00:00:00 2001 From: Abdurrahman Rajab Date: Thu, 3 Aug 2023 22:39:09 +0300 Subject: [PATCH 05/83] feat: add check --- .../Policies/PolicyEditorModal/PolicyEditorModal.constants.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/studio/components/interfaces/Auth/Policies/PolicyEditorModal/PolicyEditorModal.constants.ts b/studio/components/interfaces/Auth/Policies/PolicyEditorModal/PolicyEditorModal.constants.ts index fcd6e52a190..0b82ea98cf8 100644 --- a/studio/components/interfaces/Auth/Policies/PolicyEditorModal/PolicyEditorModal.constants.ts +++ b/studio/components/interfaces/Auth/Policies/PolicyEditorModal/PolicyEditorModal.constants.ts @@ -93,10 +93,12 @@ CREATE POLICY "policy_name" ON ${schema}.${table} FOR INSERT USING ( auth.uid() = user_id +) WITH CHECK ( + auth.uid() = user_id );`.trim(), name: 'Enable insert for users based on user_id', definition: 'auth.uid() = user_id', - check: '', + check: 'true', command: 'INSERT', roles: [], }, From 1a40b38610ed4937927d97d3bbbe1607fa0e1918 Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Tue, 22 Aug 2023 03:01:25 +0000 Subject: [PATCH 06/83] Add email based auth with PKCE flow --- .../NavigationMenu.constants.ts | 4 + ...mail-based-auth-with-pkce-flow-for-ssr.mdx | 240 ++++++++++++++++++ 2 files changed, 244 insertions(+) create mode 100644 apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 37803d4823b..2a5991b0882 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -481,6 +481,10 @@ export const auth = { }, { name: 'Password Reset', url: '/guides/auth/auth-password-reset' }, { name: 'Email Templates', url: '/guides/auth/auth-email-templates' }, + { + name: 'Email Auth with PKCE flow for SSR', + url: '/guides/auth/email-based-auth-with-pkce-flow-for-ssr', + }, ], }, { diff --git a/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx b/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx new file mode 100644 index 00000000000..6350914c336 --- /dev/null +++ b/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx @@ -0,0 +1,240 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + title: 'Email Auth with PKCE flow for SSR', + description: 'Learn how to configure email authentication in your server-side rendering (SSR) application to work with the PKCE flow.', +} + +- Install Supabase Auth Helpers +- Set environment variables +- Setting up the Auth Helpers +- Create API endpoint for handling `token_hash` +- Update email templates with URL for API endpoint + +### Install Supabase Auth Helpers + +The Auth Helpers will help you in getting user authentication working in your favourite server-side rendering (SSR) framework. + + + +```bash +npm install @supabase/auth-helpers-nextjs @supabase/supabase-js +``` + + +```bash +npm install @supabase/auth-helpers-sveltekit @supabase/supabase-js +``` + + + +### Set environment variables + +Create an `.env.local` file in your project root directory. You can get your `SITE_URL` and `ANON_KEY` from inside of the [dashboard](https://supabase.com/dashboard/project/_/settings/api). + + + +```bash .env.local +NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url +NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key +``` + + +```bash .env.local +PUBLIC_SUPABASE_URL=your_supabase_project_url +PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key +``` + + + +### Setting up the Auth Helpers + +When using the Supabase client on the server, you must perform extra steps to ensure the user's auth session remains active. Since the user's session is tracked in a cookie, we need to read this cookie and update it if necessary. + + + +Next.js Server Components allow you to read a cookie but not write back to it. Middleware on the other hand allow you to both read and write to cookies. + +Next.js [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) runs immediately before each route is rendered. We'll use Middleware to refresh the user's session before loading Server Component routes. + +Create a new `middleware.js` file in the root of your project and populate with the following: + +```js middleware.js +import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' +import { NextResponse } from 'next/server' + +export async function middleware(req) { + const res = NextResponse.next() + const supabase = createMiddlewareClient({ req, res }) + await supabase.auth.getSession() + return res +} +``` + + +Create a new `hooks.server.js` file in the root of your project and populate with the following: + +```ts src/hooks.server.js +import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public' +import { createSupabaseServerClient } from '@supabase/auth-helpers-sveltekit' +import type { Handle } from '@sveltejs/kit' + +export const handle: Handle = async ({ event, resolve }) => { + event.locals.supabase = createSupabaseServerClient({ + supabaseUrl: PUBLIC_SUPABASE_URL, + supabaseKey: PUBLIC_SUPABASE_ANON_KEY, + event, + }) + + /** + * a little helper that is written for convenience so that instead + * of calling `const { data: { session } } = await supabase.auth.getSession()` + * you just call this `await getSession()` + */ + event.locals.getSession = async () => { + const { + data: { session }, + } = await event.locals.supabase.auth.getSession() + return session + } + + return resolve(event, { + filterSerializedResponseHeaders(name) { + return name === 'content-range' + }, + }) +} +``` + + + +### Create API endpoint for handling `token_hash` + +In order to use the updated email links we will need to setup a endpoint for verifying the `token_hash` along with the `type` to exchange `token_hash` for the user's `session`, which is set as a cookie for future requests made to Supabase. + + + +Create a new file at `app/auth/confirm/route.js` and populate with the following: + +```js app/auth/confirm/route.js +import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs"; +import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; + +export async function GET(req) { + const { searchParams } = new URL(req.url); + const token_hash = searchParams.get("token_hash"); + const type = searchParams.get("type"); + const next = searchParams.get("next") ?? "/"; + + if (token_hash && type) { + const supabase = createRouteHandlerClient({ cookies }); + await supabase.auth.verifyOtp({ type, token_hash }); + } + + return NextResponse.redirect(new URL(`/${next.slice(1)}`, req.url)); +} +``` + + +Create a new file at `src/routes/auth/confirm/+server.js` and populate with the following: + +```js src/routes/auth/confirm/+server.js +import { redirect } from '@sveltejs/kit'; + +export const GET = async (event) => { + const { + url, + locals: { supabase } + } = event; + const token_hash = url.searchParams.get('token') as string; + const type = url.searchParams.get('type') as string; + const next = url.searchParams.get('next') ?? '/'; + + if (token_hash && type) { + const { error } = await supabase.auth.verifyOtp({ token_hash, type }); + if (!error) { + throw redirect(303, `/${next.slice(1)}`); + } + } + + // return to the sign in screen + throw redirect(303, '/auth/signin'); +}; +``` + + + +### Update email templates with URL for API endpoint + +Let's update the URL in our email templates to point to our new confirmation endpoint for the user to get confirmed. + +**Confirm signup template** + +```html +

Confirm your signup

+ +

Follow this link to confirm your user:

+

Confirm your email

+``` + +**Invite user template** + +```html +

You have been invited

+ +

You have been invited to create a user on {{ .SiteURL }}. Follow this link to accept the invite:

+ +

Accept the invite

+``` + +**Magic Link template** + +```html +

Magic Link

+ +

Follow this link to login:

+

Log In

+``` + +**Change Email Address template** + +```html +

Confirm Change of Email

+ +

Follow this link to confirm the update of your email from {{ .Email }} to {{ .NewEmail }}:

+

Change Email

+``` + +**Reset Password template** + +```html +

Reset Password

+ +

Follow this link to reset the password for your user:

+

Reset Password

+``` + +export const Page = ({ children }) => + +export default Page From 23b858524ef1caa68fe7158edb84847f36a8abe1 Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Tue, 22 Aug 2023 23:39:42 +0000 Subject: [PATCH 07/83] Update the first sentence --- .../guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx b/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx index 6350914c336..1c842286d9a 100644 --- a/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx +++ b/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx @@ -13,7 +13,7 @@ export const meta = { ### Install Supabase Auth Helpers -The Auth Helpers will help you in getting user authentication working in your favourite server-side rendering (SSR) framework. +The Auth Helpers will assist you in implementing user authentication within your server-side rendering (SSR) framework. Date: Wed, 23 Aug 2023 01:26:40 +0000 Subject: [PATCH 08/83] Add oauth based auth with PKCE flow --- .../NavigationMenu.constants.ts | 1 + .../auth/oauth-with-pkce-flow-for-ssr.mdx | 192 ++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 apps/docs/pages/guides/auth/oauth-with-pkce-flow-for-ssr.mdx diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 37803d4823b..8247affb1c0 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -481,6 +481,7 @@ export const auth = { }, { name: 'Password Reset', url: '/guides/auth/auth-password-reset' }, { name: 'Email Templates', url: '/guides/auth/auth-email-templates' }, + { name: 'OAuth with PKCE flow for SSR', url: '/guides/auth/oauth-with-pkce-flow-for-ssr' }, ], }, { diff --git a/apps/docs/pages/guides/auth/oauth-with-pkce-flow-for-ssr.mdx b/apps/docs/pages/guides/auth/oauth-with-pkce-flow-for-ssr.mdx new file mode 100644 index 00000000000..bef2287eaf9 --- /dev/null +++ b/apps/docs/pages/guides/auth/oauth-with-pkce-flow-for-ssr.mdx @@ -0,0 +1,192 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + title: 'OAuth with PKCE flow for SSR', + description: 'Learn how to configure OAuth authentication in your server-side rendering (SSR) application to work with the PKCE flow.', +} + +### Install Supabase Auth Helpers + +The Auth Helpers will assist you in implementing user authentication within your server-side rendering (SSR) framework. + + + +```bash +npm install @supabase/auth-helpers-nextjs @supabase/supabase-js +``` + + +```bash +npm install @supabase/auth-helpers-sveltekit @supabase/supabase-js +``` + + + +### Set environment variables + +Create an `.env.local` file in your project root directory. You can get your `SITE_URL` and `ANON_KEY` from inside of the [dashboard](https://supabase.com/dashboard/project/_/settings/api). + + + +```bash .env.local +NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url +NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key +``` + + +```bash .env.local +PUBLIC_SUPABASE_URL=your_supabase_project_url +PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key +``` + + + +### Setting up the Auth Helpers + +When using the Supabase client on the server, you must perform extra steps to ensure the user's auth session remains active. Since the user's session is tracked in a cookie, we need to read this cookie and update it if necessary. + + + +Next.js Server Components allow you to read a cookie but not write back to it. Middleware on the other hand allow you to both read and write to cookies. + +Next.js [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) runs immediately before each route is rendered. We'll use Middleware to refresh the user's session before loading Server Component routes. + +Create a new `middleware.js` file in the root of your project and populate with the following: + +```js middleware.js +import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' +import { NextResponse } from 'next/server' + +export async function middleware(req) { + const res = NextResponse.next() + const supabase = createMiddlewareClient({ req, res }) + await supabase.auth.getSession() + return res +} +``` + + +Create a new `hooks.server.js` file in the root of your project and populate with the following: + +```ts src/hooks.server.js +import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public' +import { createSupabaseServerClient } from '@supabase/auth-helpers-sveltekit' +import type { Handle } from '@sveltejs/kit' + +export const handle: Handle = async ({ event, resolve }) => { + event.locals.supabase = createSupabaseServerClient({ + supabaseUrl: PUBLIC_SUPABASE_URL, + supabaseKey: PUBLIC_SUPABASE_ANON_KEY, + event, + }) + + event.locals.getSession = async () => { + const { + data: { session }, + } = await event.locals.supabase.auth.getSession() + return session + } + + return resolve(event, { + filterSerializedResponseHeaders(name) { + return name === 'content-range' + }, + }) +} +``` + + + +### Create API endpoint for handling the `code` exchange + +In order to use OAuth we will need to setup a endpoint for the `code` exchange, to exchange an auth `code` for the user's `session`, which is set as a cookie for future requests made to Supabase. + + + +Create a new file at `app/auth/callback/route.js` and populate with the following: + +```js app/auth/callback/route.js +import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs"; +import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; + +export async function GET(req) { + const { searchParams } = new URL(req.url); + const code = searchParams.get("code"); + const next = searchParams.get("next") ?? "/"; + + if (code) { + const supabase = createRouteHandlerClient({ cookies: () => cookies() }); + const { error } = await supabase.auth.exchangeCodeForSession(code); + if (!error) { + return NextResponse.redirect(new URL(`/${next.slice(1)}`, req.url)); + } + } + + // return the user to an error page with instructions + return NextResponse.redirect(new URL('/auth/auth-code-error', req.url)); +} +``` + + +Create a new file at `src/routes/auth/callback/+server.js` and populate with the following: + +```js src/routes/auth/callback/+server.js +import { redirect } from '@sveltejs/kit'; + +export const GET = async (event) => { + const { + url, + locals: { supabase } + } = event; + const code = url.searchParams.get('code') as string; + const next = url.searchParams.get('next') ?? '/'; + + if (code) { + const { error } = await supabase.auth.exchangeCodeForSession(code) + if (!error) { + throw redirect(303, `/${next.slice(1)}`); + } + } + + // return the user to an error page with instructions + throw redirect(303, '/auth/auth-code-error'); +}; +``` + + + +Let's point our `.signInWithOAuth` method's redirect to the callback route we create above: + +```js +await supabase.auth.signInWithOAuth({ + email, + options: { + redirectTo: `http://example.com/auth/callback` + } +}) +``` + +export const Page = ({ children }) => + +export default Page From 1b56873ea903698c7a33f5fdae16e866c23c4564 Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Wed, 23 Aug 2023 01:36:42 +0000 Subject: [PATCH 09/83] Remove bullet points from docs --- ...mail-based-auth-with-pkce-flow-for-ssr.mdx | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx b/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx index 1c842286d9a..208660ed982 100644 --- a/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx +++ b/apps/docs/pages/guides/auth/email-based-auth-with-pkce-flow-for-ssr.mdx @@ -5,12 +5,6 @@ export const meta = { description: 'Learn how to configure email authentication in your server-side rendering (SSR) application to work with the PKCE flow.', } -- Install Supabase Auth Helpers -- Set environment variables -- Setting up the Auth Helpers -- Create API endpoint for handling `token_hash` -- Update email templates with URL for API endpoint - ### Install Supabase Auth Helpers The Auth Helpers will assist you in implementing user authentication within your server-side rendering (SSR) framework. @@ -101,11 +95,6 @@ export const handle: Handle = async ({ event, resolve }) => { event, }) - /** - * a little helper that is written for convenience so that instead - * of calling `const { data: { session } } = await supabase.auth.getSession()` - * you just call this `await getSession()` - */ event.locals.getSession = async () => { const { data: { session }, @@ -149,10 +138,14 @@ export async function GET(req) { if (token_hash && type) { const supabase = createRouteHandlerClient({ cookies }); - await supabase.auth.verifyOtp({ type, token_hash }); + const { error } = await supabase.auth.verifyOtp({ type, token_hash }); + if (!error) { + return NextResponse.redirect(new URL(`/${next.slice(1)}`, req.url)); + } } - return NextResponse.redirect(new URL(`/${next.slice(1)}`, req.url)); + // return the user to an error page with some instructions + return NextResponse.redirect(new URL('/auth/auth-code-error', req.url)); } ``` @@ -178,8 +171,8 @@ export const GET = async (event) => { } } - // return to the sign in screen - throw redirect(303, '/auth/signin'); + // return the user to an error page with some instructions + throw redirect(303, '/auth/auth-code-error'); }; ``` From e8755abdd2fe7f9a0fe88eeee38b0eca0efb46a9 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Fri, 25 Aug 2023 13:19:42 -0230 Subject: [PATCH 10/83] Fix duplicate key --- studio/components/interfaces/Support/Support.constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/studio/components/interfaces/Support/Support.constants.ts b/studio/components/interfaces/Support/Support.constants.ts index 3bec483febf..1e16de175d5 100644 --- a/studio/components/interfaces/Support/Support.constants.ts +++ b/studio/components/interfaces/Support/Support.constants.ts @@ -36,7 +36,7 @@ export const CATEGORY_OPTIONS = [ query: undefined, }, { - value: 'Problem', + value: 'Abuse', label: 'Abuse report', description: 'Report abuse of a Supabase project or Supabase brand', query: undefined, From 66c0903364a987f73b2a7ca3d90a4ed0c31756df Mon Sep 17 00:00:00 2001 From: kishanhitk Date: Sat, 26 Aug 2023 14:45:56 +0530 Subject: [PATCH 11/83] chore: add note --- studio/data/projects/project-type-generation-query.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/studio/data/projects/project-type-generation-query.ts b/studio/data/projects/project-type-generation-query.ts index f950459d43f..8e14366dcc8 100644 --- a/studio/data/projects/project-type-generation-query.ts +++ b/studio/data/projects/project-type-generation-query.ts @@ -9,6 +9,8 @@ export type GenerateTypesVariables = { ref?: string } export async function generateTypes({ ref }: GenerateTypesVariables, signal?: AbortSignal) { if (!ref) throw new Error('Project ref is required') + // TODO: Something wrong with the typescript endpoint on local dev and self-hosted + const { data, error } = await get(`/v1/projects/{ref}/types/typescript`, { params: { path: { ref } }, signal, From 9ba9ab70977d4576029649a5031a68c01f51cec3 Mon Sep 17 00:00:00 2001 From: Neeraj Walia Date: Sun, 27 Aug 2023 00:08:49 +0530 Subject: [PATCH 12/83] Add bucket name validation --- studio/pages/api/storage/[ref]/buckets/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/studio/pages/api/storage/[ref]/buckets/index.ts b/studio/pages/api/storage/[ref]/buckets/index.ts index e426db1810c..e7a968948d5 100644 --- a/studio/pages/api/storage/[ref]/buckets/index.ts +++ b/studio/pages/api/storage/[ref]/buckets/index.ts @@ -33,6 +33,13 @@ const handleGet = async (req: NextApiRequest, res: NextApiResponse) => { const handlePost = async (req: NextApiRequest, res: NextApiResponse) => { const { id, public: isPublicBucket } = req.body + // To validate bucket name, can be removed once the issue is fixed in supabase lib + const regex = /^[a-z0-9.-]+$/ + if (!regex.test(id)) { + return res.status(400).json({ error: { message: 'Bucket name invalid' } }) + } + // Bucket name validation ends here + const { data, error } = await supabase.storage.createBucket(id, { public: isPublicBucket }) if (error) { return res.status(400).json({ error: { message: error.message } }) From d1b9242edfca16124e536fb7d03b8b6b99daab97 Mon Sep 17 00:00:00 2001 From: kishanhitk Date: Tue, 29 Aug 2023 19:04:58 +0530 Subject: [PATCH 13/83] feat: add type generation from local dashboard --- .../api/v1/projects/[ref]/types/typescript.ts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 studio/pages/api/v1/projects/[ref]/types/typescript.ts diff --git a/studio/pages/api/v1/projects/[ref]/types/typescript.ts b/studio/pages/api/v1/projects/[ref]/types/typescript.ts new file mode 100644 index 00000000000..56fc47a33cc --- /dev/null +++ b/studio/pages/api/v1/projects/[ref]/types/typescript.ts @@ -0,0 +1,38 @@ +import { NextApiRequest, NextApiResponse } from 'next' +import { PG_META_URL } from 'lib/constants' +import apiWrapper from 'lib/api/apiWrapper' +import { constructHeaders } from 'lib/api/apiHelpers' +import { get } from 'lib/common/fetch' + +export default (req: NextApiRequest, res: NextApiResponse) => + apiWrapper(req, res, handler, { withAuth: true }) + +async function handler(req: NextApiRequest, res: NextApiResponse) { + const { method } = req + + switch (method) { + case 'GET': + return handleGetAll(req, res) + default: + res.setHeader('Allow', ['GET']) + res.status(405).json({ error: { message: `Method ${method} Not Allowed` } }) + } +} + +const handleGetAll = async (req: NextApiRequest, res: NextApiResponse) => { + const includedSchema = 'public,graphql_public,storage' + const excludedSchema = + 'auth,cron,extensions,graphql,net,pgsodium,pgsodium_masks,realtime,supabase_functions,supabase_migrations,vault,_analytics,_realtime' + + const headers = constructHeaders(req.headers) + const response = await get( + `${PG_META_URL}/generators/typescript?included_schema=${includedSchema}&excluded_schemas=${excludedSchema}`, + { headers } + ) + + if (response.error) { + return res.status(400).json({ error: response.error }) + } + + return res.status(200).json({ types: response }) +} From 20cfa8e79985152847004cc5ce0bd0b1618f2d9a Mon Sep 17 00:00:00 2001 From: kishanhitk Date: Tue, 29 Aug 2023 19:06:26 +0530 Subject: [PATCH 14/83] chore: remove TODO comment --- studio/data/projects/project-type-generation-query.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/studio/data/projects/project-type-generation-query.ts b/studio/data/projects/project-type-generation-query.ts index 8e14366dcc8..f950459d43f 100644 --- a/studio/data/projects/project-type-generation-query.ts +++ b/studio/data/projects/project-type-generation-query.ts @@ -9,8 +9,6 @@ export type GenerateTypesVariables = { ref?: string } export async function generateTypes({ ref }: GenerateTypesVariables, signal?: AbortSignal) { if (!ref) throw new Error('Project ref is required') - // TODO: Something wrong with the typescript endpoint on local dev and self-hosted - const { data, error } = await get(`/v1/projects/{ref}/types/typescript`, { params: { path: { ref } }, signal, From c0e9a1e7e8e1cdf793a8d7d1059d42bf846a99da Mon Sep 17 00:00:00 2001 From: kishanhitk Date: Wed, 30 Aug 2023 09:25:03 +0530 Subject: [PATCH 15/83] chore: cleaner code --- .../api/v1/projects/[ref]/types/typescript.ts | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/studio/pages/api/v1/projects/[ref]/types/typescript.ts b/studio/pages/api/v1/projects/[ref]/types/typescript.ts index 56fc47a33cc..fa62b486eb3 100644 --- a/studio/pages/api/v1/projects/[ref]/types/typescript.ts +++ b/studio/pages/api/v1/projects/[ref]/types/typescript.ts @@ -20,11 +20,26 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { } const handleGetAll = async (req: NextApiRequest, res: NextApiResponse) => { - const includedSchema = 'public,graphql_public,storage' - const excludedSchema = - 'auth,cron,extensions,graphql,net,pgsodium,pgsodium_masks,realtime,supabase_functions,supabase_migrations,vault,_analytics,_realtime' + const includedSchema = ['public', 'graphql_public', 'storage'].join(',') + + const excludedSchema = [ + 'auth', + 'cron', + 'extensions', + 'graphql', + 'net', + 'pgsodium', + 'pgsodium_masks', + 'realtime', + 'supabase_functions', + 'supabase_migrations', + 'vault', + '_analytics', + '_realtime', + ].join(',') const headers = constructHeaders(req.headers) + const response = await get( `${PG_META_URL}/generators/typescript?included_schema=${includedSchema}&excluded_schemas=${excludedSchema}`, { headers } From 26b51c725e6a6d4f461083ebe8f98f27e1e4a4ac Mon Sep 17 00:00:00 2001 From: Buzz <69213001+buzzthedev@users.noreply.github.com> Date: Wed, 30 Aug 2023 12:57:08 +0100 Subject: [PATCH 16/83] Update realtime-with-nextjs.mdx Fixed spelling errors and grammar. --- apps/docs/pages/guides/realtime/realtime-with-nextjs.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/docs/pages/guides/realtime/realtime-with-nextjs.mdx b/apps/docs/pages/guides/realtime/realtime-with-nextjs.mdx index e60afb4f74a..fd9e8d98675 100644 --- a/apps/docs/pages/guides/realtime/realtime-with-nextjs.mdx +++ b/apps/docs/pages/guides/realtime/realtime-with-nextjs.mdx @@ -7,8 +7,8 @@ export const meta = { sidebar_label: 'Videos', } -In this guide we explore the best ways to receive realtime Postgres changes with your Next.js application. -We'll show both client and serverside updates, and explore the which option is best. +In this guide, we explore the best ways to receive real-time Postgres changes with your Next.js application. +We'll show both client and server side updates, and explore which option is best.