forked from lmsqueezy/nextjs-billing
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NextAuth magic emails; user data in checkouts
- Loading branch information
Showing
20 changed files
with
1,551 additions
and
188 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
'use client' | ||
|
||
import { signIn } from "next-auth/react" | ||
|
||
const handleSubmit = (event) => { | ||
event.preventDefault() | ||
signIn("email", { email: event.target.email.value }) | ||
} | ||
|
||
export default function SignIn() { | ||
return ( | ||
<div> | ||
<h1>Sign in with a magic link</h1> | ||
<form method="post" onSubmit={handleSubmit}> | ||
<label> | ||
Email address | ||
<input type="email" id="email" name="email" /> | ||
</label> | ||
<button type="submit">Sign in with Email</button> | ||
</form> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export default function Verify() { | ||
return ( | ||
<> | ||
<p>Magic link sent!</p> | ||
<p>Please check your email inbox for an email from <code>{process.env.NEXT_PUBLIC_EMAIL_FROM_DEFAULT}</code>.</p> | ||
<p>Return to <a href="/">Homepage</a></p> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export default function Home() { | ||
return ( | ||
<div> | ||
<h1>Demo Billing app</h1> | ||
<p>Marketing home</p> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import NextAuth from "next-auth"; | ||
import { authOptions } from "@/lib/auth"; | ||
|
||
const handler = NextAuth(authOptions); | ||
|
||
export { handler as GET, handler as POST } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
import { LemonSqueezy } from "../../billing/lemonsqueezy"; | ||
import { getSession } from "@/lib/auth"; | ||
|
||
import LemonSqueezy from '@lemonsqueezy/lemonsqueezy.js' | ||
const ls = new LemonSqueezy(process.env.LEMONSQUEEZY_API_KEY); | ||
|
||
|
||
export async function POST(request: Request) { | ||
const session = await getSession(); | ||
|
||
const res = await request.json() | ||
|
||
|
@@ -19,9 +22,9 @@ export async function POST(request: Request) { | |
'button_color': '#fde68a' | ||
}, | ||
'checkout_data': { | ||
'email': "[email protected]", // Displays in the checkout form eg session.user.email with NextAuth.js | ||
'email': session.user.email, // Displays in the checkout form eg session.user.email with NextAuth.js | ||
'custom': { | ||
'user_id': "1" // Sent in the background; visible in webhooks and API calls eg session.user.id with NextAuth.js | ||
'user_id': session.user.id // Sent in the background; visible in webhooks and API calls eg session.user.id with NextAuth.js | ||
} | ||
}, | ||
'product_options': { | ||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
"use client"; | ||
|
||
import { SessionProvider } from "next-auth/react"; | ||
import { Toaster } from "sonner"; | ||
|
||
export function Providers({ children }: { children: React.ReactNode }) { | ||
return ( | ||
<SessionProvider> | ||
<Toaster /> | ||
{children} | ||
</SessionProvider> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { getServerSession } from "next-auth/next"; | ||
import { NextAuthOptions } from 'next-auth'; | ||
import EmailProvider from 'next-auth/providers/email'; | ||
import { PrismaAdapter } from "@auth/prisma-adapter"; | ||
import prisma from "@/lib/prisma"; | ||
import { sendVerificationRequest } from '@/utils/send-verification-request'; | ||
|
||
export const authOptions: NextAuthOptions = { | ||
adapter: PrismaAdapter(prisma), | ||
providers: [ | ||
EmailProvider({ | ||
name: 'email', | ||
server: '', | ||
from: '[email protected]', | ||
sendVerificationRequest, | ||
}), | ||
], | ||
pages: { | ||
signIn: '/login', | ||
verifyRequest: '/login/verify', | ||
}, | ||
session: { | ||
strategy: 'jwt' | ||
}, | ||
callbacks: { | ||
// Add user ID to session from token | ||
session: async ({ session, token }) => { | ||
if (session?.user) { | ||
session.user.id = token.sub; | ||
} | ||
return session; | ||
} | ||
} | ||
} | ||
|
||
|
||
export function getSession() { | ||
return getServerSession(authOptions) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,15 @@ | ||
import { PrismaClient } from "@prisma/client"; | ||
import { PrismaClient } from '@prisma/client' | ||
|
||
declare global { | ||
var prisma: PrismaClient | undefined; | ||
} | ||
// PrismaClient is attached to the `global` object in development to prevent | ||
// exhausting your database connection limit. | ||
// | ||
// Learn more: | ||
// https://pris.ly/d/help/next-js-best-practices | ||
|
||
const prisma = global.prisma || new PrismaClient({ log: ["info"] }); | ||
if (process.env.NODE_ENV !== "production") global.prisma = prisma; | ||
const globalForPrisma = global as unknown as { prisma: PrismaClient } | ||
|
||
export default prisma; | ||
export const prisma = globalForPrisma.prisma || new PrismaClient() | ||
|
||
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma | ||
|
||
export default prisma |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { Resend } from 'resend'; | ||
|
||
export const resend = new Resend(process.env.RESEND_API_KEY!); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { getToken } from "next-auth/jwt" | ||
import { withAuth } from "next-auth/middleware" | ||
import { NextResponse } from "next/server" | ||
|
||
export default withAuth( | ||
async function middleware(req) { | ||
const token = await getToken({ req }) | ||
const isAuth = !!token | ||
const isAuthPage = req.nextUrl.pathname.startsWith("/login") | ||
|
||
// Redirect auth pages (/login) to dashboard when logged in | ||
if (isAuthPage) { | ||
if (isAuth) { | ||
return NextResponse.redirect(new URL("/dashboard", req.url)) | ||
} | ||
|
||
return null | ||
} | ||
|
||
if (!isAuth) { | ||
let from = req.nextUrl.pathname; | ||
if (req.nextUrl.search) { | ||
from += req.nextUrl.search; | ||
} | ||
|
||
// Load the homepage (/home) at / when not logged in | ||
if (req.nextUrl.pathname == '/') { | ||
return NextResponse.rewrite(new URL('/', req.url)); | ||
} | ||
|
||
return NextResponse.redirect( | ||
new URL(`/login?from=${encodeURIComponent(from)}`, req.url) | ||
); | ||
} else { | ||
// Redirect / to /dashboard when logged in | ||
// if (req.nextUrl.pathname == '/') { | ||
// return NextResponse.redirect(new URL('/dashboard', req.url)); | ||
// } | ||
} | ||
}, | ||
{ | ||
callbacks: { | ||
async authorized() { | ||
// This is a work-around for handling redirect on auth pages. | ||
// We return true here so that the middleware function above | ||
// is always called. | ||
return true | ||
}, | ||
}, | ||
} | ||
) | ||
|
||
export const config = { | ||
// /login + all locked pages should be listed here | ||
matcher: [ | ||
'/', | ||
'/dashboard', | ||
'/billing', | ||
'/login' | ||
], | ||
} |
Oops, something went wrong.