mirror of
https://github.com/supabase/supabase.git
synced 2026-05-07 01:10:15 -04:00
Simplify the tanstack auth block.
This commit is contained in:
@@ -9,23 +9,7 @@ description: Supabase client for Tanstack Start
|
||||
|
||||
1. Follow the steps in /ui/docs/tanstack/password-based-auth to setup your repo.
|
||||
|
||||
2. Add the following property to your `createRootRoute` function:
|
||||
|
||||
```ts
|
||||
import { fetchUser } from "@/lib/supabase/fetch-user-server-fn";
|
||||
|
||||
...
|
||||
beforeLoad: async () => {
|
||||
const user = await fetchUser();
|
||||
|
||||
return {
|
||||
user,
|
||||
};
|
||||
},
|
||||
...
|
||||
```
|
||||
|
||||
3. Try to access the /info route, you should be redirected to login screen. If you create an account and try accessing the /info page, you should see your email.
|
||||
2. Try to access the /info route, you should be redirected to login screen. If you create an account and login and try accessing the /info page, you should see your email.
|
||||
|
||||
## Folder structure
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
},
|
||||
{
|
||||
"path": "registry/default/blocks/password-based-auth-tanstack/routes/_protected.tsx",
|
||||
"content": "import { createFileRoute, redirect } from '@tanstack/react-router'\n\nexport const Route = createFileRoute('/_protected')({\n beforeLoad: ({ context }) => {\n if (!context.user) {\n throw redirect({ to: '/login' })\n }\n },\n})\n",
|
||||
"content": "import { fetchUser } from '@/registry/default/blocks/password-based-auth-tanstack/lib/supabase/fetch-user-server-fn'\nimport { createFileRoute, redirect } from '@tanstack/react-router'\n\nexport const Route = createFileRoute('/_protected')({\n beforeLoad: async () => {\n const user = await fetchUser()\n\n if (!user) {\n throw redirect({ to: '/login' })\n }\n\n return {\n user,\n }\n },\n})\n",
|
||||
"type": "registry:file",
|
||||
"target": "routes/_protected.tsx"
|
||||
},
|
||||
@@ -41,7 +41,7 @@
|
||||
},
|
||||
{
|
||||
"path": "registry/default/blocks/password-based-auth-tanstack/routes/auth/confirm.ts",
|
||||
"content": "import { createClient } from '@/registry/default/clients/tanstack/lib/supabase/server'\nimport { type EmailOtpType } from '@supabase/supabase-js'\nimport { createFileRoute, redirect } from '@tanstack/react-router'\nimport { createServerFn } from '@tanstack/react-start'\nimport { getWebRequest } from '@tanstack/react-start/server'\n\nconst confirmFn = createServerFn({ method: 'GET' })\n .validator((searchParams: unknown) => {\n if (\n searchParams &&\n typeof searchParams === 'object' &&\n 'token_hash' in searchParams &&\n 'type' in searchParams &&\n 'next' in searchParams\n ) {\n return searchParams\n }\n throw new Error('Invalid search params')\n })\n .handler(async (ctx) => {\n const request = getWebRequest()\n\n if (!request) {\n throw redirect({ to: `/auth/error`, params: { error: 'No request' } })\n }\n\n const searchParams = ctx.data\n const token_hash = searchParams['token_hash'] as string\n const type = searchParams['type'] as EmailOtpType | null\n const next = (searchParams['next'] ?? '/') as string\n\n if (token_hash && type) {\n const supabase = createClient()\n\n const { error } = await supabase.auth.verifyOtp({\n type,\n token_hash,\n })\n console.log(error?.message)\n if (!error) {\n // redirect user to specified redirect URL or root of app\n throw redirect({ href: next })\n } else {\n // redirect the user to an error page with some instructions\n throw redirect({\n to: `/auth/error`,\n params: { error: error?.message },\n })\n }\n }\n\n // redirect the user to an error page with some instructions\n throw redirect({\n to: `/auth/error`,\n params: { error: 'No token hash or type' },\n })\n })\n\nexport const Route = createFileRoute('/auth/confirm')({\n preload: false,\n loader: (opts) => confirmFn({ data: opts.location.search }),\n})\n",
|
||||
"content": "import { createClient } from '@/registry/default/clients/tanstack/lib/supabase/server'\nimport { type EmailOtpType } from '@supabase/supabase-js'\nimport { createFileRoute, redirect } from '@tanstack/react-router'\nimport { createServerFn } from '@tanstack/react-start'\nimport { getWebRequest } from '@tanstack/react-start/server'\n\nconst confirmFn = createServerFn({ method: 'GET' })\n .validator((searchParams: unknown) => {\n if (\n searchParams &&\n typeof searchParams === 'object' &&\n 'token_hash' in searchParams &&\n 'type' in searchParams &&\n 'next' in searchParams\n ) {\n return searchParams\n }\n throw new Error('Invalid search params')\n })\n .handler(async (ctx) => {\n const request = getWebRequest()\n\n if (!request) {\n throw redirect({ to: `/auth/error`, search: { error: 'No request' } })\n }\n\n const searchParams = ctx.data\n const token_hash = searchParams['token_hash'] as string\n const type = searchParams['type'] as EmailOtpType | null\n const next = (searchParams['next'] ?? '/') as string\n\n if (token_hash && type) {\n const supabase = createClient()\n\n const { error } = await supabase.auth.verifyOtp({\n type,\n token_hash,\n })\n console.log(error?.message)\n if (!error) {\n // redirect user to specified redirect URL or root of app\n throw redirect({ href: next })\n } else {\n // redirect the user to an error page with some instructions\n throw redirect({\n to: `/auth/error`,\n search: { error: error?.message },\n })\n }\n }\n\n // redirect the user to an error page with some instructions\n throw redirect({\n to: `/auth/error`,\n search: { error: 'No token hash or type' },\n })\n })\n\nexport const Route = createFileRoute('/auth/confirm')({\n preload: false,\n loader: (opts) => confirmFn({ data: opts.location.search }),\n})\n",
|
||||
"type": "registry:file",
|
||||
"target": "routes/auth/confirm.ts"
|
||||
},
|
||||
|
||||
+9
-2
@@ -1,9 +1,16 @@
|
||||
import { fetchUser } from '@/registry/default/blocks/password-based-auth-tanstack/lib/supabase/fetch-user-server-fn'
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/_protected')({
|
||||
beforeLoad: ({ context }) => {
|
||||
if (!context.user) {
|
||||
beforeLoad: async () => {
|
||||
const user = await fetchUser()
|
||||
|
||||
if (!user) {
|
||||
throw redirect({ to: '/login' })
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@ const confirmFn = createServerFn({ method: 'GET' })
|
||||
const request = getWebRequest()
|
||||
|
||||
if (!request) {
|
||||
throw redirect({ to: `/auth/error`, params: { error: 'No request' } })
|
||||
throw redirect({ to: `/auth/error`, search: { error: 'No request' } })
|
||||
}
|
||||
|
||||
const searchParams = ctx.data
|
||||
@@ -44,7 +44,7 @@ const confirmFn = createServerFn({ method: 'GET' })
|
||||
// redirect the user to an error page with some instructions
|
||||
throw redirect({
|
||||
to: `/auth/error`,
|
||||
params: { error: error?.message },
|
||||
search: { error: error?.message },
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ const confirmFn = createServerFn({ method: 'GET' })
|
||||
// redirect the user to an error page with some instructions
|
||||
throw redirect({
|
||||
to: `/auth/error`,
|
||||
params: { error: 'No token hash or type' },
|
||||
search: { error: 'No token hash or type' },
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user