Merge pull request #10506 from supabase/master

Prod deploy dashboard
This commit is contained in:
Joshen Lim authored and GitHub committed 2022-11-24 17:45:54 +08:00
commit 70069f86b3
24 files changed
+9717 -62133

No files matched your search

+15 -6
View File
@@ -131,7 +131,7 @@ Our approach for client libraries is modular. Each sub-library is a standalone i
<td>Go</td>
<td>-</td>
<td><a href="https://github.com/supabase-community/postgrest-go" target="_blank" rel="noopener noreferrer">postgrest-go</a></td>
<td>-</td>
<td><a href="https://github.com/supabase-community/gotrue-go" target="_blank" rel="noopener noreferrer">gotrue-go</a></td>
<td>-</td>
<td><a href="https://github.com/supabase-community/storage-go" target="_blank" rel="noopener noreferrer">storage-go</a></td>
<td><a href="https://github.com/supabase-community/functions-go" target="_blank" rel="noopener noreferrer">functions-go</a></td>
@@ -147,12 +147,12 @@ Our approach for client libraries is modular. Each sub-library is a standalone i
</tr>
<tr>
<td>Kotlin</td>
<td>-</td>
<td><a href="https://github.com/supabase-community/supabase-kt" target="_blank" rel="noopener noreferrer">supabase-kt</a></td>
<td><a href="https://github.com/supabase-community/postgrest-kt" target="_blank" rel="noopener noreferrer">postgrest-kt</a></td>
<td><a href="https://github.com/supabase-community/gotrue-kt" target="_blank" rel="noopener noreferrer">gotrue-kt</a></td>
<td>-</td>
<td>-</td>
<td>-</td>
<td><a href="https://github.com/supabase-community/supabase-kt/tree/master/Realtime" target="_blank" rel="noopener noreferrer">realtime-kt</a></td>
<td><a href="https://github.com/supabase-community/supabase-kt/tree/master/Storage" target="_blank" rel="noopener noreferrer">storage-kt</a></td>
<td><a href="https://github.com/supabase-community/supabase-kt/tree/master/Functions" target="_blank" rel="noopener noreferrer">functions-kt</a></td>
</tr>
<tr>
<td>Python</td>
@@ -188,7 +188,16 @@ Our approach for client libraries is modular. Each sub-library is a standalone i
<td><a href="https://github.com/supabase-community/gotrue-swift" target="_blank" rel="noopener noreferrer">gotrue-swift</a></td>
<td><a href="https://github.com/supabase-community/realtime-swift" target="_blank" rel="noopener noreferrer">realtime-swift</a></td>
<td><a href="https://github.com/supabase-community/storage-swift" target="_blank" rel="noopener noreferrer">storage-swift</a></td>
<td>-</td>
<td><a href="https://github.com/supabase-community/functions-swift" target="_blank" rel="noopener noreferrer">functions-swift</a></td>
</tr>
<tr>
<td>Godot Engine (GDScript)</td>
<td><a href="https://github.com/supabase-community/godot-engine.supabase" target="_blank" rel="noopener noreferrer">supabase-gdscript</a></td>
<td><a href="https://github.com/supabase-community/postgrest-gdscript" target="_blank" rel="noopener noreferrer">postgrest-gdscript</a></td>
<td><a href="https://github.com/supabase-community/gotrue-gdscript" target="_blank" rel="noopener noreferrer">gotrue-gdscript</a></td>
<td><a href="https://github.com/supabase-community/realtime-gdscript" target="_blank" rel="noopener noreferrer">realtime-gdscript</a></td>
<td><a href="https://github.com/supabase-community/storage-gdscript" target="_blank" rel="noopener noreferrer">storage-gdscript</a></td>
<td><a href="https://github.com/supabase-community/functions-gdscript" target="_blank" rel="noopener noreferrer">functions-gdscript</a></td>
</tr>
</table>
@@ -38,6 +38,11 @@ const examples = [
'Generate Open Graph images with Deno and Supabase Edge Functions, no framework needed.',
href: 'https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/opengraph',
},
{
name: 'OG Image Generation & Storage CDN Caching',
description: 'Cache generated images with Supabase Storage CDN.',
href: 'https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/og-image-with-storage-cdn',
},
{
name: 'Get User Location',
description: `Get user location data from user's IP address.`,
@@ -307,6 +307,7 @@ export const menuItems: NavMenu = {
name: 'Developer Tools',
url: undefined,
items: [
{ name: 'Estuary', url: '/guides/integrations/estuary', items: [] },
{ name: 'pgMustard', url: '/guides/integrations/pgmustard', items: [] },
{ name: 'Prisma', url: '/guides/integrations/prisma', items: [] },
{ name: 'Sequin', url: '/guides/integrations/sequin', items: [] },
+1 -1
View File
@@ -27,7 +27,7 @@ async function gen_v001(spec: CliSpec, dest: string) {
const commands = spec.commands.map((x) => {
const isChild = x.subcommands.length < 1
const heading = isChild ? `### ${x.summary} {#${x.id}}` : `## ${x.summary} {#${x.id}}`
const heading = isChild ? `### ${x.summary} [#${x.id}]` : `## ${x.summary} [#${x.id}]`
return {
...x,
+1 -1
View File
@@ -21,7 +21,7 @@ By creating a supabase client with the auth context from the function, you can d
```js lines=14,17-19,22-23 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'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
serve(async (req: Request) => {
try {
@@ -0,0 +1,101 @@
import Layout from '~/layouts/DefaultGuideLayout'
export const meta = {
id: 'estuary',
title: 'Estuary',
description: 'Create a real-time data pipeline connecting Firestore and Supabase to make migration simple.',
}
Estuary Flow is a platform for creating [real-time data pipelines at scale](https://www.estuary.dev/).
It combines the intuitive interface of an ELT service with an event-driven runtime and a variety of open-source connectors.
You can use Flow to migrate your data from Firestore to the Postgres database in your Supabase project.
You do this by building a real-time pipeline that captures data from Firestore and materializes (loads) that data to Postgres.
Once created, the pipeline backfills all your historical data from Firestore and continues to process new data events in real time.
## Prerequisites
Before you begin, you'll need:
* An [Estuary account](go.estuary.dev/sign-up).
* For your Firestore database:
* A Google service account with read access to your Firestore database, via [roles/datastore.viewer](https://cloud.google.com/datastore/docs/access/iam). You can assign this role when you [create the service account](https://cloud.google.com/iam/docs/creating-managing-service-accounts#creating), or [add it to an existing service account](https://cloud.google.com/iam/docs/granting-changing-revoking-access#single-role).
* A generated [JSON service account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating) for the service account.
* A Supabase project
## Step 1: Capture your Firestore data
You'll start by creating a **capture**, a task in Flow that connects to your data source system: in this case, Firestore. This process will create one or more data **collections**, backed by a real-time data lake.
1. Go to the Flow web application at [dashboard.estuary.dev](http://dashboard.estuary.dev) and sign in using the credentials provided by your Estuary account manager.
2. Click the **Captures** tab and choose **New Capture**.
3. Locate and select the **Google Firestore** card.
A form appears with the properties required for a Firestore capture.
4. Set a name for your capture.
Click inside the **Name** field to generate a drop-down menu of available **prefixes** and select one (likely, this will be the name of your organization). Append a unique capture name after the `/` to create the full name, for example, `acmeCo/myFirestoreCapture`.
5. Fill out the required properties for Firestore.
* **Database**: Flow can autodetect the database name, but you may optionally specify it here. This is helpful if the service account used has access to multiple Firebase projects. Your database name usually follows the format `projects/$PROJECTID/databases/(default)`.
* **Credentials**: The JSON service account key created per the prerequisites.
6. Click **Discover Endpoint**.
Flow uses the provided configuration to initiate a connection with Firestore. It generates a capture specification and details of the collections that it will create, once published.
7. Use the **Specification Editor** to view the [JSON schemas](https://docs.estuary.dev/concepts/schemas/) for each collection and make sure they are formatted correctly for your needs. If they're not, you can edit them.
8. Click **Save and publish**.
You'll see a notification when the capture publishes successfully.
The data currently in your Firestore database has been captured, and future updates to it will be captured continuously.
Click **Materialize Collections** to continue.
## Step 2: Materialize your collections to Postgres
Next, you'll add a Postgres materialization to connect the captured collections to tables in your Supabase Postgres database.
1. On the **Create Materialization** page, search for and select the **PostgreSQL** tile.
A form appears with the properties required for a Postgres materialization.
2. Choose a unique name for your materialization like you did when naming your capture; for example, `acmeCo/mySupabaseMaterialization`.
3. Fill out the required properties for PostgreSQL. You can find most of these in Supabase by going to the **Settings** section and clicking **Database**.
* **Address**: Format at `<host>:<port>`.
* **User**: Usually, this is `postgres`.
* **Password**: The password you set when you created your Supabase project.
4. Scroll down to view the **Collection Selector** and fill in the **Table** field for each collection.
The collections you just created have already been selected, but you must provide names for the tables to which they'll be materialized.
5. Click **Discover Endpoint**.
Flow uses the provided configuration to initiate a connection to your Supabase Postgres database and generate a specification.
6. Click **Save and Publish**. You'll see a notification when the full materialization publishes successfully.
Your Firestore collections are copied to tables in Supabase. As long as you leave the capture and materialation running, any changes to the Firestore data will be reflected in Supabase in milliseconds.
## Resources
For more information, visit the [Flow docs](https://docs.estuary.dev/). In particular:
* [Guide to create a Data Flow](https://docs.estuary.dev/guides/create-dataflow/)
* [Firestore capture connector](https://docs.estuary.dev/reference/Connectors/capture-connectors/google-firestore/)
* [Postgres materializaiton connector](https://docs.estuary.dev/reference/Connectors/materialization-connectors/PostgreSQL/)
export const Page = ({ children }) => <Layout meta={meta} children={children} />
export default Page
@@ -1185,7 +1185,7 @@ class SplashPageState extends State<SplashPage> {
}
} catch (_) {
context.showErrorSnackBar(
message: 'Error occured during session refresh',
message: 'Error occurred during session refresh',
);
Navigator.of(context).pushAndRemoveUntil(
RegisterPage.route(), (_) => false);
@@ -0,0 +1,21 @@
# Open Graph (OG) Image Generation with Supabase Storage CDN Caching
Generate Open Graph images with Deno and Supabase Edge Functions and cache the generated image with Supabase Storage CDN.
- Docs: https://deno.land/x/og_edge@0.0.2
- Examples: https://vercel.com/docs/concepts/functions/edge-functions/og-image-examples
- Demo: https://obuldanrptloktxcffvn.functions.supabase.co/launchweek-ticket-og?ticketNumber=1234&username=thorwebdev&name=Thor%20%E9%9B%B7%E7%A5%9E%20Schaeff
## Run locally
```bash
supabase functions serve og-image-with-storage-cdn --no-verify-jwt
```
Navigate to http://localhost:54321/functions/v1/og-image-with-storage-cdn?ticketNumber=3524&username=thorwebdev&name=Thor%20%E9%9B%B7%E7%A5%9E%20Schaeff
## Deploy
```bash
supabase functions deploy og-image-with-storage-cdn --no-verify-jwt
```
@@ -0,0 +1,205 @@
import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0'
import { ImageResponse } from 'https://deno.land/x/og_edge@0.0.4/mod.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
import { corsHeaders } from '../_shared/cors.ts'
const STORAGE_URL = 'https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/lw6'
const BACKGROUND_IMAGE_STD = `${STORAGE_URL}/lw6_ticket_regular.jpg`
const BACKGROUND_IMAGE_GOLDEN = `${STORAGE_URL}/lw6_ticket_gold.jpg`
const SUPA_CHECKMARK = `${STORAGE_URL}/supaverified.png`
// Load custom font
const FONT_URL = `${STORAGE_URL}/CircularStd-Bold.otf`
const font = fetch(new URL(FONT_URL, import.meta.url)).then((res) => res.arrayBuffer())
export async function handler(req: Request) {
const url = new URL(req.url)
const ticketNumber = url.searchParams.get('ticketNumber')
const username = url.searchParams.get('username') ?? url.searchParams.get('amp;username')
const name = url.searchParams.get('name') ?? url.searchParams.get('amp;name')
const golden = url.searchParams.get('golden') ?? url.searchParams.get('amp;golden')
if (!username || !ticketNumber || !name)
return new Response(JSON.stringify({ error: 'missing params' }), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 400,
})
try {
// Try to get image from Supabase Storage CDN.
const storageResponse = await fetch(`${STORAGE_URL}/tickets/${username}.png?version=dev`) // TODO change for prod.
if (storageResponse.ok) return storageResponse
// Else, generate image ad upload to storage.
const fontData = await font
const numDigits = `${Number(ticketNumber)}`.length
const prefix = `00000000`.slice(numDigits)
const generatedImage = new ImageResponse(
(
<div
style={{
width: '2000px',
height: '1000px',
backgroundColor: '#000',
color: '#fff',
fontFamily: '"Circular"',
overflow: 'hidden',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
{/* Background image */}
<img
width="2000"
height="1000"
style={{
position: 'absolute',
top: '0',
left: '0',
zIndex: '-9000',
}}
src={golden ? BACKGROUND_IMAGE_GOLDEN : BACKGROUND_IMAGE_STD}
/>
{/* GitHub Avatar image */}
<img
width="270"
height="270"
style={{
position: 'absolute',
top: '360',
left: '460',
borderRadius: 135,
}}
src={`https://github.com/${username}.png`}
/>
{/* Name & username */}
<div
style={{
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
position: 'absolute',
top: '360',
left: '815',
width: '600',
height: '270',
overflow: 'hidden',
textOverflow: 'clip',
}}
>
<p
style={{
fontSize: '70',
lineHeight: 0.9,
}}
>
{name}
</p>
{/* Username and supaverified checkmark */}
<div
style={{
display: 'flex',
fontSize: '35',
}}
>
<span>{`@${username}`}</span>
<span
style={{
marginTop: '5',
marginLeft: '10',
}}
>
<img width="44" height="44" src={SUPA_CHECKMARK} />
</span>
</div>
</div>
{/* Date */}
<p
style={{
position: 'absolute',
top: '750',
left: '815',
fontSize: '25',
}}
>
December 12th, 2022
</p>
{/* URL */}
<p
style={{
position: 'absolute',
top: '750',
left: '1120',
fontSize: '25',
}}
>
supabase.com/launch-week
</p>
{/* Ticket No */}
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
bottom: '385',
right: '60',
width: '705',
height: '215',
transform: 'rotate(90deg)',
}}
>
<p
style={{
fontSize: '80',
}}
>
{`№ ${prefix}${ticketNumber}`}
</p>
</div>
</div>
),
{
width: 2000,
height: 1000,
fonts: [
{
name: 'Circular',
data: fontData,
style: 'normal',
},
],
headers: {
'content-type': 'image/png',
'cache-control': 'public, max-age=31536000, s-maxage=31536000, no-transform, immutable',
'cdn-cache-control': 'max-age=31536000',
},
}
)
const supabaseAdminClient = createClient(
// Supabase API URL - env var exported by default when deployed.
Deno.env.get('SUPABASE_URL') ?? '',
// Supabase API SERVICE ROLE KEY - env var exported by default when deployed.
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
)
// Upload image to storage.
const { error } = await supabaseAdminClient.storage
.from('images')
.upload(`lw6/tickets/${username}.png`, generatedImage.body!, {
// cacheControl: '31536000', // TODO add for prod
upsert: false,
})
if (error) throw error
return generatedImage
} catch (error) {
return new Response(JSON.stringify({ error: error.message }), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 400,
})
}
}
@@ -0,0 +1,11 @@
// Follow this setup guide to integrate the Deno language server with your editor:
// https://deno.land/manual/getting_started/setup_your_environment
// This enables autocomplete, go to definition, etc.
import { serve } from 'https://deno.land/std@0.140.0/http/server.ts'
import { handler } from './handler.tsx'
console.log(`Function "og-image-with-storage-cdn" up and running!`)
serve(handler)
@@ -5,6 +5,14 @@ Generate Open Graph images with Deno and Supabase Edge Functions, no framework n
- Docs: https://deno.land/x/og_edge@0.0.2
- Demo: https://zdtdtxajzydjqzuktnqx.functions.supabase.co/opengraph
## Run locally
```bash
supabase functions serve opengraph --no-verify-jwt
```
Navigate to http://localhost:54321/functions/v1/opengraph
## Deploy
```bash
@@ -1,7 +1,7 @@
import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0'
import { ImageResponse } from 'https://deno.land/x/og_edge@0.0.2/mod.ts'
import { ImageResponse } from 'https://deno.land/x/og_edge@0.0.4/mod.ts'
export async function handler(req: Request) {
export function handler(req: Request) {
return new ImageResponse(
(
<div
@@ -6,7 +6,6 @@ import { serve } from 'https://deno.land/std@0.140.0/http/server.ts'
import { handler } from './handler.tsx'
// @ts-ignore
serve(handler)
console.log(`Function "opengraph" up and running!`)
// To deploy: supabase functions deploy opengraph --no-verify-jwt
serve(handler)
@@ -4977,9 +4977,9 @@
}
},
"node_modules/engine.io": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz",
"integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz",
"integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==",
"dev": true,
"dependencies": {
"@types/cookie": "^0.4.1",
@@ -15688,9 +15688,9 @@
}
},
"engine.io": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz",
"integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz",
"integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==",
"dev": true,
"requires": {
"@types/cookie": "^0.4.1",
+9153 -10987
View File
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,108 @@
import HCaptcha from '@hcaptcha/react-hcaptcha'
import { useStore } from 'hooks'
import { auth } from 'lib/gotrue'
import { useRef, useState } from 'react'
import { useSWRConfig } from 'swr'
import { Button, Form, Input } from 'ui'
import { object, string } from 'yup'
const signInSchema = object({
email: string().email('Must be a valid email').required('Email is required'),
})
const SignInSSOForm = () => {
const { ui } = useStore()
const { cache } = useSWRConfig()
const [captchaToken, setCaptchaToken] = useState<string | null>(null)
const captchaRef = useRef<HCaptcha>(null)
const onSignIn = async ({ email, password }: { email: string; password: string }) => {
const toastId = ui.setNotification({
category: 'loading',
message: `Signing in...`,
})
let token = captchaToken
if (!token) {
const captchaResponse = await captchaRef.current?.execute({ async: true })
token = captchaResponse?.response ?? null
}
const { data, error } = await auth.signInWithSSO({
domain: email.split('@')[1],
options: { captchaToken: token ?? undefined },
})
if (!error) {
// .clear() does actually exist on the cache object, but it's not in the types 🤦🏻
// @ts-ignore
cache.clear()
if (data) {
// redirect to SSO identity provider page
window.location.href = data.url
}
} else {
captchaRef.current?.resetCaptcha()
ui.setNotification({
id: toastId,
category: 'error',
message: error.message,
})
}
}
return (
<Form
validateOnBlur
id="signIn-form"
initialValues={{ email: '' }}
validationSchema={signInSchema}
onSubmit={onSignIn}
>
{({ isSubmitting }: { isSubmitting: boolean }) => {
return (
<div className="flex flex-col gap-4">
<Input
id="email"
name="email"
type="email"
label="Email"
placeholder="gavin@hooli.com"
disabled={isSubmitting}
/>
<div className="self-center">
<HCaptcha
ref={captchaRef}
sitekey={process.env.NEXT_PUBLIC_HCAPTCHA_SITE_KEY!}
size="invisible"
onVerify={(token) => {
setCaptchaToken(token)
}}
onExpire={() => {
setCaptchaToken(null)
}}
/>
</div>
<Button
block
form="signIn-form"
htmlType="submit"
size="large"
disabled={isSubmitting}
loading={isSubmitting}
>
Sign In
</Button>
</div>
)
}}
</Form>
)
}
export default SignInSSOForm
@@ -0,0 +1,16 @@
import Link from 'next/link'
import { Button, IconLock } from 'ui'
const SignInWithSSO = () => {
return (
<Link href="/sign-in-sso">
<a>
<Button block size="large" type="outline" icon={<IconLock width={18} height={18} />}>
Continue with SSO
</Button>
</a>
</Link>
)
}
export default SignInWithSSO
@@ -455,8 +455,8 @@ const SupportForm: FC<Props> = ({ setSentCategory }) => {
id="message"
label="Message"
placeholder="Describe the issue you're facing, along with any relevant information. Please be as detailed and specific as possible."
limit={500}
labelOptional="500 character limit"
limit={5000}
labelOptional="5000 character limit"
/>
</div>
<div className="space-y-4 px-6">
@@ -71,7 +71,7 @@ const NotificationRow: FC<Props> = ({
)}
</div>
<div className="flex-grow mr-8 flex flex-col gap-4">
<div className="w-full flex justify-end">
<div className="w-full flex justify-between">
<div className="w-9/10 space-y-2">
{formatNotificationText(project, notification, ownerReassignStatus)}
{formatNotificationCTAText(availableActions, ownerReassignStatus)}
@@ -487,7 +487,7 @@ curl -X POST '${endpoint}/auth/v1/signup' \\
js: {
language: 'js',
code: `
let { user, error } = await supabase.auth.signUp({
let { data, error } = await supabase.auth.signUp({
email: 'someone@email.com',
password: '${randomPassword}'
})
@@ -511,7 +511,7 @@ curl -X POST '${endpoint}/auth/v1/token?grant_type=password' \\
js: {
language: 'js',
code: `
let { user, error } = await supabase.auth.signInWithPassword({
let { data, error } = await supabase.auth.signInWithPassword({
email: 'someone@email.com',
password: '${randomPassword}'
})
@@ -534,7 +534,7 @@ curl -X POST '${endpoint}/auth/v1/magiclink' \\
js: {
language: 'js',
code: `
let { user, error } = await supabase.auth.signInWithOtp({
let { data, error } = await supabase.auth.signInWithOtp({
email: 'someone@email.com'
})
`,
@@ -557,7 +557,7 @@ curl -X POST '${endpoint}/auth/v1/signup' \\
js: {
language: 'js',
code: `
let { user, error } = await supabase.auth.signUp({
let { data, error } = await supabase.auth.signUp({
phone: '+13334445555',
password: 'some-password'
})
@@ -580,7 +580,7 @@ curl -X POST '${endpoint}/auth/v1/otp' \\
js: {
language: 'js',
code: `
let { user, error } = await supabase.auth.signInWithOtp({
let { data, error } = await supabase.auth.signInWithOtp({
phone: '+13334445555'
})
`,
@@ -604,7 +604,7 @@ curl -X POST '${endpoint}/auth/v1/verify' \\
js: {
language: 'js',
code: `
let { session, error } = await supabase.auth.verifyOTP({
let { data, error } = await supabase.auth.verifyOTP({
phone: '+13334445555',
token: '123456'
})
@@ -641,7 +641,7 @@ let { data, error } = await supabase.auth.api.inviteUserByEmail('someone@email.c
js: {
language: 'js',
code: `
let { user, error } = await supabase.auth.signInWithOAuth({
let { data, error } = await supabase.auth.signInWithOAuth({
provider: 'github'
})
`,
@@ -660,7 +660,7 @@ curl -X GET '${endpoint}/auth/v1/user' \\
js: {
language: 'js',
code: `
const user = supabase.auth.user()
const { data: { user } } = await supabase.auth.getUser()
`,
},
}),
@@ -705,7 +705,7 @@ let { data, error } = await supabase.auth.api.resetPasswordForEmail(email)
js: {
language: 'js',
code: `
const { user, error } = await supabase.auth.update({
const { data, error } = await supabase.auth.updateUser({
email: "new@email.com",
password: "new-password",
data: { hello: 'world' }
-51111
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -28,7 +28,7 @@
"@supabase/postgres-meta": "^0.26.1",
"@supabase/react-data-grid": "^7.1.0-beta.7",
"@supabase/shared-types": "^0.1.29",
"@supabase/supabase-js": "^2.0.0",
"@supabase/supabase-js": "^2.1.0",
"ajv": "^8.6.3",
"analytics-node": "^3.5.0",
"awesome-debounce-promise": "^2.1.0",
+39
View File
@@ -0,0 +1,39 @@
import SignInSSOForm from 'components/interfaces/SignIn/SignInSSOForm'
import { SignInLayout } from 'components/layouts'
import Link from 'next/link'
import { NextPageWithLayout } from 'types'
const SignInSSOPage: NextPageWithLayout = () => {
return (
<>
<div className="flex flex-col gap-5">
<SignInSSOForm />
</div>
<div className="my-8 self-center text-sm">
<div>
<span className="text-scale-1000">Interested in SSO?</span>{' '}
<a
href="https://supabase.com/contact/enterprise"
rel="noopener noreferrer"
className="underline text-scale-1200 hover:text-scale-1100 transition"
>
Let Us Know
</a>
</div>
</div>
</>
)
}
SignInSSOPage.getLayout = (page) => (
<SignInLayout
heading="Welcome back"
subheading="Sign in to your enterprise account"
logoLinkToMarketingSite={true}
>
{page}
</SignInLayout>
)
export default SignInSSOPage
+8 -2
View File
@@ -1,14 +1,20 @@
import Link from 'next/link'
import { useFlag } from 'hooks'
import { NextPageWithLayout } from 'types'
import SignInForm from 'components/interfaces/SignIn/SignInForm'
import SignInWithGitHub from 'components/interfaces/SignIn/SignInWithGitHub'
import SignInWithSSO from 'components/interfaces/SignIn/SignInWithSSO'
import { SignInLayout } from 'components/layouts'
import Link from 'next/link'
import { NextPageWithLayout } from 'types'
const SignInPage: NextPageWithLayout = () => {
const showSsoLogin = useFlag('mfaSso')
return (
<>
<div className="flex flex-col gap-5">
<SignInWithGitHub />
{showSsoLogin && <SignInWithSSO />}
<div className="relative">
<div className="absolute inset-0 flex items-center">