diff --git a/packages/backend/package.json b/packages/backend/package.json index 8f07f80911..353613bb57 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -120,9 +120,9 @@ "file-type": "19.3.0", "fluent-ffmpeg": "2.1.3", "form-data": "4.0.0", - "glob": "10.3.10", + "glob": "11.0.0", "got": "14.4.2", - "happy-dom": "15.6.1", + "happy-dom": "15.7.4", "hpagent": "1.2.0", "htmlescape": "1.1.1", "http-link-header": "1.1.3", diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index 47f64f6609..808795fdac 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -64,15 +64,6 @@ export class ApiCallService implements OnApplicationShutdown { let statusCode = err.httpStatusCode; if (err.httpStatusCode === 401) { reply.header('WWW-Authenticate', 'Bearer realm="Misskey"'); - } else if (err.kind === 'client') { - reply.header('WWW-Authenticate', `Bearer realm="Misskey", error="invalid_request", error_description="${err.message}"`); - statusCode = statusCode ?? 400; - } else if (err.kind === 'permission') { - // (ROLE_PERMISSION_DENIEDは関係ない) - if (err.code === 'PERMISSION_DENIED') { - reply.header('WWW-Authenticate', `Bearer realm="Misskey", error="insufficient_scope", error_description="${err.message}"`); - } - statusCode = statusCode ?? 403; } else if (err.code === 'RATE_LIMIT_EXCEEDED') { const info: unknown = err.info; const unixEpochInSeconds = Date.now(); @@ -83,6 +74,15 @@ export class ApiCallService implements OnApplicationShutdown { } else { this.logger.warn(`rate limit information has unexpected type ${typeof(err.info?.reset)}`); } + } else if (err.kind === 'client') { + reply.header('WWW-Authenticate', `Bearer realm="Misskey", error="invalid_request", error_description="${err.message}"`); + statusCode = statusCode ?? 400; + } else if (err.kind === 'permission') { + // (ROLE_PERMISSION_DENIEDは関係ない) + if (err.code === 'PERMISSION_DENIED') { + reply.header('WWW-Authenticate', `Bearer realm="Misskey", error="insufficient_scope", error_description="${err.message}"`); + } + statusCode = statusCode ?? 403; } else if (!statusCode) { statusCode = 500; } diff --git a/packages/backend/src/server/api/RateLimiterService.ts b/packages/backend/src/server/api/RateLimiterService.ts index e94160a657..e9afb9d05a 100644 --- a/packages/backend/src/server/api/RateLimiterService.ts +++ b/packages/backend/src/server/api/RateLimiterService.ts @@ -32,18 +32,11 @@ export class RateLimiterService { @bindThis public limit(limitation: IEndpointMeta['limit'] & { key: NonNullable }, actor: string, factor = 1) { - { - if (this.disabled) { - return Promise.resolve(); - } - - // those lines with the "wrong" brace style / indentation are - // done that way so that the *other* lines stay identical to - // Misskey, simplifying merges + return new Promise((ok, reject) => { + if (this.disabled) ok(); // Short-term limit - // eslint-disable-next-line brace-style - const minP = () => { return new Promise((ok, reject) => { + const minP = (): void => { const minIntervalLimiter = new Limiter({ id: `${actor}:${limitation.key}:min`, duration: limitation.minInterval! * factor, @@ -62,18 +55,16 @@ export class RateLimiterService { return reject({ code: 'BRIEF_REQUEST_INTERVAL', info }); } else { if (hasLongTermLimit) { - return maxP().then(ok, reject); + return maxP(); } else { return ok(); } } }); - // eslint-disable-next-line brace-style - }); }; + }; // Long term limit - // eslint-disable-next-line brace-style - const maxP = () => { return new Promise((ok, reject) => { + const maxP = (): void => { const limiter = new Limiter({ id: `${actor}:${limitation.key}`, duration: limitation.duration! * factor, @@ -94,8 +85,7 @@ export class RateLimiterService { return ok(); } }); - // eslint-disable-next-line brace-style - }); }; + }; const hasShortTermLimit = typeof limitation.minInterval === 'number'; @@ -104,12 +94,12 @@ export class RateLimiterService { typeof limitation.max === 'number'; if (hasShortTermLimit) { - return minP(); + minP(); } else if (hasLongTermLimit) { - return maxP(); + maxP(); } else { - return Promise.resolve(); + ok(); } - } + }); } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d297feacf1..31efc9a89a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -251,14 +251,14 @@ importers: specifier: 4.0.0 version: 4.0.0 glob: - specifier: 10.3.10 - version: 10.3.10 + specifier: 11.0.0 + version: 11.0.0 got: specifier: 14.4.2 version: 14.4.2 happy-dom: - specifier: 15.6.1 - version: 15.6.1 + specifier: 15.7.4 + version: 15.7.4 hpagent: specifier: 1.2.0 version: 1.2.0 @@ -7580,11 +7580,6 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true - glob@10.4.2: - resolution: {integrity: sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==} - engines: {node: '>=16 || 14 >=14.18'} - hasBin: true - glob@11.0.0: resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} engines: {node: 20 || >=22} @@ -7671,8 +7666,8 @@ packages: happy-dom@10.0.3: resolution: {integrity: sha512-WkCP+Z5fX6U5PY+yHP3ElV5D9PoxRAHRWPFq3pG9rg/6Hjf5ak7dozAgSCywsTRUq2qfa8vV8OQvUy5pRXy8EQ==} - happy-dom@15.6.1: - resolution: {integrity: sha512-dsMHLsJHZYhXeExP47B2siAfKNVxptlwFss3/bq/9sG3iBt0P2WYFBq68JgMR5vB5gsN2Ev0feTTPD/+rosUNQ==} + happy-dom@15.7.4: + resolution: {integrity: sha512-r1vadDYGMtsHAAsqhDuk4IpPvr6N8MGKy5ntBo7tSdim+pWDxus2PNqOcOt8LuDZ4t3KJHE+gCuzupcx/GKnyQ==} engines: {node: '>=18.0.0'} hard-rejection@2.1.0: @@ -7902,6 +7897,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -8220,10 +8216,6 @@ packages: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} - jackspeak@3.4.0: - resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==} - engines: {node: '>=14'} - jackspeak@4.0.1: resolution: {integrity: sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==} engines: {node: 20 || >=22} @@ -9538,10 +9530,6 @@ packages: resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} engines: {node: '>=16 || 14 >=14.17'} - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - path-scurry@2.0.0: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} @@ -11121,7 +11109,6 @@ packages: ts-case-convert@2.0.2: resolution: {integrity: sha512-vdKfx1VAdpvEBOBv5OpVu5ZFqRg9HdTI4sYt6qqMeICBeNyXvitrarCnFWNDAki51IKwCyx+ZssY46Q9jH5otA==} - bundledDependencies: [] ts-dedent@2.2.0: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} @@ -11633,8 +11620,8 @@ packages: vue-component-type-helpers@2.0.29: resolution: {integrity: sha512-58i+ZhUAUpwQ+9h5Hck0D+jr1qbYl4voRt5KffBx8qzELViQ4XdT/Tuo+mzq8u63teAG8K0lLaOiL5ofqW38rg==} - vue-component-type-helpers@2.1.2: - resolution: {integrity: sha512-URuxnrOhO9lUG4LOAapGWBaa/WOLDzzyAbL+uKZqT7RS+PFy0cdXI2mUSh7GaMts6vtHaeVbGk7trd0FPJi65Q==} + vue-component-type-helpers@2.1.6: + resolution: {integrity: sha512-ng11B8B/ZADUMMOsRbqv0arc442q7lifSubD0v8oDXIFoMg/mXwAPUunrroIDkY+mcD0dHKccdaznSVp8EoX3w==} vue-demi@0.14.7: resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==} @@ -14082,7 +14069,7 @@ snapshots: content-disposition: 0.5.4 fastify-plugin: 4.5.0 fastq: 1.17.1 - glob: 10.4.2 + glob: 10.3.10 '@fastify/view@8.2.0': dependencies: @@ -16281,7 +16268,7 @@ snapshots: ts-dedent: 2.2.0 type-fest: 2.19.0 vue: 3.4.37(typescript@5.5.4) - vue-component-type-helpers: 2.1.2 + vue-component-type-helpers: 2.1.6 transitivePeerDependencies: - encoding - prettier @@ -16300,7 +16287,7 @@ snapshots: ts-dedent: 2.2.0 type-fest: 2.19.0 vue: 3.4.37(typescript@5.5.4) - vue-component-type-helpers: 2.1.2 + vue-component-type-helpers: 2.1.6 '@swc/cli@0.3.12(@swc/core@1.6.6)(chokidar@3.5.3)': dependencies: @@ -20034,15 +20021,6 @@ snapshots: minipass: 7.0.4 path-scurry: 1.10.1 - glob@10.4.2: - dependencies: - foreground-child: 3.1.1 - jackspeak: 3.4.0 - minimatch: 9.0.4 - minipass: 7.1.2 - package-json-from-dist: 1.0.0 - path-scurry: 1.11.1 - glob@11.0.0: dependencies: foreground-child: 3.1.1 @@ -20179,7 +20157,7 @@ snapshots: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 - happy-dom@15.6.1: + happy-dom@15.7.4: dependencies: entities: 4.5.0 webidl-conversions: 7.0.0 @@ -20694,12 +20672,6 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 - jackspeak@3.4.0: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - jackspeak@4.0.1: dependencies: '@isaacs/cliui': 8.0.2 @@ -22434,11 +22406,6 @@ snapshots: lru-cache: 10.2.2 minipass: 7.0.4 - path-scurry@1.11.1: - dependencies: - lru-cache: 10.2.2 - minipass: 7.1.2 - path-scurry@2.0.0: dependencies: lru-cache: 11.0.0 @@ -24597,7 +24564,7 @@ snapshots: vue-component-type-helpers@2.0.29: {} - vue-component-type-helpers@2.1.2: {} + vue-component-type-helpers@2.1.6: {} vue-demi@0.14.7(vue@3.4.37(typescript@5.5.4)): dependencies: