fixes
This commit is contained in:
1
.claude/worktrees/suspicious-wilson
Submodule
1
.claude/worktrees/suspicious-wilson
Submodule
Submodule .claude/worktrees/suspicious-wilson added at 707f632d34
@@ -5,7 +5,7 @@ export const runtime = "nodejs";
|
|||||||
import { getServerSession } from "next-auth/next";
|
import { getServerSession } from "next-auth/next";
|
||||||
import { authOptions } from "@/lib/auth";
|
import { authOptions } from "@/lib/auth";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { uploadToDrive, updateDriveFile, generateReportMarkdown } from "@/lib/google-drive";
|
import { uploadToDrive, updateDriveFile, generateReportMarkdown, getGoogleAuth } from "@/lib/google-drive";
|
||||||
|
|
||||||
export async function POST(
|
export async function POST(
|
||||||
req: Request,
|
req: Request,
|
||||||
@@ -18,13 +18,11 @@ export async function POST(
|
|||||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// With database sessions (not JWT), the Google access token lives in the
|
let auth;
|
||||||
// Account table — getToken() returns null in this strategy.
|
try {
|
||||||
const account = await prisma.account.findFirst({
|
auth = await getGoogleAuth(session.user.id);
|
||||||
where: { userId: session.user.id, provider: "google" },
|
} catch (error) {
|
||||||
});
|
console.error("Failed to get Google Auth:", error);
|
||||||
|
|
||||||
if (!account?.access_token) {
|
|
||||||
return NextResponse.json({ error: "Unauthorized or missing Google token" }, { status: 401 });
|
return NextResponse.json({ error: "Unauthorized or missing Google token" }, { status: 401 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,10 +48,10 @@ export async function POST(
|
|||||||
|
|
||||||
if (report.driveFileId) {
|
if (report.driveFileId) {
|
||||||
// Update the existing Drive file in place
|
// Update the existing Drive file in place
|
||||||
driveFile = await updateDriveFile(account.access_token, report.driveFileId, markdown);
|
driveFile = await updateDriveFile(auth, report.driveFileId, markdown);
|
||||||
} else {
|
} else {
|
||||||
// First export — create a new Drive file and store its ID
|
// First export — create a new Drive file and store its ID
|
||||||
driveFile = await uploadToDrive(account.access_token, fileName, markdown, folderSetting?.value);
|
driveFile = await uploadToDrive(auth, fileName, markdown, folderSetting?.value);
|
||||||
await prisma.report.update({
|
await prisma.report.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { driveFileId: driveFile.id },
|
data: { driveFileId: driveFile.id },
|
||||||
|
|||||||
@@ -1,10 +1,56 @@
|
|||||||
import { google } from 'googleapis';
|
import { google } from 'googleapis';
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
|
import { prisma } from './prisma';
|
||||||
|
|
||||||
export async function uploadToDrive(accessToken: string, fileName: string, content: string, folderId?: string) {
|
export async function getGoogleAuth(userId: string) {
|
||||||
const auth = new google.auth.OAuth2();
|
const account = await prisma.account.findFirst({
|
||||||
auth.setCredentials({ access_token: accessToken });
|
where: { userId, provider: 'google' },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!account) {
|
||||||
|
throw new Error('Google account not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const auth = new google.auth.OAuth2(
|
||||||
|
process.env.GOOGLE_CLIENT_ID,
|
||||||
|
process.env.GOOGLE_CLIENT_SECRET
|
||||||
|
);
|
||||||
|
|
||||||
|
auth.setCredentials({
|
||||||
|
access_token: account.access_token,
|
||||||
|
refresh_token: account.refresh_token,
|
||||||
|
expiry_date: account.expires_at ? account.expires_at * 1000 : null,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if the token is expired or will expire in the next 1 minute
|
||||||
|
// NextAuth stores expires_at in seconds
|
||||||
|
const isExpired = account.expires_at ? (account.expires_at * 1000) < (Date.now() + 60000) : true;
|
||||||
|
|
||||||
|
if (isExpired && account.refresh_token) {
|
||||||
|
try {
|
||||||
|
const { credentials } = await auth.refreshAccessToken();
|
||||||
|
auth.setCredentials(credentials);
|
||||||
|
|
||||||
|
// Update database with new tokens
|
||||||
|
await prisma.account.update({
|
||||||
|
where: { id: account.id },
|
||||||
|
data: {
|
||||||
|
access_token: credentials.access_token,
|
||||||
|
refresh_token: credentials.refresh_token || account.refresh_token,
|
||||||
|
expires_at: credentials.expiry_date ? Math.floor(credentials.expiry_date / 1000) : null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log('Successfully refreshed Google access token for user:', userId);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error refreshing access token:', error);
|
||||||
|
// If refresh fails, we still return the auth object, but requests will fail with 401
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function uploadToDrive(auth: any, fileName: string, content: string, folderId?: string) {
|
||||||
const drive = google.drive({ version: 'v3', auth });
|
const drive = google.drive({ version: 'v3', auth });
|
||||||
|
|
||||||
const fileMetadata: any = {
|
const fileMetadata: any = {
|
||||||
@@ -34,10 +80,7 @@ export async function uploadToDrive(accessToken: string, fileName: string, conte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateDriveFile(accessToken: string, fileId: string, content: string) {
|
export async function updateDriveFile(auth: any, fileId: string, content: string) {
|
||||||
const auth = new google.auth.OAuth2();
|
|
||||||
auth.setCredentials({ access_token: accessToken });
|
|
||||||
|
|
||||||
const drive = google.drive({ version: 'v3', auth });
|
const drive = google.drive({ version: 'v3', auth });
|
||||||
|
|
||||||
const media = {
|
const media = {
|
||||||
|
|||||||
Reference in New Issue
Block a user