Move to next-auth

This commit is contained in:
Jared Palmer 2023-05-22 10:16:09 -04:00
parent 3b8bb9dea4
commit a46b2ac3c6
10 changed files with 107 additions and 20 deletions

View file

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

View file

@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
import { Chat } from "../../chat"; import { Chat } from "../../chat";
import { type Metadata } from "next"; import { type Metadata } from "next";
import { getServerSession } from "@/lib/session/get-server-session"; import { auth } from "@/auth";
export interface ChatPageProps { export interface ChatPageProps {
params: { params: {
@ -29,7 +29,7 @@ export const runtime = "nodejs"; // default
export const preferredRegion = "home"; export const preferredRegion = "home";
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
export default async function ChatPage({ params }: ChatPageProps) { export default async function ChatPage({ params }: ChatPageProps) {
const session = await getServerSession(); const session = await auth();
const chat = await prisma.chat.findFirst({ const chat = await prisma.chat.findFirst({
where: { where: {
id: params.id, id: params.id,

View file

@ -1,6 +1,6 @@
import { getServerSession } from "@/lib/session/get-server-session";
import { Chat } from "./chat"; import { Chat } from "./chat";
import { Sidebar } from "./sidebar"; import { Sidebar } from "./sidebar";
import { auth } from "@/auth";
// Prisma does not support Edge without the Data Proxy currently // Prisma does not support Edge without the Data Proxy currently
export const runtime = "nodejs"; // default export const runtime = "nodejs"; // default
@ -8,7 +8,7 @@ export const preferredRegion = "home";
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
export default async function IndexPage() { export default async function IndexPage() {
const session = await getServerSession(); const session = await auth();
return ( return (
<div className="relative flex h-full w-full overflow-hidden"> <div className="relative flex h-full w-full overflow-hidden">
<Sidebar session={session} newChat /> <Sidebar session={session} newChat />

View file

@ -2,7 +2,7 @@ import { NextChatLogo } from "@/components/ui/nextchat-logo";
import { Login } from "@/components/ui/login"; import { Login } from "@/components/ui/login";
import { UserMenu } from "@/components/ui/user-menu"; import { UserMenu } from "@/components/ui/user-menu";
import { prisma } from "@/lib/prisma"; import { prisma } from "@/lib/prisma";
import { type Session } from "@/lib/session/types"; import { type Session } from "@auth/nextjs/types";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Plus } from "lucide-react"; import { Plus } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
@ -70,7 +70,8 @@ async function SidebarList({ session }: { session?: Session }) {
updatedAt: "desc", updatedAt: "desc",
}, },
}), }),
[session?.user.id || ""], // @ts-ignore
[session?.user?.id || ""],
{ {
revalidate: 3600, revalidate: 3600,
} }

26
auth.ts Normal file
View file

@ -0,0 +1,26 @@
import NextAuth from "@auth/nextjs";
import GitHub from "@auth/nextjs/providers/github";
import { NextResponse } from "next/server";
export const {
handlers: { GET, POST },
auth,
CSRF_experimental,
} = NextAuth({
// @ts-ignore
providers: [GitHub],
session: { strategy: "jwt" },
async authorized({ request, auth }: any) {
const url = request.nextUrl;
if (request.method === "POST") {
const { authToken } = (await request.json()) ?? {};
// If the request has a valid auth token, it is authorized
const valid = true;
if (valid) return true;
return NextResponse.json("Invalid auth token", { status: 401 });
}
// Logged in users are authenticated, otherwise redirect to login page
return !!auth;
},
});

View file

@ -1,14 +1,13 @@
"use client"; "use client";
import { signIn } from "@auth/nextjs/client";
import Link from "next/link";
export function Login() { export function Login() {
return ( return (
<Link <button
className="inline-flex w-full items-center justify-center rounded border border-zinc-800 bg-white h-8 px-4 -my-1.5 text-sm leading-6 tracking-tight text-zinc-900 transition-colors ease-in-out hover:bg-zinc-100 disabled:cursor-not-allowed disabled:opacity-50" className="inline-flex w-full items-center justify-center rounded border border-zinc-800 bg-white h-8 px-4 -my-1.5 text-sm leading-6 tracking-tight text-zinc-900 transition-colors ease-in-out hover:bg-zinc-100 disabled:cursor-not-allowed disabled:opacity-50"
href="/api/auth/login?next=/?s=1" onClick={() => signIn("github")}
> >
<span className="font-medium">Login</span> <span className="font-medium">Login</span>
</Link> </button>
); );
} }

View file

@ -1,7 +1,9 @@
"use client"; "use client";
import { ThemeToggle } from "@/components/theme-toggle"; import { ThemeToggle } from "@/components/theme-toggle";
import { type Session } from "@/lib/session/types"; import { type Session } from "@auth/nextjs/types";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { signOut } from "@auth/nextjs/client";
import Image from "next/image"; import Image from "next/image";
export interface UserMenuProps { export interface UserMenuProps {
@ -14,12 +16,12 @@ export function UserMenu({ session }: UserMenuProps) {
<DropdownMenu.Root> <DropdownMenu.Root>
<DropdownMenu.Trigger asChild> <DropdownMenu.Trigger asChild>
<button className="focus:outline-none"> <button className="focus:outline-none">
{session.user?.avatar ? ( {session.user?.image ? (
<Image <Image
width={24} width={24}
height={24} height={24}
className="h-6 w-6 rounded-full select-none ring-zinc-100/10 ring-1 hover:opacity-80 transition-opacity duration-300" className="h-6 w-6 rounded-full select-none ring-zinc-100/10 ring-1 hover:opacity-80 transition-opacity duration-300"
src={session.user?.avatar ? `${session.user.avatar}&s=60` : ""} src={session.user?.image ? `${session.user.image}&s=60` : ""}
alt={session.user.name ?? "Avatar"} alt={session.user.name ?? "Avatar"}
/> />
) : ( ) : (
@ -81,9 +83,7 @@ export function UserMenu({ session }: UserMenuProps) {
</DropdownMenu.Item> </DropdownMenu.Item>
<DropdownMenu.Item <DropdownMenu.Item
className="py-2 px-3 hover:bg-zinc-200 dark:hover:bg-zinc-800 transition-colors duration-200 cursor-pointer text-xs focus:outline-none" className="py-2 px-3 hover:bg-zinc-200 dark:hover:bg-zinc-800 transition-colors duration-200 cursor-pointer text-xs focus:outline-none"
onClick={() => { onClick={() => signOut()}
window.location.href = "/api/auth/logout";
}}
> >
Log Out Log Out
</DropdownMenu.Item> </DropdownMenu.Item>
@ -94,4 +94,4 @@ export function UserMenu({ session }: UserMenuProps) {
); );
} }
UserMenu.displayName = "Signout"; UserMenu.displayName = "UserMenu";

1
middleware.ts Normal file
View file

@ -0,0 +1 @@
export { auth as middleware } from "./auth";

View file

@ -15,7 +15,8 @@
"format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache" "format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache"
}, },
"dependencies": { "dependencies": {
"@next-auth/prisma-adapter": "^1.0.6", "@auth/nextjs": "0.0.0-manual.030e8328",
"@next-auth/prisma-adapter": "1.0.6",
"@prisma/client": "^4.14.0", "@prisma/client": "^4.14.0",
"@radix-ui/react-dropdown-menu": "^2.0.4", "@radix-ui/react-dropdown-menu": "^2.0.4",
"@vercel/analytics": "^1.0.0", "@vercel/analytics": "^1.0.0",
@ -69,5 +70,10 @@
"prisma": "^4.14.0", "prisma": "^4.14.0",
"tailwindcss": "^3.3.1", "tailwindcss": "^3.3.1",
"typescript": "^4.9.3" "typescript": "^4.9.3"
},
"pnpm": {
"overrides": {
"@auth/core": "0.0.0-manual.527fff6c"
}
} }
} }

54
pnpm-lock.yaml generated
View file

@ -1,8 +1,14 @@
lockfileVersion: '6.0' lockfileVersion: '6.0'
overrides:
'@auth/core': 0.0.0-manual.527fff6c
dependencies: dependencies:
'@auth/nextjs':
specifier: 0.0.0-manual.030e8328
version: 0.0.0-manual.030e8328(next@13.4.3-canary.3)(react@18.2.0)
'@next-auth/prisma-adapter': '@next-auth/prisma-adapter':
specifier: ^1.0.6 specifier: 1.0.6
version: 1.0.6(@prisma/client@4.14.0)(next-auth@4.22.1) version: 1.0.6(@prisma/client@4.14.0)(next-auth@4.22.1)
'@prisma/client': '@prisma/client':
specifier: ^4.14.0 specifier: ^4.14.0
@ -173,6 +179,35 @@ packages:
'@jridgewell/gen-mapping': 0.3.3 '@jridgewell/gen-mapping': 0.3.3
'@jridgewell/trace-mapping': 0.3.18 '@jridgewell/trace-mapping': 0.3.18
/@auth/core@0.0.0-manual.527fff6c:
resolution: {integrity: sha512-NYWuH+6VAAMV05juyarbMm6rCDUGvS5vPFsE+V13NIfbvbwbEZPj3JfcHVv7vMDrUrPtJ4EhTh00Svejp1Moqg==}
peerDependencies:
nodemailer: ^6.8.0
peerDependenciesMeta:
nodemailer:
optional: true
dependencies:
'@panva/hkdf': 1.1.1
cookie: 0.5.0
jose: 4.14.4
oauth4webapi: 2.3.0
preact: 10.11.3
preact-render-to-string: 5.2.3(preact@10.11.3)
dev: false
/@auth/nextjs@0.0.0-manual.030e8328(next@13.4.3-canary.3)(react@18.2.0):
resolution: {integrity: sha512-AAtUl9EVCKqLRneDAq6KfUprWmsBRzsBoQ+8ytz/Nfgs8Uax5CWvCJs2CsnYNk04bXSB4L7eyMJmc1zTzZKaHg==}
peerDependencies:
next: ^13.4.2
react: ^18.2.0
dependencies:
'@auth/core': 0.0.0-manual.527fff6c
next: 13.4.3-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
transitivePeerDependencies:
- nodemailer
dev: false
/@babel/code-frame@7.21.4: /@babel/code-frame@7.21.4:
resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@ -3532,6 +3567,10 @@ packages:
path-key: 4.0.0 path-key: 4.0.0
dev: true dev: true
/oauth4webapi@2.3.0:
resolution: {integrity: sha512-JGkb5doGrwzVDuHwgrR4nHJayzN4h59VCed6EW8Tql6iHDfZIabCJvg6wtbn5q6pyB2hZruI3b77Nudvq7NmvA==}
dev: false
/oauth@0.9.15: /oauth@0.9.15:
resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==}
dev: false dev: false
@ -3824,6 +3863,15 @@ packages:
picocolors: 1.0.0 picocolors: 1.0.0
source-map-js: 1.0.2 source-map-js: 1.0.2
/preact-render-to-string@5.2.3(preact@10.11.3):
resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==}
peerDependencies:
preact: '>=10'
dependencies:
preact: 10.11.3
pretty-format: 3.8.0
dev: false
/preact-render-to-string@5.2.6(preact@10.14.1): /preact-render-to-string@5.2.6(preact@10.14.1):
resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==}
peerDependencies: peerDependencies:
@ -3833,6 +3881,10 @@ packages:
pretty-format: 3.8.0 pretty-format: 3.8.0
dev: false dev: false
/preact@10.11.3:
resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==}
dev: false
/preact@10.14.1: /preact@10.14.1:
resolution: {integrity: sha512-4XDSnUisk3YFBb3p9WeKeH1mKoxdFUsaXcvxs9wlpYR1wax/TWJVqhwmIWbByX0h7jMEJH6Zc5J6jqc58FKaNQ==} resolution: {integrity: sha512-4XDSnUisk3YFBb3p9WeKeH1mKoxdFUsaXcvxs9wlpYR1wax/TWJVqhwmIWbByX0h7jMEJH6Zc5J6jqc58FKaNQ==}
dev: false dev: false