chore: convert submodules to standard directories for true monorepo structure

This commit is contained in:
2026-05-13 14:54:23 -07:00
parent 4339da259c
commit abf9bf89c2
761 changed files with 133928 additions and 2 deletions

View File

@@ -0,0 +1,56 @@
/**
* GET /api/integrations/github/connect
*
* Kicks off GitHub OAuth. Generates an unguessable `state`, stores it
* in a short-lived (10 min) httpOnly cookie, and 302s to GitHub's
* authorize endpoint.
*
* The callback route validates the cookie matches the `state` GitHub
* echoes back, defending against login-CSRF.
*/
import { NextResponse } from "next/server";
import { randomBytes } from "crypto";
import { authSession } from "@/lib/auth/session-server";
import {
buildAuthorizeUrl, isGithubOauthConfigured,
} from "@/lib/integrations/github";
const STATE_COOKIE = "gh_oauth_state";
const STATE_TTL_S = 10 * 60;
export async function GET(req: Request) {
if (!isGithubOauthConfigured()) {
return NextResponse.json(
{ error: "GitHub OAuth is not configured on this server." },
{ status: 503 },
);
}
const session = await authSession();
if (!session?.user?.email) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const url = new URL(req.url);
// Use NEXTAUTH_URL when available — behind a proxy req.url.origin
// resolves to the internal bind address (0.0.0.0) rather than the
// public hostname, which GitHub then rejects as an unregistered URI.
const appOrigin = (process.env.NEXTAUTH_URL ?? url.origin).replace(/\/$/, "");
const callbackUrl = `${appOrigin}/api/integrations/github/callback`;
const returnTo = url.searchParams.get("returnTo") ?? "/";
const state = randomBytes(16).toString("hex");
const statePayload = `${state}:${returnTo}`;
const authorize = buildAuthorizeUrl(state, callbackUrl);
const res = NextResponse.redirect(authorize);
res.cookies.set(STATE_COOKIE, statePayload, {
httpOnly: true,
sameSite: "lax",
path: "/",
secure: url.protocol === "https:",
maxAge: STATE_TTL_S,
});
return res;
}