Reset password fixed & supplier gmail restrictions
This commit is contained in:
parent
bfd858ca62
commit
aada21d0a7
@ -4,6 +4,7 @@ import { sendEmail } from "@/lib/email"
|
||||
import { emailSchema } from "@/lib/validation"
|
||||
import { applyRateLimit } from "@/lib/rate-limit"
|
||||
import { handleApiError } from "@/lib/errors"
|
||||
import { getBaseUrl } from "@/lib/utils"
|
||||
import crypto from "crypto"
|
||||
|
||||
export async function POST(req: Request) {
|
||||
@ -64,7 +65,7 @@ export async function POST(req: Request) {
|
||||
})
|
||||
|
||||
// Send reset email
|
||||
const resetUrl = `${process.env.NEXTAUTH_URL || process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/reset-password?token=${resetToken}&email=${encodeURIComponent(email)}`
|
||||
const resetUrl = `${getBaseUrl()}/reset-password?token=${resetToken}&email=${encodeURIComponent(email)}`
|
||||
|
||||
const emailHtml = `
|
||||
<!DOCTYPE html>
|
||||
|
||||
@ -4,6 +4,7 @@ import { prisma } from "@/lib/prisma"
|
||||
import { sendEmail } from "@/lib/email"
|
||||
import { applyRateLimit } from "@/lib/rate-limit"
|
||||
import { handleApiError } from "@/lib/errors"
|
||||
import { getBaseUrl } from "@/lib/utils"
|
||||
import crypto from "crypto"
|
||||
|
||||
export async function POST(req: Request) {
|
||||
@ -63,7 +64,7 @@ export async function POST(req: Request) {
|
||||
})
|
||||
|
||||
// Send verification email
|
||||
const verifyUrl = `${process.env.NEXTAUTH_URL || process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/verify-email?token=${verificationToken}&email=${encodeURIComponent(user.email)}`
|
||||
const verifyUrl = `${getBaseUrl()}/verify-email?token=${verificationToken}&email=${encodeURIComponent(user.email)}`
|
||||
|
||||
const emailHtml = `
|
||||
<!DOCTYPE html>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { NextResponse } from "next/server"
|
||||
import { auth } from "@/auth"
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { getBaseUrl } from "@/lib/utils"
|
||||
|
||||
/**
|
||||
* GET /api/integrations/gmail/callback
|
||||
@ -10,13 +11,8 @@ export async function GET(req: Request) {
|
||||
try {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
const baseUrl =
|
||||
process.env.AUTH_URL ||
|
||||
process.env.NEXTAUTH_URL ||
|
||||
process.env.NEXT_PUBLIC_APP_URL ||
|
||||
"http://localhost:3000"
|
||||
return NextResponse.redirect(
|
||||
new URL("/login?error=unauthorized", baseUrl)
|
||||
new URL("/login?error=unauthorized", getBaseUrl())
|
||||
)
|
||||
}
|
||||
|
||||
@ -28,35 +24,20 @@ export async function GET(req: Request) {
|
||||
// Handle OAuth errors
|
||||
if (error) {
|
||||
console.error("Gmail OAuth error:", error)
|
||||
const baseUrl =
|
||||
process.env.AUTH_URL ||
|
||||
process.env.NEXTAUTH_URL ||
|
||||
process.env.NEXT_PUBLIC_APP_URL ||
|
||||
"http://localhost:3000"
|
||||
return NextResponse.redirect(
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=oauth_failed", baseUrl)
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=oauth_failed", getBaseUrl())
|
||||
)
|
||||
}
|
||||
|
||||
if (!code) {
|
||||
const baseUrl =
|
||||
process.env.AUTH_URL ||
|
||||
process.env.NEXTAUTH_URL ||
|
||||
process.env.NEXT_PUBLIC_APP_URL ||
|
||||
"http://localhost:3000"
|
||||
return NextResponse.redirect(
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=no_code", baseUrl)
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=no_code", getBaseUrl())
|
||||
)
|
||||
}
|
||||
|
||||
// Exchange authorization code for tokens
|
||||
// IMPORTANT: This redirect URI must exactly match what was sent in the authorization request
|
||||
const baseUrl =
|
||||
process.env.AUTH_URL ||
|
||||
process.env.NEXTAUTH_URL ||
|
||||
process.env.NEXT_PUBLIC_APP_URL ||
|
||||
"http://localhost:3000"
|
||||
const redirectUri = `${baseUrl}/api/integrations/gmail/callback`
|
||||
const redirectUri = `${getBaseUrl()}/api/integrations/gmail/callback`
|
||||
|
||||
console.log("Gmail OAuth Callback - Redirect URI:", redirectUri) // Log for debugging
|
||||
|
||||
@ -81,26 +62,16 @@ export async function GET(req: Request) {
|
||||
|
||||
// Provide more specific error message if it's a redirect_uri_mismatch
|
||||
if (errorData.error === "redirect_uri_mismatch") {
|
||||
const baseUrlForError =
|
||||
process.env.AUTH_URL ||
|
||||
process.env.NEXTAUTH_URL ||
|
||||
process.env.NEXT_PUBLIC_APP_URL ||
|
||||
"http://localhost:3000"
|
||||
return NextResponse.redirect(
|
||||
new URL(
|
||||
`/dashboard/juno-engine/gmail-connect?error=redirect_uri_mismatch&redirect_uri=${encodeURIComponent(redirectUri)}`,
|
||||
baseUrlForError
|
||||
getBaseUrl()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
const baseUrlForError =
|
||||
process.env.AUTH_URL ||
|
||||
process.env.NEXTAUTH_URL ||
|
||||
process.env.NEXT_PUBLIC_APP_URL ||
|
||||
"http://localhost:3000"
|
||||
return NextResponse.redirect(
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=token_exchange_failed", baseUrlForError)
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=token_exchange_failed", getBaseUrl())
|
||||
)
|
||||
}
|
||||
|
||||
@ -142,25 +113,15 @@ export async function GET(req: Request) {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching user info:", error)
|
||||
const baseUrlForError =
|
||||
process.env.AUTH_URL ||
|
||||
process.env.NEXTAUTH_URL ||
|
||||
process.env.NEXT_PUBLIC_APP_URL ||
|
||||
"http://localhost:3000"
|
||||
return NextResponse.redirect(
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=user_info_failed", baseUrlForError)
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=user_info_failed", getBaseUrl())
|
||||
)
|
||||
}
|
||||
|
||||
if (!userInfo?.email) {
|
||||
console.error("No email found in user info")
|
||||
const baseUrlForError =
|
||||
process.env.AUTH_URL ||
|
||||
process.env.NEXTAUTH_URL ||
|
||||
process.env.NEXT_PUBLIC_APP_URL ||
|
||||
"http://localhost:3000"
|
||||
return NextResponse.redirect(
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=user_info_failed", baseUrlForError)
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=user_info_failed", getBaseUrl())
|
||||
)
|
||||
}
|
||||
|
||||
@ -190,23 +151,13 @@ export async function GET(req: Request) {
|
||||
}
|
||||
})
|
||||
|
||||
const baseUrlDone =
|
||||
process.env.AUTH_URL ||
|
||||
process.env.NEXTAUTH_URL ||
|
||||
process.env.NEXT_PUBLIC_APP_URL ||
|
||||
"http://localhost:3000"
|
||||
return NextResponse.redirect(
|
||||
new URL("/dashboard/juno-engine/gmail-connect?connected=true", baseUrlDone)
|
||||
new URL("/dashboard/juno-engine/gmail-connect?connected=true", getBaseUrl())
|
||||
)
|
||||
} catch (error) {
|
||||
console.error("Gmail callback error:", error)
|
||||
const baseUrlError =
|
||||
process.env.AUTH_URL ||
|
||||
process.env.NEXTAUTH_URL ||
|
||||
process.env.NEXT_PUBLIC_APP_URL ||
|
||||
"http://localhost:3000"
|
||||
return NextResponse.redirect(
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=callback_failed", baseUrlError)
|
||||
new URL("/dashboard/juno-engine/gmail-connect?error=callback_failed", getBaseUrl())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import { auth } from "@/auth"
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { sendEmail, generateInvitationEmailHtml } from "@/lib/email"
|
||||
import { notifyInvitationReceived } from "@/lib/notifications"
|
||||
import { getBaseUrl } from "@/lib/utils"
|
||||
import crypto from "crypto"
|
||||
|
||||
/**
|
||||
@ -248,7 +249,7 @@ export async function POST(
|
||||
|
||||
// Send invitation email (use first store's name or combined names)
|
||||
const primaryStore = storesToInvite[0]
|
||||
const invitationLink = `${process.env.NEXTAUTH_URL || "http://localhost:3000"}/supplier/vendors?token=${invitations[0].token}`
|
||||
const invitationLink = `${getBaseUrl()}/supplier/vendors?token=${invitations[0].token}`
|
||||
|
||||
const emailSubject = connectToAllStores && storesToInvite.length > 1
|
||||
? `Invitation to Connect - ${storesToInvite.length} Stores`
|
||||
|
||||
@ -74,6 +74,19 @@ export async function POST(req: NextRequest) {
|
||||
)
|
||||
}
|
||||
|
||||
// 🛡️ SECURITY: Only allow VENDORS to use automated replies
|
||||
// Suppliers should not send automated responses via JUNOHUB
|
||||
if (integration.user.role !== "VENDOR") {
|
||||
logger.info("Skipping Gmail processing for non-vendor role", {
|
||||
emailAddress,
|
||||
role: integration.user.role
|
||||
})
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: "Skipping processing for non-vendor account"
|
||||
})
|
||||
}
|
||||
|
||||
const userId = integration.userId
|
||||
const storeId = integration.user.stores[0]?.id || null
|
||||
|
||||
|
||||
@ -4,3 +4,10 @@ import { twMerge } from "tailwind-merge"
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
export function getBaseUrl() {
|
||||
if (process.env.AUTH_URL) return process.env.AUTH_URL
|
||||
if (process.env.NEXTAUTH_URL) return process.env.NEXTAUTH_URL
|
||||
if (process.env.NEXT_PUBLIC_APP_URL) return process.env.NEXT_PUBLIC_APP_URL
|
||||
return "http://localhost:3000"
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user