Migrate transact function to v2 (#635)
This commit is contained in:
parent
581a42f288
commit
67a05c2f1b
|
@ -3,7 +3,6 @@ import * as admin from 'firebase-admin'
|
|||
admin.initializeApp()
|
||||
|
||||
// v1
|
||||
export * from './transact'
|
||||
export * from './stripe'
|
||||
export * from './create-user'
|
||||
export * from './on-create-bet'
|
||||
|
@ -28,6 +27,7 @@ export * from './on-create-txn'
|
|||
|
||||
// v2
|
||||
export * from './health'
|
||||
export * from './transact'
|
||||
export * from './change-user-info'
|
||||
export * from './create-answer'
|
||||
export * from './place-bet'
|
||||
|
|
|
@ -1,40 +1,40 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
|
||||
import { User } from '../../common/user'
|
||||
import { Txn } from '../../common/txn'
|
||||
import { removeUndefinedProps } from '../../common/util/object'
|
||||
import { APIError, newEndpoint } from './api'
|
||||
|
||||
export type TxnData = Omit<Txn, 'id' | 'createdTime'>
|
||||
|
||||
export const transact = functions
|
||||
.runWith({ minInstances: 1 })
|
||||
.https.onCall(async (data: TxnData, context) => {
|
||||
const userId = context?.auth?.uid
|
||||
if (!userId) return { status: 'error', message: 'Not authorized' }
|
||||
// TODO: We totally fail to validate most of the input to this function,
|
||||
// so anyone can spam our database with malformed transactions.
|
||||
|
||||
const { amount, fromType, fromId } = data
|
||||
export const transact = newEndpoint({}, async (req, auth) => {
|
||||
const data = req.body
|
||||
const { amount, fromType, fromId } = data
|
||||
|
||||
if (fromType !== 'USER')
|
||||
return {
|
||||
status: 'error',
|
||||
message: "From type is only implemented for type 'user'.",
|
||||
}
|
||||
if (fromType !== 'USER')
|
||||
throw new APIError(400, "From type is only implemented for type 'user'.")
|
||||
|
||||
if (fromId !== userId)
|
||||
return {
|
||||
status: 'error',
|
||||
message: 'Must be authenticated with userId equal to specified fromId.',
|
||||
}
|
||||
if (fromId !== auth.uid)
|
||||
throw new APIError(
|
||||
403,
|
||||
'Must be authenticated with userId equal to specified fromId.'
|
||||
)
|
||||
|
||||
if (isNaN(amount) || !isFinite(amount))
|
||||
return { status: 'error', message: 'Invalid amount' }
|
||||
if (isNaN(amount) || !isFinite(amount))
|
||||
throw new APIError(400, 'Invalid amount')
|
||||
|
||||
// Run as transaction to prevent race conditions.
|
||||
return await firestore.runTransaction(async (transaction) => {
|
||||
await runTxn(transaction, data)
|
||||
})
|
||||
// Run as transaction to prevent race conditions.
|
||||
return await firestore.runTransaction(async (transaction) => {
|
||||
const result = await runTxn(transaction, data)
|
||||
if (result.status == 'error') {
|
||||
throw new APIError(500, result.message ?? 'An unknown error occurred.')
|
||||
}
|
||||
return result
|
||||
})
|
||||
})
|
||||
|
||||
export async function runTxn(
|
||||
fbTransaction: admin.firestore.Transaction,
|
||||
|
|
|
@ -11,7 +11,7 @@ import { debounce, sum } from 'lodash'
|
|||
import { useEffect, useRef, useState } from 'react'
|
||||
import { CommentTips } from 'web/hooks/use-tip-txns'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { transact } from 'web/lib/firebase/fn-call'
|
||||
import { transact } from 'web/lib/firebase/api-call'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
import { Row } from './layout/row'
|
||||
import { Tooltip } from './tooltip'
|
||||
|
|
|
@ -54,6 +54,10 @@ export function createAnswer(params: any) {
|
|||
return call(getFunctionUrl('createanswer'), 'POST', params)
|
||||
}
|
||||
|
||||
export function transact(params: any) {
|
||||
return call(getFunctionUrl('transact'), 'POST', params)
|
||||
}
|
||||
|
||||
export function changeUserInfo(params: any) {
|
||||
return call(getFunctionUrl('changeuserinfo'), 'POST', params)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { httpsCallable } from 'firebase/functions'
|
||||
import { Txn } from 'common/txn'
|
||||
import { User } from 'common/user'
|
||||
import { randomString } from 'common/util/random'
|
||||
import './init'
|
||||
|
@ -9,11 +8,6 @@ import { safeLocalStorage } from '../util/local'
|
|||
export const cloudFunction = <RequestData, ResponseData>(name: string) =>
|
||||
httpsCallable<RequestData, ResponseData>(functions, name)
|
||||
|
||||
export const transact = cloudFunction<
|
||||
Omit<Txn, 'id' | 'createdTime'>,
|
||||
{ status: 'error' | 'success'; message?: string; txn?: Txn }
|
||||
>('transact')
|
||||
|
||||
export const createUser: () => Promise<User | null> = () => {
|
||||
const local = safeLocalStorage()
|
||||
let deviceToken = local?.getItem('device-token')
|
||||
|
|
|
@ -10,7 +10,7 @@ import { Spacer } from 'web/components/layout/spacer'
|
|||
import { User } from 'common/user'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { Linkify } from 'web/components/linkify'
|
||||
import { transact } from 'web/lib/firebase/fn-call'
|
||||
import { transact } from 'web/lib/firebase/api-call'
|
||||
import { charities, Charity } from 'common/charity'
|
||||
import { useRouter } from 'next/router'
|
||||
import Custom404 from '../404'
|
||||
|
|
Loading…
Reference in New Issue
Block a user