import { OAuthApp } from "../index.js"; import { unknownRouteResponse } from "./unknown-route-response.js"; async function handleRequest(app, { pathPrefix = "/api/github/oauth" }, request) { let { pathname } = new URL(request.url, "http://localhost"); if (!pathname.startsWith(`${pathPrefix}/`)) { return void 0; } if (request.method === "OPTIONS") { return { status: 200, headers: { "access-control-allow-origin": "*", "access-control-allow-methods": "*", "access-control-allow-headers": "Content-Type, User-Agent, Authorization" } }; } pathname = pathname.slice(pathPrefix.length + 1); const route = [request.method, pathname].join(" "); const routes = { getLogin: `GET login`, getCallback: `GET callback`, createToken: `POST token`, getToken: `GET token`, patchToken: `PATCH token`, patchRefreshToken: `PATCH refresh-token`, scopeToken: `POST token/scoped`, deleteToken: `DELETE token`, deleteGrant: `DELETE grant` }; if (!Object.values(routes).includes(route)) { return unknownRouteResponse(request); } let json; try { const text = await request.text(); json = text ? JSON.parse(text) : {}; } catch (error) { return { status: 400, headers: { "content-type": "application/json", "access-control-allow-origin": "*" }, text: JSON.stringify({ error: "[@octokit/oauth-app] request error" }) }; } const { searchParams } = new URL(request.url, "http://localhost"); const query = Object.fromEntries(searchParams); const headers = request.headers; try { if (route === routes.getLogin) { const authOptions = {}; if (query.state) { Object.assign(authOptions, { state: query.state }); } if (query.scopes) { Object.assign(authOptions, { scopes: query.scopes.split(",") }); } if (query.allowSignup) { Object.assign(authOptions, { allowSignup: query.allowSignup === "true" }); } if (query.redirectUrl) { Object.assign(authOptions, { redirectUrl: query.redirectUrl }); } const { url } = app.getWebFlowAuthorizationUrl(authOptions); return { status: 302, headers: { location: url } }; } if (route === routes.getCallback) { if (query.error) { throw new Error( `[@octokit/oauth-app] ${query.error} ${query.error_description}` ); } if (!query.code) { throw new Error('[@octokit/oauth-app] "code" parameter is required'); } const { authentication: { token: token2 } } = await app.createToken({ code: query.code }); return { status: 200, headers: { "content-type": "text/html" }, text: `

Token created successfully

Your token is: ${token2}. Copy it now as it cannot be shown again.

` }; } if (route === routes.createToken) { const { code, redirectUrl } = json; if (!code) { throw new Error('[@octokit/oauth-app] "code" parameter is required'); } const result = await app.createToken({ code, redirectUrl }); delete result.authentication.clientSecret; return { status: 201, headers: { "content-type": "application/json", "access-control-allow-origin": "*" }, text: JSON.stringify(result) }; } if (route === routes.getToken) { const token2 = headers.authorization?.substr("token ".length); if (!token2) { throw new Error( '[@octokit/oauth-app] "Authorization" header is required' ); } const result = await app.checkToken({ token: token2 }); delete result.authentication.clientSecret; return { status: 200, headers: { "content-type": "application/json", "access-control-allow-origin": "*" }, text: JSON.stringify(result) }; } if (route === routes.patchToken) { const token2 = headers.authorization?.substr("token ".length); if (!token2) { throw new Error( '[@octokit/oauth-app] "Authorization" header is required' ); } const result = await app.resetToken({ token: token2 }); delete result.authentication.clientSecret; return { status: 200, headers: { "content-type": "application/json", "access-control-allow-origin": "*" }, text: JSON.stringify(result) }; } if (route === routes.patchRefreshToken) { const token2 = headers.authorization?.substr("token ".length); if (!token2) { throw new Error( '[@octokit/oauth-app] "Authorization" header is required' ); } const { refreshToken } = json; if (!refreshToken) { throw new Error( "[@octokit/oauth-app] refreshToken must be sent in request body" ); } const result = await app.refreshToken({ refreshToken }); delete result.authentication.clientSecret; return { status: 200, headers: { "content-type": "application/json", "access-control-allow-origin": "*" }, text: JSON.stringify(result) }; } if (route === routes.scopeToken) { const token2 = headers.authorization?.substr("token ".length); if (!token2) { throw new Error( '[@octokit/oauth-app] "Authorization" header is required' ); } const result = await app.scopeToken({ token: token2, ...json }); delete result.authentication.clientSecret; return { status: 200, headers: { "content-type": "application/json", "access-control-allow-origin": "*" }, text: JSON.stringify(result) }; } if (route === routes.deleteToken) { const token2 = headers.authorization?.substr("token ".length); if (!token2) { throw new Error( '[@octokit/oauth-app] "Authorization" header is required' ); } await app.deleteToken({ token: token2 }); return { status: 204, headers: { "access-control-allow-origin": "*" } }; } const token = headers.authorization?.substr("token ".length); if (!token) { throw new Error( '[@octokit/oauth-app] "Authorization" header is required' ); } await app.deleteAuthorization({ token }); return { status: 204, headers: { "access-control-allow-origin": "*" } }; } catch (error) { return { status: 400, headers: { "content-type": "application/json", "access-control-allow-origin": "*" }, text: JSON.stringify({ error: error.message }) }; } } export { handleRequest };