You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import{emailHtmlGen}from"@/utils/emailGen";importloggerfrom"@/utils/logger";import{Environment,Paddle}from'@paddle/paddle-node-sdk';import{PrismaClient}from'@prisma/client';importbcryptfrom'bcryptjs';importjwtfrom'jsonwebtoken';importNextAuthfrom"next-auth/next";importCredentialsProviderfrom"next-auth/providers/credentials";importGoogleProviderfrom"next-auth/providers/google";importnodemailerfrom'nodemailer';importgenerateTokenfrom"utils/signJwt";constpaddle=newPaddle(process.env.PADDLE_API_KEY,{environment: Environment.production,// Switch between sandbox and productionlogLevel: 'verbose',// or 'error' for less verbose logging});constprisma=newPrismaClient();consttransporter=nodemailer.createTransport({host: process.env.EMAIL_HOST,port: process.env.EMAIL_PORT,secure: false,auth: {user: process.env.EMAIL_USER,pass: process.env.EMAIL_PASS,},});exportconstauthOptions={providers: [// OTP-based Credentials ProviderCredentialsProvider({name: "replyment-otp",credentials: {email: {label: 'Email',type: 'text',placeholder: 'your-email@example.com'},otp: {label: 'OTP',type: 'text',placeholder: '123456'},},asyncauthorize(credentials){const{ email, otp }=credentials;try{// Find user by emailletuser=awaitprisma.user.findUnique({where: { email },include: {subscription: true},});if(!user){thrownewError(`User not found&email=${email}`);}// Check OTP expirationif(newDate()>user.otpExpiry){thrownewError(`OTP expired&email=${email}`);}// Validate OTPconstisOtpValid=awaitbcrypt.compare(otp,user.otp);if(!isOtpValid){thrownewError(`Invalid OTP&email=${email}`);}if(user.status=='Banned'){thrownewError(`User is banned&email=${email}`);}// Reactivate user if inactiveif(user.status!=='Active'&&user.status!=='Banned'){user=awaitprisma.user.update({where: { email },data: {status: 'Active'},include: {subscription: true},});// Send activation emailif(user){awaittransporter.sendMail({from: process.env.EMAIL_FROM,to: user.email,subject: 'Your Account Has Been Activated',text: `Your account associated with ${user.email} has been successfully activated.`,html: emailHtmlGen("Account Activation Notice",`Your account ${user.email} has been successfully activated.`),});}}// Clear OTP fields on successawaitprisma.user.update({where: { email },data: {otp: null,otpExpiry: null,otpInit: null},});// Generate JWT with user datalogger.info(`OTP verified for ${email}`,{paddleId: user.paddleId});returnuser;}catch(error){thrownewError(error.message||`OTP verification failed&email=${email}`);}},}),// Google ProviderGoogleProvider({clientId: process.env.GOOGLE_CLIENT_ID,clientSecret: process.env.GOOGLE_CLIENT_SECRET,}),],session: {jwt: true,maxAge: 7*24*60*60,// 7 days},jwt: {// The maximum age of the NextAuth.js issued JWT in seconds.// Defaults to `session.maxAge`.maxAge: 7*24*60*60,// 7 days},callbacks: {// SignIn callbackasyncsignIn({ user, account, profile }){try{letpaddleUserId=null;try{if(!user.paddleId){// Fetch Paddle user dataconstpaddleResponse=awaitfetch(`https://api.paddle.com/customers?email=${encodeURIComponent(user.email)}`,{method: 'GET',headers: {'Content-Type': 'application/json','Authorization': `Bearer ${process.env.PADDLE_API_KEY}`}});if(!paddleResponse.ok){returnnewResponse('Failed to fetch Paddle user data',{status: paddleResponse.status});}letpaddleUser=awaitpaddleResponse.json();paddleUserId=paddleUser?.data?.[0]?.id||null;if(!paddleUserId){paddleUser=awaitpaddle.customers.create({email: user?.email,name: user?.name||'Replyment User',});paddleUserId=paddleUser.id;}}else{paddleUserId=user.paddleId;}}catch(e){console.log("Paddle User Fetch Error",e)}// Handle sign-in with Googletry{if(account.provider==='google'){letexistingUser=awaitprisma.user.findUnique({where: {email: user.email},include: {subscription: true},});// Create a new user if it doesn't existif(!existingUser){existingUser=awaitprisma.user.create({data: {paddleId: paddleUserId,email: user.email,role: 'User',subscription: {create: {level: 'None'}},},include: {subscription: true},});}if(existingUser.status=='Banned'){thrownewError(`User is banned&email=${user.email}`);}// Fix: Update the Paddle ID if not presentif(existingUser&&!existingUser.paddleId){awaitprisma.user.update({where: {email: user.email},data: {paddleId: paddleUserId},});}// Reactivate user if inactiveif(existingUser&&existingUser.status!=='Active'&&existingUser.status!=='Banned'){existingUser=awaitprisma.user.update({where: {email: user.email},data: {status: 'Active'},include: {subscription: true},});// Send activation emailif(existingUser){awaittransporter.sendMail({from: process.env.EMAIL_FROM,to: existingUser.email,subject: 'Your Account Has Been Activated',text: `Your account associated with ${existingUser.email} has been successfully activated.`,html: emailHtmlGen("Account Activation Notice",`Your account ${existingUser.email} has been successfully activated.`),});}}// Attach account data to JWTlogger.info(`JWT generated for ${user.email}`);consttoken=awaitgenerateToken(existingUser.id,{email: existingUser.email,role: existingUser.role,paddleId: paddleUserId,subscriptionId: existingUser.subscription.id,});user.accessToken=token;returnuser;}}catch(e){console.log("Google Signin Error",e)}try{// Handle sign-in with credentialsif(account.provider==='credentials'){// Fix: Update the Paddle ID if not presentif(!user.paddleId){awaitprisma.user.update({where: {email: user.email},data: {paddleId: paddleUserId},});}// Generate JWT with user datalogger.info(`JWT generated for ${user.email}`);consttoken=awaitgenerateToken(user.id,{email: user.email,role: user.role,paddleId: paddleUserId,subscriptionId: user.subscription?.id,});user.accessToken=token;}}catch(e){console.log("Credentials Signin Error",e)}returntrue;}catch(error){constmeta={userEmail: user.email,errorCode: error.code||'UNKNOWN',stack: error.stack,};logger.error(`Sign-in error: ${error.message}`,meta);console.log(error)returnfalse;}},// JWT callbackasyncjwt({ token, user }){if(user){token.accessToken=user.accessToken;token.exp=Math.floor((Date.now()+7*24*60*60*1000)/1000);}returntoken;},// Session callbackasyncsession({ session, token }){if(token){try{constdecodedToken=jwt.verify(token.accessToken,process.env.JWT_SECRET);if(decodedToken.exp<Math.floor(Date.now()/1000)){returnnull;}}catch(error){returnnull;}}else{returnnull;}session.accessToken=token.accessToken;if(session.user&&session.user.email){try{// Check user statusconstuserStatus=awaitprisma.user.findUnique({where: {email: session.user.email},select: {status: true},});// Log the user statuslogger.auth(`User status: ${userStatus?.status}`,{email: session.user.email});// Invalidate session if the user is bannedif(userStatus?.status==='Banned'){returnnull;}}catch(error){logger.error(`Error fetching user status: ${error.message}`,{email: session.user.email,stack: error.stack,});returnnull;}}returnsession;},},secret: process.env.NEXTAUTH_SECRET,pages: {signIn: "/welcome",error: "/welcome",},debug: process.env.NODE_ENV==="development",};consthandler=NextAuth(authOptions);export{handlerasGET,handlerasPOST};
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
middleware.js
app\api\auth\[...nextauth]\route.js
Beta Was this translation helpful? Give feedback.
All reactions