Skip to content

Commit 0874edb

Browse files
committed
Write rate limits (#1578)
* get rate limit ip correctly * add write rate-limits
1 parent 54a1184 commit 0874edb

File tree

5 files changed

+77
-1
lines changed

5 files changed

+77
-1
lines changed

packages/pds/src/api/com/atproto/repo/applyWrites.ts

+28
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { InvalidRequestError, AuthRequiredError } from '@atproto/xrpc-server'
33
import { prepareCreate, prepareDelete, prepareUpdate } from '../../../../repo'
44
import { Server } from '../../../../lexicon'
55
import {
6+
HandlerInput,
67
isCreate,
78
isUpdate,
89
isDelete,
@@ -15,9 +16,36 @@ import {
1516
import AppContext from '../../../../context'
1617
import { ConcurrentWriteError } from '../../../../services/repo'
1718

19+
const ratelimitPoints = ({ input }: { input: HandlerInput }) => {
20+
let points = 0
21+
for (const op of input.body.writes) {
22+
if (isCreate(op)) {
23+
points += 3
24+
} else if (isUpdate(op)) {
25+
points += 2
26+
} else {
27+
points += 1
28+
}
29+
}
30+
return points
31+
}
32+
1833
export default function (server: Server, ctx: AppContext) {
1934
server.com.atproto.repo.applyWrites({
2035
auth: ctx.accessVerifierCheckTakedown,
36+
rateLimit: [
37+
{
38+
name: 'repo-write-hour',
39+
calcKey: ({ auth }) => auth.credentials.did,
40+
calcPoints: ratelimitPoints,
41+
},
42+
{
43+
name: 'repo-write-day',
44+
calcKey: ({ auth }) => auth.credentials.did,
45+
calcPoints: ratelimitPoints,
46+
},
47+
],
48+
2149
handler: async ({ input, auth }) => {
2250
const tx = input.body
2351
const { repo, validate, swapCommit } = tx

packages/pds/src/api/com/atproto/repo/createRecord.ts

+12
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ import { ConcurrentWriteError } from '../../../../services/repo'
1616
export default function (server: Server, ctx: AppContext) {
1717
server.com.atproto.repo.createRecord({
1818
auth: ctx.accessVerifierCheckTakedown,
19+
rateLimit: [
20+
{
21+
name: 'repo-write-hour',
22+
calcKey: ({ auth }) => auth.credentials.did,
23+
calcPoints: () => 3,
24+
},
25+
{
26+
name: 'repo-write-day',
27+
calcKey: ({ auth }) => auth.credentials.did,
28+
calcPoints: () => 3,
29+
},
30+
],
1931
handler: async ({ input, auth }) => {
2032
const { repo, collection, rkey, record, swapCommit, validate } =
2133
input.body

packages/pds/src/api/com/atproto/repo/deleteRecord.ts

+12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@ import { ConcurrentWriteError } from '../../../../services/repo'
99
export default function (server: Server, ctx: AppContext) {
1010
server.com.atproto.repo.deleteRecord({
1111
auth: ctx.accessVerifierCheckTakedown,
12+
rateLimit: [
13+
{
14+
name: 'repo-write-hour',
15+
calcKey: ({ auth }) => auth.credentials.did,
16+
calcPoints: () => 1,
17+
},
18+
{
19+
name: 'repo-write-day',
20+
calcKey: ({ auth }) => auth.credentials.did,
21+
calcPoints: () => 1,
22+
},
23+
],
1224
handler: async ({ input, auth }) => {
1325
const { repo, collection, rkey, swapCommit, swapRecord } = input.body
1426
const did = await ctx.services.account(ctx.db).getDidForActor(repo)

packages/pds/src/api/com/atproto/repo/putRecord.ts

+12
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ import { ConcurrentWriteError } from '../../../../services/repo'
1616
export default function (server: Server, ctx: AppContext) {
1717
server.com.atproto.repo.putRecord({
1818
auth: ctx.accessVerifierCheckTakedown,
19+
rateLimit: [
20+
{
21+
name: 'repo-write-hour',
22+
calcKey: ({ auth }) => auth.credentials.did,
23+
calcPoints: () => 2,
24+
},
25+
{
26+
name: 'repo-write-day',
27+
calcKey: ({ auth }) => auth.credentials.did,
28+
calcPoints: () => 2,
29+
},
30+
],
1931
handler: async ({ auth, input }) => {
2032
const {
2133
repo,

packages/pds/src/index.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
RateLimiterOpts,
2121
Options as XrpcServerOptions,
2222
} from '@atproto/xrpc-server'
23-
import { MINUTE } from '@atproto/common'
23+
import { DAY, HOUR, MINUTE } from '@atproto/common'
2424
import * as appviewConsumers from './app-view/event-stream/consumers'
2525
import inProcessAppView from './app-view/api'
2626
import API from './api'
@@ -288,6 +288,18 @@ export class PDS {
288288
points: 3000,
289289
},
290290
],
291+
shared: [
292+
{
293+
name: 'repo-write-hour',
294+
durationMs: HOUR,
295+
points: 5000, // creates=3, puts=2, deletes=1
296+
},
297+
{
298+
name: 'repo-write-day',
299+
durationMs: DAY,
300+
points: 35000, // creates=3, puts=2, deletes=1
301+
},
302+
],
291303
}
292304
}
293305

0 commit comments

Comments
 (0)