From 6d2e549e715f5b5cb6584c62e37c61abf0972778 Mon Sep 17 00:00:00 2001 From: thorwebdev Date: Wed, 12 Oct 2022 17:47:42 +0800 Subject: [PATCH 1/3] chore: update tshirt function --- .../functions/get-tshirt-competition/README.md | 4 ++-- .../functions/get-tshirt-competition/index.ts | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/examples/edge-functions/supabase/functions/get-tshirt-competition/README.md b/examples/edge-functions/supabase/functions/get-tshirt-competition/README.md index 9f6033295a7..8d0bcb0dd72 100644 --- a/examples/edge-functions/supabase/functions/get-tshirt-competition/README.md +++ b/examples/edge-functions/supabase/functions/get-tshirt-competition/README.md @@ -2,10 +2,10 @@ To celebrate the support of GET requests in Supabase Edge Functions we're giving away some limited edition Functions Shirts! -To win a Supabase Edge Functions T-Shirt, make a GET request to https://obuldanrptloktxcffvn.functions.supabase.co/get-tshirt-competition with your email address, your Twitter handle (optional), and the correct answer, e.g. +To win a Supabase Edge Functions T-Shirt, make a GET request to https://obuldanrptloktxcffvn.functions.supabase.co/get-tshirt-competition with your email address, your Twitter handle (optional), your t-shirt size (S-2XL) and the correct answer, e.g. ```text -https://obuldanrptloktxcffvn.functions.supabase.co/get-tshirt-competition?email=testr@test.de&twitter=thorwebdev&answer=20 +https://obuldanrptloktxcffvn.functions.supabase.co/get-tshirt-competition?email=testr@test.de&twitter=thorwebdev&size=2XL&answer=20 ``` You can read the functions source code to figure out the answer ;) diff --git a/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts b/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts index 75f0985258d..392da9f29f0 100644 --- a/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts +++ b/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts @@ -27,11 +27,17 @@ serve(async (req) => { const url = new URL(req.url) const email = url.searchParams.get('email') const twitter = url.searchParams.get('twitter') + const size = url.searchParams.get('size') const answer = url.searchParams.get('answer') - if (!/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email ?? '') || !answer) + if ( + !/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email ?? '') || + !answer || + !twitter || + !size + ) throw new Error( - `You're missing either a valid 'email' and/or 'answer' param(s). HINT: https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts` + `Please provide valid 'email', 'twitter', 'size', and 'answer' params. HINT: https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/get-tshirt-competition/index.ts` ) if (Number(answer) !== positionInAlphabet(email!)) @@ -50,6 +56,7 @@ serve(async (req) => { { email, twitter, + size, }, { onConflict: 'email' } ) @@ -71,4 +78,4 @@ serve(async (req) => { }) // To invoke: -// curl -i --location --request GET 'http://localhost:54321/functions/v1/get-tshirt-competition?email=testr@test.de&answer=20' +// curl -i --location --request GET 'http://localhost:54321/functions/v1/get-tshirt-competition?email=testr@test.de&twitter=thorwebdev&size=2XL&answer=20' From f03179d5722cdf0bc3aa8545acf06656b73d4f81 Mon Sep 17 00:00:00 2001 From: thorwebdev Date: Wed, 12 Oct 2022 18:23:53 +0800 Subject: [PATCH 2/3] feat: functions docs improvements. --- apps/reference/docs/guides/functions.mdx | 43 ------------- apps/reference/docs/guides/functions/auth.mdx | 63 +++++++++++++++++++ .../docs/guides/functions/examples.mdx | 47 ++++++++++++++ apps/reference/nav/_referenceSidebars.js | 7 ++- 4 files changed, 116 insertions(+), 44 deletions(-) create mode 100644 apps/reference/docs/guides/functions/auth.mdx create mode 100644 apps/reference/docs/guides/functions/examples.mdx diff --git a/apps/reference/docs/guides/functions.mdx b/apps/reference/docs/guides/functions.mdx index d32cfa12cf4..0391adce248 100644 --- a/apps/reference/docs/guides/functions.mdx +++ b/apps/reference/docs/guides/functions.mdx @@ -7,29 +7,6 @@ sidebar_label: Overview import Tabs from '@theme/Tabs' import TabItem from '@theme/TabItem' -import ButtonCard from '@site/src/components/ButtonCard' -const examples = [ - { - name: 'With supabase-js', - description: 'Use the Supabase client inside your Edge Function.', - href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts', - }, - { - name: 'With CORS headers', - description: 'Send CORS headers for invoking from the browser.', - href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/browser-with-cors/index.ts', - }, - { - name: 'React Native with Stripe', - description: 'Full example for using Supabase and Stripe, with Expo.', - href: 'https://github.com/supabase-community/expo-stripe-payments-with-supabase-functions', - }, - { - name: 'Flutter with Stripe', - description: 'Full example for using Supabase and Stripe, with Flutter.', - href: 'https://github.com/supabase-community/flutter-stripe-payments-with-supabase-functions', - }, -] Edge Functions are server-side TypeScript functions, distributed globally at the edge—close to your users. They can be used for listening to webhooks or integrating your Supabase project with third-parties [like Stripe](https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/stripe-webhooks). @@ -235,26 +212,6 @@ To see all the secrets which you have set remotely, use [`supabase secrets list` supabase secrets list ``` -## Examples - -You can find a list of useful [Edge Function Examples](https://github.com/supabase/supabase/tree/master/examples/edge-functions) in our GitHub repository. - -
-
- {examples.map((x) => ( -
- -
- ))} -
-
- ## Suggestions ### Database Functions vs Edge Functions diff --git a/apps/reference/docs/guides/functions/auth.mdx b/apps/reference/docs/guides/functions/auth.mdx new file mode 100644 index 00000000000..43b6c983e64 --- /dev/null +++ b/apps/reference/docs/guides/functions/auth.mdx @@ -0,0 +1,63 @@ +--- +id: auth +title: Auth +description: Supabase Edge Functions and Auth. +--- + +Edge Functions work seamlessly with [Supabase Auth](/docs/guides/auth), allowing you to identify which user called your function. + +When [invoking](docs/reference/javascript/invoke) a function with one of the [client libraries](docs/reference), the logged in user's JWT is automatically attached to the function call and becomes accessible within your function. + +This is important, for example, to identify which customer's credit card should be charged. You can see this concept end-to-end in our [Stripe example app](https://github.com/supabase-community/expo-stripe-payments-with-supabase-functions). + +## Auth Context & RLS + +By creating a supabase client with the auth context from the function, you can do two things: + +1. Get the user object. +2. Run queries in the context of the user with [Row Level Security (RLS)](http://localhost:3010/docs/guides/auth/row-level-security) policies enforced. + +```js title="supabase/functions/select-from-table-with-auth-rls/index.ts" +import { serve } from 'https://deno.land/std@0.131.0/http/server.ts' +import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.0.0-rc.12' + +serve(async (req: Request) => { + try { + // Create a Supabase client with the Auth context of the logged in user. + const supabaseClient = createClient( + // Supabase API URL - env var exported by default. + Deno.env.get('SUPABASE_URL') ?? '', + // Supabase API ANON KEY - env var exported by default. + Deno.env.get('SUPABASE_ANON_KEY') ?? '', + // Create client with Auth context of the user that called the function. + // This way your row-level-security (RLS) policies are applied. + // highlight-next-line + { global: { headers: { Authorization: req.headers.get('Authorization')! } } } + ) + // Now we can get the session or user object + // highlight-start + const { + data: { user }, + } = await supabaseClient.auth.getUser() + // highlight-end + + // And we can run queries in the context of our authenticated user + // highlight-start + const { data, error } = await supabaseClient.from('users').select('*') + if (error) throw error + // highlight-end + + return new Response(JSON.stringify({ user, data }), { + headers: { 'Content-Type': 'application/json' }, + status: 200, + }) + } catch (error) { + return new Response(JSON.stringify({ error: error.message }), { + headers: { 'Content-Type': 'application/json' }, + status: 400, + }) + } +}) +``` + +See the [example on GitHub](https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts). diff --git a/apps/reference/docs/guides/functions/examples.mdx b/apps/reference/docs/guides/functions/examples.mdx new file mode 100644 index 00000000000..e56dc4da517 --- /dev/null +++ b/apps/reference/docs/guides/functions/examples.mdx @@ -0,0 +1,47 @@ +--- +id: examples +title: Examples +description: Useful Supabase Edge Functions Examples. +--- + +import ButtonCard from '@site/src/components/ButtonCard' +const examples = [ + { + name: 'With supabase-js', + description: 'Use the Supabase client inside your Edge Function.', + href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts', + }, + { + name: 'With CORS headers', + description: 'Send CORS headers for invoking from the browser.', + href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/browser-with-cors/index.ts', + }, + { + name: 'React Native with Stripe', + description: 'Full example for using Supabase and Stripe, with Expo.', + href: 'https://github.com/supabase-community/expo-stripe-payments-with-supabase-functions', + }, + { + name: 'Flutter with Stripe', + description: 'Full example for using Supabase and Stripe, with Flutter.', + href: 'https://github.com/supabase-community/flutter-stripe-payments-with-supabase-functions', + }, +] + +You can find a list of useful [Edge Function Examples](https://github.com/supabase/supabase/tree/master/examples/edge-functions) in our GitHub repository. + +
+
+ {examples.map((x) => ( +
+ +
+ ))} +
+
diff --git a/apps/reference/nav/_referenceSidebars.js b/apps/reference/nav/_referenceSidebars.js index 9871aa55528..e0150208708 100644 --- a/apps/reference/nav/_referenceSidebars.js +++ b/apps/reference/nav/_referenceSidebars.js @@ -156,7 +156,12 @@ const sidebars = { type: 'category', label: 'Edge Functions', collapsed: true, - items: ['guides/functions', 'guides/functions/cicd-workflow'], + items: [ + 'guides/functions', + 'guides/functions/auth', + 'guides/functions/examples', + 'guides/functions/cicd-workflow', + ], }, { type: 'category', From c5655c32b890eadf8136b305642e133405426600 Mon Sep 17 00:00:00 2001 From: thorwebdev Date: Wed, 12 Oct 2022 23:19:48 +0800 Subject: [PATCH 3/3] chore: fix links. --- apps/reference/docs/guides/functions/auth.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/reference/docs/guides/functions/auth.mdx b/apps/reference/docs/guides/functions/auth.mdx index 43b6c983e64..615ed5484c7 100644 --- a/apps/reference/docs/guides/functions/auth.mdx +++ b/apps/reference/docs/guides/functions/auth.mdx @@ -6,7 +6,7 @@ description: Supabase Edge Functions and Auth. Edge Functions work seamlessly with [Supabase Auth](/docs/guides/auth), allowing you to identify which user called your function. -When [invoking](docs/reference/javascript/invoke) a function with one of the [client libraries](docs/reference), the logged in user's JWT is automatically attached to the function call and becomes accessible within your function. +When [invoking](/docs/reference/javascript/invoke) a function with one of the [client libraries](/docs/reference), the logged in user's JWT is automatically attached to the function call and becomes accessible within your function. This is important, for example, to identify which customer's credit card should be charged. You can see this concept end-to-end in our [Stripe example app](https://github.com/supabase-community/expo-stripe-payments-with-supabase-functions).