From 79bd299b685609bf0720ee88dbaec4f2b1186369 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Wed, 9 Mar 2022 11:08:57 -0600 Subject: [PATCH] Enforce max question length, description length, and tag length. --- common/contract.ts | 4 ++++ common/util/parse.ts | 4 +++- functions/src/create-contract.ts | 24 ++++++++++++++++++++---- web/components/feed-create.tsx | 3 ++- web/pages/create.tsx | 3 ++- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/common/contract.ts b/common/contract.ts index 11609329..83d1139e 100644 --- a/common/contract.ts +++ b/common/contract.ts @@ -41,3 +41,7 @@ export type Contract = { } export type outcomeType = 'BINARY' | 'MULTI' | 'FREE_RESPONSE' + +export const MAX_QUESTION_LENGTH = 480 +export const MAX_DESCRIPTION_LENGTH = 10000 +export const MAX_TAG_LENGTH = 60 diff --git a/common/util/parse.ts b/common/util/parse.ts index 10876b12..b73bdfb3 100644 --- a/common/util/parse.ts +++ b/common/util/parse.ts @@ -1,7 +1,9 @@ +import { MAX_TAG_LENGTH } from '../contract' + export function parseTags(text: string) { const regex = /(?:^|\s)(?:[#][a-z0-9_]+)/gi const matches = (text.match(regex) || []).map((match) => - match.trim().substring(1) + match.trim().substring(1).substring(0, MAX_TAG_LENGTH) ) const tagSet = new Set() const uniqueTags: string[] = [] diff --git a/functions/src/create-contract.ts b/functions/src/create-contract.ts index bb78f134..0bad05ea 100644 --- a/functions/src/create-contract.ts +++ b/functions/src/create-contract.ts @@ -1,8 +1,15 @@ import * as functions from 'firebase-functions' import * as admin from 'firebase-admin' +import * as _ from 'lodash' import { chargeUser, getUser } from './utils' -import { Contract, outcomeType } from '../../common/contract' +import { + Contract, + MAX_DESCRIPTION_LENGTH, + MAX_QUESTION_LENGTH, + MAX_TAG_LENGTH, + outcomeType, +} from '../../common/contract' import { slugify } from '../../common/util/slugify' import { randomString } from '../../common/util/random' import { getNewContract } from '../../common/new-contract' @@ -34,10 +41,19 @@ export const createContract = functions const creator = await getUser(userId) if (!creator) return { status: 'error', message: 'User not found' } - const { question, description, initialProb, ante, closeTime, tags } = data + let { question, description, initialProb, ante, closeTime, tags } = data - if (!question) - return { status: 'error', message: 'Missing question field' } + if (!question || typeof question != 'string') + return { status: 'error', message: 'Missing or invalid question field' } + question = question.slice(0, MAX_QUESTION_LENGTH) + + if (typeof description !== 'string') + return { status: 'error', message: 'Invalid description field' } + description = description.slice(0, MAX_DESCRIPTION_LENGTH) + + if (tags !== undefined && !_.isArray(tags)) + return { status: 'error', message: 'Invalid tags field' } + tags = tags?.map((tag) => tag.toString().slice(0, MAX_TAG_LENGTH)) let outcomeType = data.outcomeType ?? 'BINARY' if (!['BINARY', 'MULTI', 'FREE_RESPONSE'].includes(outcomeType)) diff --git a/web/components/feed-create.tsx b/web/components/feed-create.tsx index 00bbc31f..de4d6e22 100644 --- a/web/components/feed-create.tsx +++ b/web/components/feed-create.tsx @@ -5,7 +5,7 @@ import { Spacer } from './layout/spacer' import { NewContract } from '../pages/create' import { firebaseLogin, User } from '../lib/firebase/users' import { ContractsGrid } from './contracts-list' -import { Contract } from '../../common/contract' +import { Contract, MAX_QUESTION_LENGTH } from '../../common/contract' import { Col } from './layout/col' import clsx from 'clsx' import { Row } from './layout/row' @@ -121,6 +121,7 @@ export default function FeedCreate(props: { placeholder={placeholder} value={question} rows={question.length > 68 ? 4 : 2} + maxLength={MAX_QUESTION_LENGTH} onClick={(e) => e.stopPropagation()} onChange={(e) => setQuestion(e.target.value.replace('\n', ''))} onFocus={() => setIsExpanded(true)} diff --git a/web/pages/create.tsx b/web/pages/create.tsx index 5e8830e0..c4feb11c 100644 --- a/web/pages/create.tsx +++ b/web/pages/create.tsx @@ -18,7 +18,7 @@ import { ProbabilitySelector } from '../components/probability-selector' import { parseWordsAsTags } from '../../common/util/parse' import { TagsList } from '../components/tags-list' import { Row } from '../components/layout/row' -import { outcomeType } from '../../common/contract' +import { MAX_DESCRIPTION_LENGTH, outcomeType } from '../../common/contract' export default function Create() { const [question, setQuestion] = useState('') @@ -186,6 +186,7 @@ export function NewContract(props: { question: string; tag?: string }) {