import { NextRequest, NextResponse } from "next/server"; import { db } from "@/db"; import { users } from "@/db/schema"; import { createJwtToken } from "@/lib/auth"; import { generateId, now } from "@/lib/utils"; import { eq } from "drizzle-orm"; const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID!; const GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET!; const FRONTEND_URL = process.env.FRONTEND_URL || "http://localhost:5173"; /** * GET /api/auth/github/callback * Handle GitHub OAuth callback and create user session. */ export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url); const code = searchParams.get("code"); if (!code) { return NextResponse.redirect(`${FRONTEND_URL}/?error=no_code`); } try { // Exchange code for access token const tokenResponse = await fetch( "https://github.com/login/oauth/access_token", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: JSON.stringify({ client_id: GITHUB_CLIENT_ID, client_secret: GITHUB_CLIENT_SECRET, code, }), } ); const tokenData = await tokenResponse.json(); const accessToken = tokenData.access_token; if (!accessToken) { console.error("No access token:", tokenData); return NextResponse.redirect(`${FRONTEND_URL}/?error=no_token`); } // Get user info from GitHub const userResponse = await fetch("https://api.github.com/user", { headers: { Authorization: `Bearer ${accessToken}`, }, }); const githubUser = await userResponse.json(); // Check if user exists // NOTE: sync_status columns excluded until Turso migration is applied const existingUsers = await db .select({ id: users.id, githubId: users.githubId, username: users.username, avatarUrl: users.avatarUrl, role: users.role, githubAccessToken: users.githubAccessToken, createdAt: users.createdAt, updatedAt: users.updatedAt, }) .from(users) .where(eq(users.githubId, githubUser.id)) .limit(1); let userData; if (existingUsers.length > 0) { // Update existing user with new GitHub token await db .update(users) .set({ githubAccessToken: accessToken, updatedAt: now() }) .where(eq(users.githubId, githubUser.id)); userData = { ...existingUsers[0], githubAccessToken: accessToken }; } else { // Create new user const newUser = { id: generateId(), githubId: githubUser.id, username: githubUser.login, avatarUrl: githubUser.avatar_url, role: null, githubAccessToken: accessToken, createdAt: now(), updatedAt: now(), }; await db.insert(users).values(newUser); userData = newUser; } // Create JWT token const token = createJwtToken(userData.id, userData.role); return NextResponse.redirect(`${FRONTEND_URL}/?token=${token}`); } catch (error) { console.error("GitHub auth error:", error); return NextResponse.redirect(`${FRONTEND_URL}/?error=auth_failed`); } }