Skip to content

Commit

Permalink
Merge pull request #61 from hubcio2115/feat/migrate-to-next-auth-v5
Browse files Browse the repository at this point in the history
Migrate to next-auth v5
  • Loading branch information
hubcio2115 committed Jul 8, 2024
2 parents cb6116a + 44d5e8f commit 8b36d3e
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 111 deletions.
14 changes: 8 additions & 6 deletions apps/web/.env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
# When adding additional environment variables, the schema in "/src/env.mjs"
# should be updated accordingly.

NEXT_PUBLIC_API_URL="http://localhost:3000"

# Drizzle
# Get the Database URL from the "prisma" dropdown selector in PlanetScale.
# Change the query params at the end of the URL to "?ssl={"rejectUnauthorized":true}"
Expand All @@ -18,18 +20,18 @@ POSTGRES_URL='postgres://YOUR_POSTGRES_URL_HERE?pgbouncer=true&connect_timeout=1
# You can generate a new secret on the command line with:
# openssl rand -base64 32
# https://next-auth.js.org/configuration/options#secret
# NEXTAUTH_SECRET=""
NEXTAUTH_URL="http://localhost:3000"
AUTH_SECRET=""
AUTH_URL="http://localhost:3000"

# Next Auth Google Provider
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
AUTH_GOOGLE_ID=""
AUTH_GOOGLE_SECRET=""
YOUTUBE_DATA_API_KEY=""

# Mux secrets
MUX_TOKEN_ID=""
MUX_TOKEN_SECRET=""

# Secret for communication with our webhook
MUX_WEBHOOK_SECRET=""
# URL for mux cors
MUX_URL=${NEXTAUTH_URL}
# URL for mux cors
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"geist": "^1.3.0",
"lucide-react": "^0.290.0",
"next": "^14.2.3",
"next-auth": "^4.24.7",
"next-auth": "5.0.0-beta.19",
"next-themes": "^0.2.1",
"pg": "^8.11.5",
"react": "18.2.0",
Expand Down
8 changes: 2 additions & 6 deletions apps/web/src/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import NextAuth from "next-auth";
import { handlers } from "~/server/auth";

import { authOptions } from "~/server/auth";

// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
export const { GET, POST } = handlers;
4 changes: 2 additions & 2 deletions apps/web/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Toaster } from "~/components/ui/toaster";
import { ReactQueryProvider } from "~/providers/react-query-provider";
import { SessionProvider } from "~/providers/session-provider";
import { ThemeProvider } from "~/providers/theme-provider";
import { getServerAuthSession } from "~/server/auth";
import { auth } from "~/server/auth";
import "~/styles/globals.css";

export const metadata = {
Expand All @@ -15,7 +15,7 @@ export const metadata = {
};

export default async function RootLayout({ children }: PropsWithChildren) {
const session = await getServerAuthSession();
const session = await auth();

return (
<html lang="en" className={GeistSans.className} suppressHydrationWarning>
Expand Down
82 changes: 40 additions & 42 deletions apps/web/src/components/navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { LogOut } from "lucide-react";
import { signOut, useSession } from "next-auth/react";
import { signIn, signOut, useSession } from "next-auth/react";
import Link from "next/link";
import { usePathname } from "next/navigation";

Expand All @@ -25,51 +25,49 @@ export default function Navbar() {
session.status === "authenticated" && isOnDashboard;

return (
<>
<div className="flex w-full items-center justify-between">
<div className="flex gap-4">
<h1 className="text-3xl font-bold text-gray-900">
<span className="text-fuchsia-900">Edit</span>
thing
</h1>
<div className="flex w-full items-center justify-between">
<div className="flex gap-4">
<h1 className="text-3xl font-bold text-gray-900">
<span className="text-fuchsia-900">Edit</span>
thing
</h1>

{shouldShowOrganizationsSelect ? <OrganizationSelect /> : null}
</div>
{shouldShowOrganizationsSelect ? <OrganizationSelect /> : null}
</div>

<div>
{session.status === "authenticated" ? (
<div className="flex gap-2">
<DropdownMenu>
<DropdownMenuTrigger className="focus:outline-none">
<Profile session={session.data} />
</DropdownMenuTrigger>
<div>
{session.status === "authenticated" ? (
<div className="flex gap-2">
<DropdownMenu>
<DropdownMenuTrigger className="focus:outline-none">
<Profile session={session.data} />
</DropdownMenuTrigger>

<DropdownMenuContent className="w-[200px]">
<DropdownMenuItem onClick={() => signOut()}>
<LogOut
className="mr-2 h-4 w-4 hover:cursor-pointer"
color="red"
/>
<span>Log out</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenuContent className="w-[200px]">
<DropdownMenuItem onClick={() => signOut()}>
<LogOut
className="mr-2 h-4 w-4 hover:cursor-pointer"
color="red"
/>
<span>Log out</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

{!isOnDashboard && (
<Link href="/dashboard/">
<Button variant="outline" className="rounded-full">
Go to Dashboard
</Button>
</Link>
)}
</div>
) : (
<Link href="/api/auth/signin">
<Button variant="ghost">Sign in</Button>
</Link>
)}
</div>
{!isOnDashboard && (
<Link href="/dashboard/">
<Button variant="outline" className="rounded-full">
Go to Dashboard
</Button>
</Link>
)}
</div>
) : (
<Button variant="ghost" onClick={() => signIn()}>
Sign in
</Button>
)}
</div>
</>
</div>
);
}
15 changes: 8 additions & 7 deletions apps/web/src/env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,30 @@ export const env = createEnv({
.enum(["development", "test", "production"])
.default("development"),

NEXTAUTH_SECRET:
AUTH_SECRET:
process.env.NODE_ENV === "production"
? z.string().min(1)
: z.string().min(1).optional(),
NEXTAUTH_URL: z.preprocess(
// This makes Vercel deployments not fail if you don't set NEXTAUTH_URL

AUTH_URL: z.preprocess(
// This makes Vercel deployments not fail if you don't set AUTH_URL
// Since NextAuth.js automatically uses the VERCEL_URL if present.
(str) => process.env.VERCEL_URL ?? str,
// VERCEL_URL doesn't include `https` so it cant be validated as a URL
process.env.VERCEL ? z.string().min(1) : z.string().url(),
),

GOOGLE_CLIENT_ID: z.string().min(1),
GOOGLE_CLIENT_SECRET: z.string().min(1),
AUTH_GOOGLE_ID: z.string().min(1),
AUTH_GOOGLE_SECRET: z.string().min(1),

MUX_TOKEN_ID: z.string().min(1),
MUX_TOKEN_SECRET: z.string().min(1),
MUX_WEBHOOK_SECRET: z.string().min(1),
MUX_URL: z.string().min(1),
},

client: {
// NEXT_PUBLIC_PUBLISHABLE_KEY: z.string().min(1),
NEXT_PUBLIC_API_URL: z.string(),
},
// If you're using Next.js < 13.4.4, you'll need to specify the runtimeEnv manually
// runtimeEnv: {
Expand All @@ -48,7 +49,7 @@ export const env = createEnv({

// For Next.js >= 13.4.4, you only need to destructure client variables:
experimental__runtimeEnv: {
NEXT_PUBLIC_PUBLISHABLE_KEY: process.env.NEXT_PUBLIC_PUBLISHABLE_KEY,
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
},

/**
Expand Down
15 changes: 3 additions & 12 deletions apps/web/src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
import { withAuth } from "next-auth/middleware";
import { auth } from "./server/auth";

export default withAuth({
callbacks: {
authorized: ({ req }) => {
const token = req.cookies.get("next-auth.session-token")?.value;
export default auth;

if (token) return true;
return false;
},
},
});

export const config = { matcher: ["/dashboard"] };
export const config = { matcher: ["/dashboard", "/api/projects/"] };
16 changes: 8 additions & 8 deletions apps/web/src/server/actions/organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ import {
users,
} from "~/server/db/schema";

import { getServerAuthSession } from "../auth";
import { auth } from "../auth";
import { db } from "../db";
import { organizations, usersToOrganizations } from "../db/schema";

export async function getOwnOrganizations(): Promise<
[{ id: number; name: string }[], null] | [null, Error]
> {
const session = await getServerAuthSession();
const session = await auth();

if (!session) {
return [null, new Error("You must be signed in to perform this action")];
Expand All @@ -50,7 +50,7 @@ export async function getOrgViewWithMembers() {
export async function getOwnOrganizationByName(
name: Organization["name"],
): Promise<Result<OrganizationWithMembers>> {
const session = await getServerAuthSession();
const session = await auth();

if (!session) {
return [null, "You must be signed in to perform this action"];
Expand Down Expand Up @@ -88,7 +88,7 @@ export async function getOrganizations(): Promise<
}[]
>
> {
const session = await getServerAuthSession();
const session = await auth();

if (!session) {
return [null, "You must be signed in to perform this action."];
Expand All @@ -113,7 +113,7 @@ export async function getOrganizations(): Promise<
export async function createOrganization({
name,
}: InsertOrganization): Promise<Result<Organization>> {
const session = await getServerAuthSession();
const session = await auth();

try {
const newOrg = await createOrganizationInner(db, name, session?.user.id!, true);
Expand All @@ -131,7 +131,7 @@ export async function updateOrganizationName({
oldName: Organization["name"];
name: Organization["name"];
}): Promise<Result<null>> {
const session = await getServerAuthSession();
const session = await auth();

const owner = (
await db
Expand Down Expand Up @@ -163,7 +163,7 @@ export async function updateOrganizationName({
export async function deleteOrganization(
name: Organization["name"],
): Promise<Result<null>> {
const session = await getServerAuthSession();
const session = await auth();

const orgWithMember = (
await db
Expand Down Expand Up @@ -287,7 +287,7 @@ export async function updateMemberRole({
memberId: User["id"];
role: OrgMemberRole;
}): Promise<null | Error> {
const session = await getServerAuthSession();
const session = await auth();
const currentOwner = (
await db
.select()
Expand Down
38 changes: 11 additions & 27 deletions apps/web/src/server/auth.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import { DrizzleAdapter } from "@auth/drizzle-adapter";
import {
type DefaultSession,
type NextAuthOptions,
getServerSession,
} from "next-auth";
import NextAuth, { type DefaultSession } from "next-auth";
import Google from "next-auth/providers/google";
import { db } from "./db";
import { createTable } from "./db/schema";
import type { Adapter } from "next-auth/adapters";
import GoogleProvider from "next-auth/providers/google";

import { env } from "~/env.mjs";
import { generateSeedForOrgName, stripSpecialCharacters } from "~/lib/utils";
import {
createOrganization,
getOrganizationByName,
} from "~/server/api/utils/organizations";
import { db } from "~/server/db";
import { createTable } from "~/server/db/schema";
} from "./api/utils/organizations";

/**
* Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`
Expand Down Expand Up @@ -42,7 +36,7 @@ declare module "next-auth" {
*
* @see https://next-auth.js.org/configuration/options
*/
export const authOptions: NextAuthOptions = {
export const { auth, handlers, signIn, signOut } = NextAuth({
callbacks: {
session: ({ session, user }) => ({
...session,
Expand All @@ -52,14 +46,11 @@ export const authOptions: NextAuthOptions = {
},
}),
},

adapter: DrizzleAdapter(db, createTable) as Adapter,
providers: [
// Sign in with Google Oauth provider
GoogleProvider({
clientId: env.GOOGLE_CLIENT_ID,
clientSecret: env.GOOGLE_CLIENT_SECRET,
}),
],

providers: [Google],

events: {
async createUser({ user }) {
const userName = user.name;
Expand Down Expand Up @@ -124,11 +115,4 @@ export const authOptions: NextAuthOptions = {
}
},
},
};

/**
* Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file.
*
* @see https://next-auth.js.org/configuration/nextjs
*/
export const getServerAuthSession = () => getServerSession(authOptions);
});

0 comments on commit 8b36d3e

Please sign in to comment.