Skip to content
31 linesCodeBlameRaw
1/**
2 * Where a connector's sign-in comes back to: the server sends the browser
3 * here with the `state` the sign-in started with and a `code` (or an
4 * `error`). The agents service finishes the sign-in, lists the connector's
5 * tools, and the browser lands on the connector's page saying so.
6 */
7import { data, redirect } from "react-router";
8
9import { customizePath } from "@g1t/contracts/customize";
10
11import type { Route } from "./+types/connector-callback";
12import { connectorPagePath } from "../../../lib/customize";
13import { workspaceAgents } from "../../../lib/services.server";
14import { requireUser, roleIn } from "../../../lib/session.server";
15
16export async function loader({ params, context, request }: Route.LoaderArgs) {
17 const viewer = requireUser(context, request);
18 const slug = params.owner.toLowerCase();
19 if (!roleIn(viewer, slug)) throw data(null, { status: 404 });
20 const url = new URL(request.url);
21 const back = (problem: string) => redirect(`${customizePath("connectors", slug)}?problem=${encodeURIComponent(problem)}`);
22 const error = url.searchParams.get("error");
23 if (error) return back(`The sign-in didn't finish: ${url.searchParams.get("error_description") || error}.`);
24 const state = url.searchParams.get("state") ?? "";
25 const code = url.searchParams.get("code") ?? "";
26 if (!state || !code) return back("The sign-in came back without what it needs. Start it again.");
27 const done = await workspaceAgents.finishConnectorSignIn(slug, viewer, state, code).catch(() => null);
28 if (!done) return back("The agents service didn't answer. Start the sign-in again in a moment.");
29 if (!done.ok) return back(done.error.message);
30 return redirect(`${connectorPagePath(slug, done.value.id)}?signed_in=1`);
31}