chore: simplify next-auth (#80)

This commit is contained in:
Balázs Orbán 2023-06-27 20:03:01 +02:00 committed by GitHub
parent 5912336152
commit 012ea40414
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 55 additions and 116 deletions

View file

@ -2,17 +2,15 @@
## Then get your OpenAI API Key here: https://platform.openai.com/account/api-keys
OPENAI_API_KEY=XXXXXXXX
## Generate a random secret: https://generate-secret.vercel.app/32
NEXTAUTH_SECRET=XXXXXXXX
## Only required for localhost
NEXTAUTH_URL=http://localhost:3000
## Generate a random secret: https://generate-secret.vercel.app/32 or `openssl rand -base64 32`
AUTH_SECRET=XXXXXXXX
## Create a GitHub OAuth app here: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app
AUTH_GITHUB_ID=XXXXXXXX
AUTH_GITHUB_SECRET=XXXXXXXX
## Support OAuth login on preview deployments, see: https://authjs.dev/guides/basics/deployment#securing-a-preview-deployment
AUTH_REDIRECT_PROXY_URL=https://auth.example.com/api/auth
# instructions to create kv database here: https://vercel.com/docs/storage/vercel-kv/quickstart and
# Instructions to create kv database here: https://vercel.com/docs/storage/vercel-kv/quickstart and
KV_URL=XXXXXXXX
KV_REST_API_URL=XXXXXXXX
KV_REST_API_TOKEN=XXXXXXXX

View file

@ -1 +1,2 @@
export { GET, POST } from '@/auth'
export const runtime = 'edge'

View file

@ -16,9 +16,9 @@ const openai = new OpenAIApi(configuration)
export async function POST(req: Request) {
const json = await req.json()
const { messages, previewToken } = json
const session = await auth()
const userId = (await auth())?.user.id
if (session == null) {
if (!userId) {
return new Response('Unauthorized', {
status: 401
})
@ -38,31 +38,28 @@ export async function POST(req: Request) {
const stream = OpenAIStream(res, {
async onCompletion(completion) {
const title = json.messages[0].content.substring(0, 100)
const userId = session?.user?.id
if (userId) {
const id = json.id ?? nanoid()
const createdAt = Date.now()
const path = `/chat/${id}`
const payload = {
id,
title,
userId,
createdAt,
path,
messages: [
...messages,
{
content: completion,
role: 'assistant'
}
]
}
await kv.hmset(`chat:${id}`, payload)
await kv.zadd(`user:chat:${userId}`, {
score: createdAt,
member: `chat:${id}`
})
const id = json.id ?? nanoid()
const createdAt = Date.now()
const path = `/chat/${id}`
const payload = {
id,
title,
userId,
createdAt,
path,
messages: [
...messages,
{
content: completion,
role: 'assistant'
}
]
}
await kv.hmset(`chat:${id}`, payload)
await kv.zadd(`user:chat:${userId}`, {
score: createdAt,
member: `chat:${id}`
})
}
})

63
auth.ts
View file

@ -1,64 +1,35 @@
import NextAuth from 'next-auth'
import NextAuth, { type DefaultSession } from 'next-auth'
import GitHub from 'next-auth/providers/github'
import CredentialsProvider from 'next-auth/providers/credentials'
import { NextResponse } from 'next/server'
// We default to using GitHub for authentication for local development and production.
// On Preview deployments, we use a dummy credentials provider. This allows folks to easily
// test the app without having to create a custom GitHub OAuth app or change the callback URL
// just to test the application on previews.
declare module 'next-auth' {
interface Session {
user: {
/** The user's id. */
id: string
} & DefaultSession['user']
}
}
// We have a custom /sign-in page for non-preview environments. In preview environments, the user
// will be redirected to /api/auth/signin instead.
export const {
handlers: { GET, POST },
auth,
CSRF_experimental
// @ts-ignore
} = NextAuth({
// @ts-ignore
providers: [
process.env.VERCEL_ENV === 'preview'
? CredentialsProvider({
name: 'Credentials',
credentials: {
username: {
label: 'Username',
type: 'text',
placeholder: 'jsmith'
},
password: { label: 'Password', type: 'password' }
},
async authorize(credentials) {
return {
id: 1,
name: 'J Smith',
email: 'jsmith@example.com',
picture: 'https://i.pravatar.cc/150?u=jsmith@example.com'
} as any
}
})
: GitHub
],
providers: [GitHub],
callbacks: {
// @ts-ignore
jwt: async ({ token, profile }) => {
if (profile?.id) {
jwt({ token, profile }) {
if (profile) {
token.id = profile.id
token.image = profile.picture
}
return token
},
// @ts-ignore
authorized({ auth }) {
return !!auth?.user
},
trustHost: true
}
},
...(process.env.VERCEL_ENV === 'preview'
? {}
: {
pages: {
signIn: '/sign-in'
}
})
pages: {
signIn: '/sign-in'
}
})

View file

@ -1,5 +1,5 @@
export { auth as middleware } from './auth'
export const config = {
matcher: ['/', '/api/chat']
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)']
}

13
next-auth.d.ts vendored
View file

@ -1,13 +0,0 @@
import NextAuth, { DefaultSession } from 'next-auth'
declare module 'next-auth' {
/**
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
*/
interface Session {
user: {
/** The user's postal address. */
id: string
} & DefaultSession['user']
}
}

View file

@ -32,7 +32,7 @@
"focus-trap-react": "^10.1.1",
"nanoid": "^4.0.2",
"next": "13.4.7-canary.1",
"next-auth": "0.0.0-manual.e65faa1c",
"next-auth": "0.0.0-manual.83c4ebd1",
"next-themes": "^0.2.1",
"openai-edge": "^0.5.1",
"react": "^18.2.0",

29
pnpm-lock.yaml generated
View file

@ -60,8 +60,8 @@ dependencies:
specifier: 13.4.7-canary.1
version: 13.4.7-canary.1(react-dom@18.2.0)(react@18.2.0)
next-auth:
specifier: 0.0.0-manual.e65faa1c
version: 0.0.0-manual.e65faa1c(next@13.4.7-canary.1)(react-dom@18.2.0)(react@18.2.0)
specifier: 0.0.0-manual.83c4ebd1
version: 0.0.0-manual.83c4ebd1(next@13.4.7-canary.1)(react@18.2.0)
next-themes:
specifier: ^0.2.1
version: 0.2.1(next@13.4.7-canary.1)(react-dom@18.2.0)(react@18.2.0)
@ -172,19 +172,6 @@ packages:
preact-render-to-string: 5.2.3(preact@10.11.3)
dev: false
/@auth/nextjs@0.0.0-manual.179c08d4(next@13.4.7-canary.1)(react@18.2.0):
resolution: {integrity: sha512-HVuDgb6xlYLV5mHTGc0Pycg8BlwtcvjvS+54QXEbOBpA5tulzKxAH8QlCoKj5R9XHW9hP9DiCnvXyVV9x2N+jA==}
peerDependencies:
next: ^13.4.6
react: ^18.2.0
dependencies:
'@auth/core': 0.0.0-manual.8fcd46b0
next: 13.4.7-canary.1(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
transitivePeerDependencies:
- nodemailer
dev: false
/@babel/helper-string-parser@7.22.5:
resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==}
engines: {node: '>=6.9.0'}
@ -3696,21 +3683,19 @@ packages:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
dev: true
/next-auth@0.0.0-manual.e65faa1c(next@13.4.7-canary.1)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-I51GvhZhZEf/gzhiTKivYPAIyZ74sCF3YXAMMuZ/bjahybeehPEu7opcPEA+H0Uxrvmo2G8/BQ7mT+TiFdM9IQ==}
/next-auth@0.0.0-manual.83c4ebd1(next@13.4.7-canary.1)(react@18.2.0):
resolution: {integrity: sha512-6nUXtVrZqTWvVz2NhUB/xbMyzxUSQycQWOquACwdpk63AcnZ3g01v+W0UX9paqkGIdqLPtI/pL6rA2N+MT58SQ==}
peerDependencies:
next: ^13.4.5
next: ^13.4.6
nodemailer: ^6.6.5
react: ^17.0.2 || ^18
react-dom: ^17.0.2 || ^18
react: ^18.2.0
peerDependenciesMeta:
nodemailer:
optional: true
dependencies:
'@auth/nextjs': 0.0.0-manual.179c08d4(next@13.4.7-canary.1)(react@18.2.0)
'@auth/core': 0.0.0-manual.8fcd46b0
next: 13.4.7-canary.1(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/next-themes@0.2.1(next@13.4.7-canary.1)(react-dom@18.2.0)(react@18.2.0):