mirror your GitHub repos to tangled.org automatically
1import { randomBytes } from 'node:crypto'
2import { githubOAuthUrl } from '#server/utils/github-app'
3import { sessionConfig } from '#server/utils/server-session'
4
5interface OAuthFlowData {
6 state: string
7 installationId: number
8}
9
10/**
11 * Begin GitHub user-to-server OAuth to prove the connecting user administers
12 * the installation they're about to bind a tangled handle to. The random
13 * `state` is sealed into a short-lived cookie and verified in the callback.
14 */
15export default defineEventHandler(async event => {
16 const query = getQuery(event)
17 const raw = query.installationId
18 if (typeof raw !== 'string' || !/^\d+$/.test(raw)) {
19 throw createError({ statusCode: 400, statusMessage: 'installationId is required and must be numeric' })
20 }
21 const installationId = Number(raw)
22
23 const state = randomBytes(16).toString('base64url')
24 const flow = await useSession<OAuthFlowData>(event, {
25 ...sessionConfig(),
26 name: 'synchub-gh-oauth',
27 maxAge: 10 * 60,
28 })
29 await flow.update({ state, installationId })
30
31 const { url } = useRuntimeConfig().public
32 const redirectUri = `${url.replace(/\/$/, '')}/api/github/oauth/callback`
33 await sendRedirect(event, githubOAuthUrl({ state, redirectUri }), 302)
34})