Merge pull request #9493 from supabase/chore/functions-updates-2210122

Chore/functions updates 2210122
This commit is contained in:
Thor 雷神 Schaeff authored and GitHub committed 2022-10-12 23:59:54 +08:00
commit 030b0bcba7
6 files changed
+128 -49

No files matched your search

-43
View File
@@ -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.
<div class="container" style={{ padding: 0 }}>
<div class="row is-multiline">
{examples.map((x) => (
<div class="col col--6">
<ButtonCard
class="card"
to={x.href}
title={x.name}
description={x.description}
style={{ height: '100%' }}
/>
</div>
))}
</div>
</div>
## Suggestions
### Database Functions vs Edge Functions
@@ -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).
@@ -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.
<div class="container" style={{ padding: 0 }}>
<div class="row is-multiline">
{examples.map((x) => (
<div class="col col--6">
<ButtonCard
class="card"
to={x.href}
title={x.name}
description={x.description}
style={{ height: '100%' }}
/>
</div>
))}
</div>
</div>
+6 -1
View File
@@ -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',
@@ -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 ;)
@@ -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'