feat: create login page

This commit is contained in:
0xzion
2023-12-29 20:36:25 +08:00
parent 35bbf9433d
commit f328f8061c
3 changed files with 145 additions and 12 deletions

View File

@@ -0,0 +1,44 @@
import { useEffect, useState } from 'react'
import { Box } from '@fower/react'
import { signIn } from 'next-auth/react'
import { useSearchParams } from 'next/navigation'
import { toast } from 'sonner'
import { Button, Spinner } from 'uikit'
import { IconGoogle } from '@penx/icons'
export default function LoginWithGoogleButton() {
const [loading, setLoading] = useState(false)
// Get error message added by next/auth in URL.
const searchParams = useSearchParams()
const error = searchParams?.get('error')
useEffect(() => {
const errorMessage = Array.isArray(error) ? error.pop() : error
errorMessage && toast.error(errorMessage)
}, [error])
return (
<Button
disabled={loading}
size="lg"
colorScheme="white"
onClick={() => {
setLoading(true)
signIn('google', { callbackUrl: `/editor` })
}}
cursorNotAllowed={loading}
gapX2
w-240
>
{loading ? (
<Spinner />
) : (
<>
<IconGoogle />
<Box>Login with Google</Box>
</>
)}
</Button>
)
}

View File

@@ -1,10 +1,11 @@
import { PrismaAdapter } from '@next-auth/prisma-adapter'
import NextAuth from 'next-auth'
import { JWT } from 'next-auth/jwt'
import jwt from 'jsonwebtoken'
import NextAuth, { NextAuthOptions } from 'next-auth'
import { encode, JWT } from 'next-auth/jwt'
import GoogleProvider from 'next-auth/providers/google'
import { prisma } from '@penx/db'
export default NextAuth({
export const authOptions: NextAuthOptions = {
// Configure one or more authentication providers
providers: [
GoogleProvider({
@@ -23,14 +24,32 @@ export default NextAuth({
adapter: PrismaAdapter(prisma),
pages: {
signIn: `/`,
verifyRequest: `/`,
error: '/', // Error code passed in query string as ?error=
signIn: `/login`,
verifyRequest: `/login`,
error: '/login', // Error code passed in query string as ?error=
},
// jwt: {
// maxAge: 30 * 24 * 30 * 60,
// decode: async ({ token, secret }) => {
// console.log('============dencode token', token, 'secret', secret)
// const result = jwt.verify(token!, secret)
// console.log('========result:', result)
// return result
// },
// encode: async ({ token, secret }) => {
// console.log('encode token', token, 'secret', secret)
// const encoded = jwt.sign(token!, secret, { algorithm: 'HS256' })
// console.log('========encoded:', encoded)
// return encoded
// },
// },
callbacks: {
async signIn({ user, account, profile }) {
console.log('user, account:', user, 'account:', account)
// console.log('============user:', user, 'account:', account)
// await initSpace(user.id, user.name!)
return true
},
@@ -44,12 +63,15 @@ export default NextAuth({
if (account) {
// Save the access token and refresh token in the JWT on the initial login
return {
const jwt: JWT = {
...token,
accessToken: account.access_token,
accessToken: account.access_token!,
expiresAt: Math.floor(Date.now() / 1000 + account.expires_at!),
refreshToken: account.refresh_token,
} as JWT
refreshToken: account.refresh_token!,
}
// console.log('==============jwt:', jwt)
return jwt
}
return token
},
@@ -58,7 +80,12 @@ export default NextAuth({
session.accessToken = token.accessToken as string
session.userId = token.uid as string
;(session.user as any).id = token.uid
// console.log('session:', session, 'token:', token)
return session
},
},
})
}
export default NextAuth(authOptions)

View File

@@ -0,0 +1,62 @@
import { Suspense } from 'react'
import { Box } from '@fower/react'
import { GetServerSideProps } from 'next'
import { getServerSession } from 'next-auth'
import LoginWithGoogleButton from '~/components/LoginWithGoogleButton'
import { Logo } from '~/components/Logo'
import { authOptions } from './api/auth/[...nextauth]'
export default function LoginPage() {
return (
<Box column h-100vh>
<Box mx-auto py8 toCenter>
<Logo to="/" />
</Box>
<Box column flex-1 toCenter>
<Box
toCenter
py10
roundedXL
mx-auto
bgWhite
column
mt--200
w={['100%', '100%', 480]}
>
<Box as="h1" fontBold>
Welcome to PenX
</Box>
<Box as="p" textCenter mb6 leadingNormal px10 gray500>
PenX is an open-source collaborative editor to manage Markdown
content
</Box>
<Box column gap4>
<Suspense fallback={<Box my2 h10 w-100p border borderStone200 />}>
<LoginWithGoogleButton />
</Suspense>
</Box>
{/* <Box pt6>
You can also <Box as="a"> continue with SAML SSO</Box>
</Box> */}
</Box>
</Box>
</Box>
)
}
export const getServerSideProps: GetServerSideProps = async function (context) {
const session = await getServerSession(context.req, context.res, authOptions)
if (session) {
return {
redirect: {
destination: '/editor',
permanent: false,
},
}
}
return {
props: {},
}
}