我目前正在开展一个项目,涉及与下院建立苏帕基·奥特。 我收到了Supabase提供的文件(https://supabase.com/docs/guides/auth/auth-helpers/nextjs-pages ),以便将认证功能纳入我的项目。
然而,在将来源档案从目录转换为网页目录时,我遇到了困难。 我把我的网页目录与其他人合并,从目录中排出,因为我更加舒适地在页面上编码。
为了提供更多有关我问题的背景和详细情况,我记录了我的Gite/2007/5存放处的步骤和编码变化:。 你可以在读物档案中找到具体问题。
My main goal with this project is to create a project pages directory with Supabase Auth and database integration using Next.js and React.js. This setup should allow users to log in with their email and password or via OAuth/Social Auth using the "@supabase/auth-ui-react" library.
此外,我还寻求指导如何使用保护网页的中间信息,确保只有经认证的用户才能查阅某些网页。
注:“一切照旧”在无“申请”档案的情况下工作,但由于需要,我想这样做。
- 申请。
import { createPagesBrowserClient } from @supabase/auth-helpers-nextjs
import { SessionContextProvider, Session } from @supabase/auth-helpers-react
import { useState } from react
import { AppProps } from next/app
function MyApp({
Component,
pageProps,
}: AppProps<{
initialSession: Session
}>) {
// Create a new supabase browser client on every first render.
const [supabaseClient] = useState(() => createPagesBrowserClient())
return (
<SessionContextProvider
supabaseClient={supabaseClient}
initialSession={pageProps.initialSession}
>
<Component {...pageProps} />
</SessionContextProvider>
)
}
中级知识。
import { createMiddlewareClient } from @supabase/auth-helpers-nextjs
import { NextResponse } from next/server
import type { NextRequest } from next/server
export async function middleware(req: NextRequest) {
const res = NextResponse.next()
const supabase = createMiddlewareClient({ req, res })
const {
data: { user },
} = await supabase.auth.getUser()
// if user is signed in and the current path is / redirect the user to /account
if (user && req.nextUrl.pathname === /login ) {
return NextResponse.redirect(new URL( /account , req.url))
}
// if user is not signed in and the current path is not / redirect the user to /
if (!user && req.nextUrl.pathname !== /login ) {
return NextResponse.redirect(new URL( /login , req.url))
}
return res
}
export const config = {
matcher: [ / , /account ],
}
页: 1
import AuthForm from ../../components/auth/auth-form
export default function Login() {
return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 h-screen">
<div className="flex flex-col justify-center">
<div className="text-center mx-auto md:max-w-2xl">
<h1 className="header">Supabase Auth + Storage</h1>
<p>
Experience our Auth and Storage through a simple profile management example. Create a user profile and
upload an avatar image. Fast, simple, secure.
</p>
</div>
</div>
<div className="flex flex-col justify-center">
<div className="mx-auto w-1/2">
<AuthForm />
</div>
</div>
</div>
)
}
页: 1
use client
import { Auth } from @supabase/auth-ui-react
import { ThemeSupa } from @supabase/auth-ui-shared
import { createClientComponentClient } from @supabase/auth-helpers-nextjs
import { Database } from ../../types/database.types
export default function AuthForm() {
const supabase = createClientComponentClient<Database>()
return (
<Auth
supabaseClient={supabase}
view="magic_link"
appearance={{ theme: ThemeSupa }}
theme="dark"
showLinks={false}
providers={[ discord ]}
redirectTo="http://localhost:3000/api/auth/callback"
/>
)
}
页: 1
import { NextApiHandler } from next
import { createPagesServerClient } from @supabase/auth-helpers-nextjs
const handler: NextApiHandler = async (req, res) => {
const { code } = req.query
if (code) {
const supabase = createPagesServerClient({ req, res })
await supabase.auth.exchangeCodeForSession(String(code))
}
res.redirect( /account )
}
export default handler
页: 1
import { createPagesServerClient } from @supabase/auth-helpers-nextjs
export default function Profile({ user }) {
console.log(user)
return <div>Hello {user.user_metadata.name}</div>
}
export const getServerSideProps = async (ctx) => {
// Create authenticated Supabase Client
const supabase = createPagesServerClient(ctx)
// Check if we have a session
const {
data: { session },
} = await supabase.auth.getSession()
if (!session)
return {
redirect: {
destination: / ,
permanent: false,
},
}
return {
props: {
initialSession: session,
user: session.user,
},
}
}
页: 1
use client
import { useCallback, useEffect, useState } from react
import { Database } from ../../types/database.types
import { Session, createClientComponentClient } from @supabase/auth-helpers-nextjs
export default function AccountForm({ session }: { session: Session | null }) {
const supabase = createClientComponentClient<Database>()
const [loading, setLoading] = useState(true)
const [fullname, setFullname] = useState<string | null>(null)
const [username, setUsername] = useState<string | null>(null)
const [avatar_url, setAvatarUrl] = useState<string | null>(null)
const user = session?.user
const getProfile = useCallback(async () => {
try {
setLoading(true)
let { data, error, status } = await supabase
.from( profiles )
.select(`full_name, username, avatar_url`)
.eq( id , user?.id)
.single()
if (error && status !== 406) {
throw error
}
if (data) {
setFullname(data.full_name)
setUsername(data.username)
setAvatarUrl(data.avatar_url)
}
} catch (error) {
alert( Error loading user data! )
} finally {
setLoading(false)
}
}, [user, supabase])
useEffect(() => {
getProfile()
}, [user, getProfile])
async function updateProfile({
username,
avatar_url,
}: {
username: string | null
fullname: string | null
avatar_url: string | null
}) {
try {
setLoading(true)
let { error } = await supabase.from( profiles ).upsert({
id: user?.id as string,
full_name: fullname,
username,
avatar_url,
updated_at: new Date().toISOString(),
})
if (error) throw error
alert( Profile updated! )
} catch (error) {
alert( Error updating the data! )
} finally {
setLoading(false)
}
}
return (
<div className="form-widget p-4 rounded-md w-1/2 mx-auto">
<div className="mb-4">
<label htmlFor="email" className="text-sm font-medium text-gray-700">Email</label>
<input
id="email"
type="text"
value={session?.user.email}
disabled
className="w-full px-3 py-2 mt-1 border border-gray-300 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 text-black"
/>
</div>
<div className="mb-4">
<label htmlFor="fullName" className="text-sm font-medium text-gray-700">Full Name</label>
<input
id="fullName"
type="text"
value={fullname || }
onChange={(e) => setFullname(e.target.value)}
className="w-full px-3 py-2 mt-1 border border-gray-300 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 text-black"
/>
</div>
<div className="mb-4">
<label htmlFor="username" className="text-sm font-medium text-gray-700">Username</label>
<input
id="username"
type="text"
value={username || }
onChange={(e) => setUsername(e.target.value)}
className="w-full px-3 py-2 mt-1 border border-gray-300 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 text-black"
/>
</div>
<div className="mb-4">
<button
className="w-full px-4 py-2 text-white bg-blue-500 rounded-md hover:bg-blue-600"
onClick={() => updateProfile({ fullname, username, avatar_url })}
disabled={loading}
>
{loading ? Loading ... : Update }
</button>
</div>
<div>
<form action="/auth/signout" method="post">
<button
className="w-full px-4 py-2 text-gray-700 bg-gray-300 rounded-md hover:bg-gray-400"
type="submit"
>
Sign out
</button>
</form>
</div>
</div>
);
}
页: 1
const Home = () => {
return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 h-screen">
<div className="flex flex-col justify-center">
<div className="text-center mx-auto md:max-w-2xl">
<h1 className="header">You are home</h1>
</div>
</div>
</div>
)
}
export default Home