pr_01m47d15m3e54sn21z27rpy5n9/apps/web/app/routes/github-setup.tsx

66 lines2,874 bytesCodeBlame
1import { Link, data, redirect } from "react-router";
2
3import type { Route } from "./+types/github-setup";
4import { AuthCard } from "../components/auth-card";
5import { INSTALL_COOKIE, cookie, installWorkspace, readCookie } from "../lib/github";
6import { githubApp } from "../lib/github.server";
7import { page } from "../lib/meta";
8import { requireUser } from "../lib/session.server";
9
10export function meta(args: Route.MetaArgs) {
11 return page(args, { title: "Connecting GitHub · g1t" });
12}
13
14/**
15 * The app's Setup URL: GitHub returns here after an installation with
16 * `installation_id`, `setup_action` and the state. The installation is
17 * recorded against the workspace it was started for, after integrations
18 * checks with the person's own GitHub token that they can see it.
19 */
20export async function loader({ request, context }: Route.LoaderArgs) {
21 const user = requireUser(context, request);
22 const url = new URL(request.url);
23 const clear = { "set-cookie": cookie(INSTALL_COOKIE, "", 0) };
24 const workspace = installWorkspace(readCookie(request.headers.get("cookie"), INSTALL_COOKIE), url.searchParams.get("state"));
25 const action = url.searchParams.get("setup_action");
26 const installation = Number(url.searchParams.get("installation_id"));
27 // Repositories chosen again on GitHub: nothing to record, the picker
28 // lists what the installation can see now.
29 if (!workspace && action === "update") throw redirect("/new/github", { headers: clear });
30 if (!workspace) {
31 return data(
32 { error: "This installation did not start from g1t in this browser. Start again from New project.", workspace: null },
33 { headers: clear },
34 );
35 }
36 const back = `/new/github?workspace=${encodeURIComponent(workspace)}`;
37 // An organization member asked an owner to approve: nothing to record yet.
38 if (action === "request") throw redirect(`${back}&requested=1`, { headers: clear });
39 if (!Number.isSafeInteger(installation) || installation <= 0) {
40 return data({ error: "GitHub did not say which installation was made.", workspace }, { headers: clear });
41 }
42 const added = await githubApp.addInstallation(user, workspace, installation);
43 if (!added.ok) return data({ error: added.error.message, workspace }, { headers: clear });
44 throw redirect(`${back}&installation=${installation}`, { headers: clear });
45}
46
47export default function GithubSetup({ loaderData }: Route.ComponentProps) {
48 return (
49 <AuthCard
50 title="Connecting GitHub"
51 subtitle="That did not work"
52 footer={
53 <Link
54 to={loaderData.workspace ? `/new/github?workspace=${loaderData.workspace}` : "/new"}
55 className="text-fg underline underline-offset-4"
56 >
57 Back to New project
58 </Link>
59 }
60 >
61 <p className="text-sm text-danger" role="alert">
62 {loaderData.error}
63 </p>
64 </AuthCard>
65 );
66}