Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions apps/web/app/api/google/calendar/callback/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,39 @@ import { CALENDAR_STATE_COOKIE_NAME } from "@/utils/calendar/constants";
import { parseOAuthState } from "@/utils/oauth/state";
import { auth } from "@/utils/auth";
import { prefixPath } from "@/utils/path";
import { createRecallCalendar } from "@/utils/recall/calendar";

const logger = createScopedLogger("google/calendar/callback");

async function createAndLinkRecallCalendar(
connectionId: string,
refreshToken: string,
emailAccountId: string,
): Promise<void> {
try {
const recallCalendar = await createRecallCalendar({
oauth_refresh_token: refreshToken,
});

await prisma.calendarConnection.update({
where: { id: connectionId },
data: { recallCalendarId: recallCalendar.id },
});
} catch (error) {
logger.error("Failed to create Recall calendar for connection", {
error: error instanceof Error ? error.message : error,
connectionId,
emailAccountId,
});
}
}

export const GET = withError(async (request) => {
const searchParams = request.nextUrl.searchParams;
const code = searchParams.get("code");
const receivedState = searchParams.get("state");
const storedState = request.cookies.get(CALENDAR_STATE_COOKIE_NAME)?.value;

// We'll set the proper redirect URL after we decode the state and get emailAccountId
let redirectUrl = new URL("/calendars", request.nextUrl.origin);
const response = NextResponse.redirect(redirectUrl);

Expand Down Expand Up @@ -61,13 +84,11 @@ export const GET = withError(async (request) => {

const { emailAccountId } = decodedState;

// Update redirect URL to include emailAccountId
redirectUrl = new URL(
prefixPath(emailAccountId, "/calendars"),
request.nextUrl.origin,
);

// Verify user owns this email account
const session = await auth();
if (!session?.user?.id) {
logger.warn("Unauthorized calendar callback - no session");
Expand Down Expand Up @@ -134,7 +155,19 @@ export const GET = withError(async (request) => {
logger.info("Calendar connection already exists", {
emailAccountId,
googleEmail,
connectionId: existingConnection.id,
hasRecallCalendarId: !!existingConnection.recallCalendarId,
recallCalendarId: existingConnection.recallCalendarId,
});

if (!existingConnection.recallCalendarId) {
await createAndLinkRecallCalendar(
existingConnection.id,
refresh_token,
emailAccountId,
);
}

redirectUrl.searchParams.set("message", "calendar_already_connected");
return NextResponse.redirect(redirectUrl, { headers: response.headers });
}
Expand All @@ -151,6 +184,12 @@ export const GET = withError(async (request) => {
},
});

await createAndLinkRecallCalendar(
connection.id,
refresh_token,
emailAccountId,
);

await syncGoogleCalendars(
connection.id,
access_token,
Expand Down
Loading
Loading