diff --git a/functions/src/api.ts b/functions/src/api.ts index fdda0ad5..e9a488c2 100644 --- a/functions/src/api.ts +++ b/functions/src/api.ts @@ -78,6 +78,19 @@ export const lookupUser = async (creds: Credentials): Promise => { } } +export const writeResponseError = (e: unknown, res: Response) => { + if (e instanceof APIError) { + const output: { [k: string]: unknown } = { message: e.message } + if (e.details != null) { + output.details = e.details + } + res.status(e.code).json(output) + } else { + error(e) + res.status(500).json({ message: 'An unknown error occurred.' }) + } +} + export const zTimestamp = () => { return z.preprocess((arg) => { return typeof arg == 'number' ? new Date(arg) : undefined @@ -131,16 +144,7 @@ export const newEndpoint = (endpointOpts: EndpointOptions, fn: Handler) => { const authedUser = await lookupUser(await parseCredentials(req)) res.status(200).json(await fn(req, authedUser)) } catch (e) { - if (e instanceof APIError) { - const output: { [k: string]: unknown } = { message: e.message } - if (e.details != null) { - output.details = e.details - } - res.status(e.code).json(output) - } else { - error(e) - res.status(500).json({ message: 'An unknown error occurred.' }) - } + writeResponseError(e, res) } }, } as EndpointDefinition diff --git a/functions/src/get-custom-token.ts b/functions/src/get-custom-token.ts new file mode 100644 index 00000000..1f20ba09 --- /dev/null +++ b/functions/src/get-custom-token.ts @@ -0,0 +1,27 @@ +import * as admin from 'firebase-admin' +import { + APIError, + EndpointDefinition, + lookupUser, + parseCredentials, + writeResponseError, +} from './api' + +const opts = { method: 'GET', minInstances: 1 } + +export const getcustomtoken: EndpointDefinition = { + opts, + handler: async (req, res) => { + try { + const credentials = await parseCredentials(req) + if (credentials.kind != 'jwt') { + throw new APIError(403, 'API keys cannot mint custom tokens.') + } + const user = await lookupUser(credentials) + const token = await admin.auth().createCustomToken(user.uid) + res.status(200).json({ token: token }) + } catch (e) { + writeResponseError(e, res) + } + }, +} diff --git a/functions/src/index.ts b/functions/src/index.ts index 125cdea4..07b37648 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -65,6 +65,7 @@ import { unsubscribe } from './unsubscribe' import { stripewebhook, createcheckoutsession } from './stripe' import { getcurrentuser } from './get-current-user' import { acceptchallenge } from './accept-challenge' +import { getcustomtoken } from './get-custom-token' const toCloudFunction = ({ opts, handler }: EndpointDefinition) => { return onRequest(opts, handler as any) @@ -89,6 +90,7 @@ const stripeWebhookFunction = toCloudFunction(stripewebhook) const createCheckoutSessionFunction = toCloudFunction(createcheckoutsession) const getCurrentUserFunction = toCloudFunction(getcurrentuser) const acceptChallenge = toCloudFunction(acceptchallenge) +const getCustomTokenFunction = toCloudFunction(getcustomtoken) export { healthFunction as health, @@ -111,4 +113,5 @@ export { createCheckoutSessionFunction as createcheckoutsession, getCurrentUserFunction as getcurrentuser, acceptChallenge as acceptchallenge, + getCustomTokenFunction as getcustomtoken, } diff --git a/functions/src/serve.ts b/functions/src/serve.ts index 0064b69f..bf96db20 100644 --- a/functions/src/serve.ts +++ b/functions/src/serve.ts @@ -26,6 +26,7 @@ import { resolvemarket } from './resolve-market' import { unsubscribe } from './unsubscribe' import { stripewebhook, createcheckoutsession } from './stripe' import { getcurrentuser } from './get-current-user' +import { getcustomtoken } from './get-custom-token' type Middleware = (req: Request, res: Response, next: NextFunction) => void const app = express() @@ -64,6 +65,7 @@ addJsonEndpointRoute('/resolvemarket', resolvemarket) addJsonEndpointRoute('/unsubscribe', unsubscribe) addJsonEndpointRoute('/createcheckoutsession', createcheckoutsession) addJsonEndpointRoute('/getcurrentuser', getcurrentuser) +addEndpointRoute('/getcustomtoken', getcustomtoken) addEndpointRoute('/stripewebhook', stripewebhook, express.raw()) app.listen(PORT)