| 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 | */ |
| 7 | import { data, redirect } from "react-router"; |
| 8 | |
| 9 | import { customizePath } from "@g1t/contracts/customize"; |
| 10 | |
| 11 | import type { Route } from "./+types/connector-callback"; |
| 12 | import { connectorPagePath } from "../../../lib/customize"; |
| 13 | import { workspaceAgents } from "../../../lib/services.server"; |
| 14 | import { requireUser, roleIn } from "../../../lib/session.server"; |
| 15 | |
| 16 | export 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 | } |