refactor: switch to unstable_getServerSession for API routes

This commit is contained in:
shadcn 2022-11-22 17:41:51 +04:00
parent 22c4b68711
commit cef699ab70
12 changed files with 41 additions and 25 deletions

View file

@ -2,6 +2,7 @@ import { redirect } from "next/navigation"
import { getCurrentUser } from "@/lib/session"
import { authOptions } from "@/lib/auth"
import { stripe } from "@/lib/stripe"
import { getUserSubscriptionPlan as getUserSubscriptionPlan } from "@/lib/subscription"
import { Card } from "@/ui/card"
import { DashboardHeader } from "@/components/dashboard/header"
@ -17,6 +18,15 @@ export default async function BillingPage() {
const subscriptionPlan = await getUserSubscriptionPlan(user.id)
// If user has a pro plan, check cancel status on Stripe.
let isCanceled = false
if (subscriptionPlan.isPro) {
const stripePlan = await stripe.subscriptions.retrieve(
subscriptionPlan.stripeSubscriptionId
)
isCanceled = stripePlan.cancel_at_period_end
}
return (
<DashboardShell>
<DashboardHeader
@ -24,7 +34,12 @@ export default async function BillingPage() {
text="Manage billing and your subscription plan."
/>
<div className="grid gap-10">
<BillingForm subscriptionPlan={subscriptionPlan} />
<BillingForm
subscriptionPlan={{
...subscriptionPlan,
isCanceled,
}}
/>
<Card>
<Card.Header>
<Card.Title>Note</Card.Title>

View file

@ -9,7 +9,9 @@ import { toast } from "@/ui/toast"
import { Icons } from "@/components/icons"
interface BillingFormProps extends React.HTMLAttributes<HTMLFormElement> {
subscriptionPlan: UserSubscriptionPlan
subscriptionPlan: UserSubscriptionPlan & {
isCanceled: boolean
}
}
export function BillingForm({

View file

@ -87,6 +87,9 @@ export function Editor({ post }: EditorProps) {
const response = await fetch(`/api/posts/${post.id}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: data.title,
content: blocks,

View file

@ -22,6 +22,9 @@ export function PostCreateButton({
const response = await fetch("/api/posts", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Untitled Post",
}),

View file

@ -38,6 +38,9 @@ export function UserNameForm({ user, className, ...props }: UserNameFormProps) {
const response = await fetch(`/api/users/${user.id}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: data.name,
}),

View file

@ -8,7 +8,7 @@ export function withValidation<T extends ZodSchema>(
) {
return async function (req: NextApiRequest, res: NextApiResponse) {
try {
const body = req.body ? JSON.parse(req.body) : {}
const body = req.body ? req.body : {}
await schema.parse(body)

View file

@ -1,7 +1,6 @@
import { UserSubscriptionPlan } from "types"
import { freePlan, proPlan } from "@/config/subscriptions"
import { db } from "@/lib/db"
import { stripe } from "@/lib/stripe"
export async function getUserSubscriptionPlan(
userId: string
@ -25,20 +24,10 @@ export async function getUserSubscriptionPlan(
const plan = isPro ? proPlan : freePlan
// If user has a pro plan, check cancel status on Stripe.
let isCanceled = false
if (isPro && user.stripeSubscriptionId) {
const stripePlan = await stripe.subscriptions.retrieve(
user.stripeSubscriptionId
)
isCanceled = stripePlan.cancel_at_period_end
}
return {
...plan,
...user,
stripeCurrentPeriodEnd: user.stripeCurrentPeriodEnd?.getTime(),
isCanceled,
isPro,
}
}

View file

@ -30,7 +30,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
},
})
const body = postPatchSchema.parse(JSON.parse(req.body))
const body = postPatchSchema.parse(req.body)
// TODO: Implement sanitization for content.

View file

@ -1,12 +1,13 @@
import { NextApiRequest, NextApiResponse } from "next"
import { getSession } from "next-auth/react"
import * as z from "zod"
import { unstable_getServerSession } from "next-auth/next"
import { db } from "@/lib/db"
import { withMethods } from "@/lib/api-middlewares/with-methods"
import { withAuthentication } from "@/lib/api-middlewares/with-authentication"
import { getUserSubscriptionPlan } from "@/lib/subscription"
import { RequiresProPlanError } from "@/lib/exceptions"
import { authOptions } from "@/lib/auth"
const postCreateSchema = z.object({
title: z.string().optional(),
@ -14,7 +15,7 @@ const postCreateSchema = z.object({
})
async function handler(req: NextApiRequest, res: NextApiResponse) {
const session = await getSession({ req })
const session = await unstable_getServerSession(req, res, authOptions)
const user = session?.user
if (req.method === "GET") {
@ -55,7 +56,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
}
}
const body = postCreateSchema.parse(JSON.parse(req.body))
const body = postCreateSchema.parse(req.body)
const post = await db.post.create({
data: {

View file

@ -1,19 +1,20 @@
import { NextApiRequest, NextApiResponse } from "next"
import * as z from "zod"
import { getSession } from "next-auth/react"
import { unstable_getServerSession } from "next-auth/next"
import { db } from "@/lib/db"
import { withMethods } from "@/lib/api-middlewares/with-methods"
import { withCurrentUser } from "@/lib/api-middlewares/with-current-user"
import { userNameSchema } from "@/lib/validations/user"
import { authOptions } from "@/lib/auth"
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "PATCH") {
try {
const session = await getSession({ req })
const session = await unstable_getServerSession(req, res, authOptions)
const user = session?.user
const body = JSON.parse(req.body)
const body = req.body
if (body?.name) {
const payload = userNameSchema.parse(body)
@ -30,7 +31,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
return res.end()
} catch (error) {
console.log(error)
if (error instanceof z.ZodError) {
return res.status(422).json(error.issues)
}

View file

@ -1,5 +1,5 @@
import { NextApiRequest, NextApiResponse } from "next"
import { getSession } from "next-auth/react"
import { unstable_getServerSession } from "next-auth/next"
import { proPlan } from "@/config/subscriptions"
import { withMethods } from "@/lib/api-middlewares/with-methods"
@ -7,13 +7,14 @@ import { getUserSubscriptionPlan } from "@/lib/subscription"
import { stripe } from "@/lib/stripe"
import { withAuthentication } from "@/lib/api-middlewares/with-authentication"
import { absoluteUrl } from "@/lib/utils"
import { authOptions } from "@/lib/auth"
const billingUrl = absoluteUrl("/dashboard/billing")
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "GET") {
try {
const session = await getSession({ req })
const session = await unstable_getServerSession(req, res, authOptions)
const user = session.user
const subscriptionPlan = await getUserSubscriptionPlan(user.id)

1
types/index.d.ts vendored
View file

@ -58,5 +58,4 @@ export type UserSubscriptionPlan = SubscriptionPlan &
Pick<User, "stripeCustomerId" | "stripeSubscriptionId"> & {
stripeCurrentPeriodEnd: number
isPro: boolean
isCanceled: boolean
}