From f6eb3148f365683a5baa628c3494b590417d7542 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sun, 4 May 2025 08:55:26 -0400 Subject: [PATCH 1/2] use bucket rate limit for featured timeline --- .../backend/src/server/api/endpoints/notes/featured.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index 734ff31700..b5d2a71ecd 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -30,10 +30,11 @@ export const meta = { }, }, - // 10 calls per 5 seconds + // Burst of 10 calls to handle tab reload, then 4/second for refresh limit: { - duration: 1000 * 5, - max: 10, + type: 'bucket', + size: 10, + dripSize: 4, }, } as const; From 76597d1a4c7ee04244a35c2c4dcfe6dc5dc85ac1 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sun, 4 May 2025 08:55:57 -0400 Subject: [PATCH 2/2] check role assignments in featured timeline --- .../src/server/api/endpoints/notes/featured.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index b5d2a71ecd..02d572e89b 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -12,6 +12,8 @@ import { FeaturedService } from '@/core/FeaturedService.js'; import { isUserRelated } from '@/misc/is-user-related.js'; import { CacheService } from '@/core/CacheService.js'; import { QueryService } from '@/core/QueryService.js'; +import { ApiError } from '@/server/api/error.js'; +import { RoleService } from '@/core/RoleService.js'; export const meta = { tags: ['notes'], @@ -30,6 +32,14 @@ export const meta = { }, }, + errors: { + ltlDisabled: { + message: 'Local timeline has been disabled.', + code: 'LTL_DISABLED', + id: '45a6eb02-7695-4393-b023-dd3be9aaaefd', + }, + }, + // Burst of 10 calls to handle tab reload, then 4/second for refresh limit: { type: 'bucket', @@ -61,8 +71,14 @@ export default class extends Endpoint { // eslint- private noteEntityService: NoteEntityService, private featuredService: FeaturedService, private queryService: QueryService, + private readonly roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { + const policies = await this.roleService.getUserPolicies(me ? me.id : null); + if (!policies.ltlAvailable) { + throw new ApiError(meta.errors.ltlDisabled); + } + let noteIds: string[]; if (ps.channelId) { noteIds = await this.featuredService.getInChannelNotesRanking(ps.channelId, 50);