diff --git a/src/common/enums/quote.ts b/src/common/enums/quote.ts index f1734a20c..e2dafe2fd 100644 --- a/src/common/enums/quote.ts +++ b/src/common/enums/quote.ts @@ -6,7 +6,3 @@ export const QUOTE_STATE = { // a quote is a "one-glance" excerpt; longer text is a paragraph, not a quote export const MAX_QUOTE_LENGTH = 80 - -// anti-abuse caps (product-decided defaults, tunable) -export const QUOTE_DAILY_LIMIT = 5 -export const QUOTE_PER_ARTICLE_LIMIT = 2 diff --git a/src/mutations/quote/putQuote.ts b/src/mutations/quote/putQuote.ts index 43df816cb..fa23a26bd 100644 --- a/src/mutations/quote/putQuote.ts +++ b/src/mutations/quote/putQuote.ts @@ -5,13 +5,10 @@ import { ARTICLE_STATE, MAX_QUOTE_LENGTH, NODE_TYPES, - QUOTE_DAILY_LIMIT, - QUOTE_PER_ARTICLE_LIMIT, QUOTE_STATE, USER_STATE, } from '#common/enums/index.js' import { - ActionLimitExceededError, ArticleNotFoundError, ForbiddenByStateError, ForbiddenError, @@ -32,7 +29,7 @@ const resolver: GQLMutationResolvers['putQuote'] = async ( dataSources: { atomService, articleService, - connections: { knexRO, redis }, + connections: { redis }, }, } ) => { @@ -127,34 +124,8 @@ const resolver: GQLMutationResolvers['putQuote'] = async ( throw new UserInputError('this quote is already on the wall') } - // per-article cap (prevents plastering the wall with one article) - const perArticleCount = await atomService.count({ - table: 'quote', - where: { - userId: viewer.id, - articleId: article.id, - state: QUOTE_STATE.active, - }, - }) - if (perArticleCount >= QUOTE_PER_ARTICLE_LIMIT) { - throw new ActionLimitExceededError( - `up to ${QUOTE_PER_ARTICLE_LIMIT} quotes per article` - ) - } - - // daily cap; counts posting actions (UTC day), retraction does not refund - const todayStart = new Date() - todayStart.setUTCHours(0, 0, 0, 0) - const dailyCount = await knexRO('quote') - .count('id') - .where({ userId: viewer.id }) - .andWhere('createdAt', '>=', todayStart) - .first() - if (Number(dailyCount?.count ?? 0) >= QUOTE_DAILY_LIMIT) { - throw new ActionLimitExceededError( - `up to ${QUOTE_DAILY_LIMIT} quotes per day` - ) - } + // no quantity caps: per-article and daily limits removed, so users may post + // any number of quotes; the content rules and dedup above still apply let quote try { diff --git a/src/types/__test__/2/quote.test.ts b/src/types/__test__/2/quote.test.ts index c892725d1..f67192c79 100644 --- a/src/types/__test__/2/quote.test.ts +++ b/src/types/__test__/2/quote.test.ts @@ -5,8 +5,6 @@ import { USER_STATE, CAMPAIGN_STATE, QUOTE_STATE, - QUOTE_DAILY_LIMIT, - QUOTE_PER_ARTICLE_LIMIT, } from '#common/enums/index.js' import { toGlobalId, fromGlobalId } from '#common/utils/index.js' import { AtomService, CampaignService } from '#connectors/index.js' @@ -255,11 +253,10 @@ describe('putQuote', () => { expect(count).toBe(1) }) - test('per-article cap blocks the next quote once the limit is reached', async () => { - // pre-fill up to the per-article limit with distinct excerpts + test('no per-article cap: more quotes from the same article still succeed', async () => { + // quantity limits removed — distinct excerpts from one article all post await seedQuote({ content: 'some' }) await seedQuote({ content: 'html' }) - expect(QUOTE_PER_ARTICLE_LIMIT).toBe(2) const server = await testClient({ connections, @@ -270,13 +267,12 @@ describe('putQuote', () => { query: PUT_QUOTE, variables: { input: { articleId: articleGlobalId, content: 'string' } }, }) - expect(errors?.[0].extensions.code).toBe('ACTION_LIMIT_EXCEEDED') + expect(errors).toBeUndefined() }) - test('daily cap blocks the next quote once the limit is reached', async () => { - // seed the daily limit worth of quotes for this user (today, any article) - expect(QUOTE_DAILY_LIMIT).toBe(5) - for (let i = 0; i < QUOTE_DAILY_LIMIT; i++) { + test('no daily cap: posting beyond the old daily limit still succeeds', async () => { + // quantity limits removed — posting many in a day no longer blocks + for (let i = 0; i < 5; i++) { await seedQuote({ content: `daily-${i}` }) } const server = await testClient({ @@ -288,7 +284,7 @@ describe('putQuote', () => { query: PUT_QUOTE, variables: { input: { articleId: articleGlobalId, content: 'string' } }, }) - expect(errors?.[0].extensions.code).toBe('ACTION_LIMIT_EXCEEDED') + expect(errors).toBeUndefined() }) })