Skip to content

Commit

Permalink
feat(publish-quota): per user publishArticle quota
Browse files Browse the repository at this point in the history
resolves #3842
  • Loading branch information
49659410+tx0c committed Apr 16, 2024
1 parent 6f15387 commit 4305b0c
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
13 changes: 13 additions & 0 deletions db/migrations/20240417164251_alter_user_add_publish_rate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const table = 'user'

exports.up = async (knex) => {
await knex.schema.table(table, (t) => {
t.jsonb('publish_rate')
})
}

exports.down = async (knex) => {
await knex.schema.table(table, (t) => {
t.dropColumn('publish_rate')
})
}
24 changes: 23 additions & 1 deletion src/mutations/article/publishArticle.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import type { GQLMutationResolvers } from 'definitions'
import type { Redis } from 'ioredis'

import { PUBLISH_STATE, USER_STATE } from 'common/enums'
import {
PUBLISH_ARTICLE_RATE_LIMIT,
PUBLISH_ARTICLE_RATE_PERIOD,
PUBLISH_STATE,
USER_STATE,
} from 'common/enums'
import {
DraftNotFoundError,
ForbiddenByStateError,
ForbiddenError,
UserInputError,
} from 'common/errors'
import { fromGlobalId } from 'common/utils'
import { checkOperationLimit } from 'types/directives'

const resolver: GQLMutationResolvers['publishArticle'] = async (
_,
Expand All @@ -18,6 +25,7 @@ const resolver: GQLMutationResolvers['publishArticle'] = async (
draftService,
atomService,
queues: { publicationQueue },
redis,
},
}
) => {
Expand Down Expand Up @@ -50,6 +58,20 @@ const resolver: GQLMutationResolvers['publishArticle'] = async (
throw new UserInputError('content is required')
}

const pass = await checkOperationLimit({
user: viewer.id || viewer.ip,
operation: 'publishArticle',
limit: viewer?.publishRate?.limit ?? (isProd ? 1 : 1000), // PUBLISH_ARTICLE_RATE_LIMIT,
period: viewer?.publishRate?.period ?? 720, // PUBLISH_ARTICLE_RATE_PERIOD,
redis, // : connections.redis,
})

if (!pass) {
throw new ActionLimitExceededError(
`rate exceeded for operation ${fieldName}`
)
}

if (
draft.publishState === PUBLISH_STATE.pending ||
(draft.archived && isPublished)
Expand Down
2 changes: 1 addition & 1 deletion src/types/directives/rateLimit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CACHE_PREFIX } from 'common/enums'
import { ActionLimitExceededError } from 'common/errors'
import { genCacheKey } from 'connectors'

const checkOperationLimit = async ({
export const checkOperationLimit = async ({
user,
operation,
limit,
Expand Down

0 comments on commit 4305b0c

Please sign in to comment.