diff --git a/package-lock.json b/package-lock.json index 1edbca058..3d2ba7617 100644 --- a/package-lock.json +++ b/package-lock.json @@ -861,7 +861,8 @@ }, "lodash": { "version": "4.17.11", - "resolved": "", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "supports-color": { @@ -3092,7 +3093,8 @@ }, "lodash": { "version": "4.17.11", - "resolved": "", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "supports-color": { @@ -8062,6 +8064,12 @@ "@types/node": "*" } }, + "@types/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-5YG1AiIC8HPPXRvYAIa7ehK3YMAwd0DWiPCtpuL9sgKceWLyWsVtLRA+lT4NkoanDNF9slwQ66lPizWDpgRlWA==", + "dev": true + }, "@types/case-sensitive-paths-webpack-plugin": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@types/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.1.4.tgz", @@ -8156,10 +8164,13 @@ "integrity": "sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg==" }, "@types/convict": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@types/convict/-/convict-4.2.1.tgz", - "integrity": "sha512-2cd51m3i0yeY1i3dKxcqJKeS5Q4jZnjP37OseoNeIX1OM0AhmGPuuYmwJ9OqtsU35YrREQxdb2VeX5sM3cwGMQ==", - "dev": true + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@types/convict/-/convict-5.2.1.tgz", + "integrity": "sha512-SbtKO7CzkSaBZ/yMo9+qDPG2q59BN2ONry2Qra+boPXoXfjW4gVX/ohcmRsKpZZGGNszkLCl2Wi8coIDp/qPQg==", + "dev": true, + "requires": { + "@types/node": "*" + } }, "@types/cookie": { "version": "0.3.3", @@ -13360,9 +13371,9 @@ } }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, "cacache": { "version": "13.0.1", @@ -14594,6 +14605,12 @@ "vary": "~1.1.2" }, "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -21648,7 +21665,7 @@ "integrity": "sha1-ETOUSrJHeINHOZVZaIPg05z4hc8=", "dev": true, "requires": { - "intl-pluralrules": "github:projectfluent/IntlPluralRules#94cb0fa1c23ad943bc5aafef43cea132fa51d68b" + "intl-pluralrules": "github:projectfluent/IntlPluralRules#module" }, "dependencies": { "intl-pluralrules": { @@ -28412,7 +28429,8 @@ "version": "2.1.1", "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -28444,6 +28462,7 @@ "resolved": false, "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -28460,7 +28479,8 @@ "version": "1.1.0", "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", @@ -28473,7 +28493,8 @@ "version": "1.1.0", "resolved": false, "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -28604,7 +28625,8 @@ "version": "2.0.3", "resolved": false, "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -28618,6 +28640,7 @@ "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -28634,6 +28657,7 @@ "resolved": false, "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -28648,6 +28672,7 @@ "resolved": false, "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -28665,7 +28690,22 @@ }, "mkdirp": { "version": "0.5.5", - "dev": true + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "optional": true, + "requires": { + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true, + "optional": true + } + } }, "ms": { "version": "2.1.1", @@ -28751,7 +28791,8 @@ "version": "1.0.1", "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -28765,6 +28806,7 @@ "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -28823,7 +28865,8 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "", + "resolved": false, + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true } @@ -28859,7 +28902,8 @@ "version": "5.1.2", "resolved": false, "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -28901,6 +28945,7 @@ "resolved": false, "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -28922,6 +28967,7 @@ "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -28935,7 +28981,8 @@ }, "tar": { "version": "4.4.8", - "resolved": "", + "resolved": false, + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, "requires": { @@ -28969,13 +29016,15 @@ "version": "1.0.2", "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "resolved": false, "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true + "dev": true, + "optional": true } } }, @@ -45053,6 +45102,11 @@ "unpipe": "1.0.0" }, "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, "depd": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", @@ -50782,6 +50836,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -50791,13 +50846,15 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "optional": true } } }, @@ -53819,6 +53876,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, + "optional": true, "requires": { "is-extglob": "^2.1.1" } @@ -53834,7 +53892,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "dev": true, + "optional": true }, "readdirp": { "version": "3.4.0", diff --git a/package.json b/package.json index ea2b69160..2c7a403c1 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "bcryptjs": "^2.4.3", "bull": "^3.13.0", "bunyan": "^1.8.12", + "bytes": "^3.1.0", "cheerio": "^1.0.0-rc.3", "consolidate": "0.14.0", "content-security-policy-builder": "^2.1.0", @@ -162,13 +163,14 @@ "@types/bcryptjs": "^2.4.2", "@types/bull": "^3.12.1", "@types/bunyan": "^1.8.6", + "@types/bytes": "^3.1.0", "@types/case-sensitive-paths-webpack-plugin": "^2.1.4", "@types/cheerio": "^0.22.17", "@types/classnames": "^2.2.10", "@types/common-tags": "^1.8.0", "@types/compression-webpack-plugin": "^2.0.1", "@types/consolidate": "0.14.0", - "@types/convict": "^4.2.1", + "@types/convict": "^5.2.1", "@types/cookie": "^0.3.3", "@types/cookie-parser": "^1.4.2", "@types/cors": "^2.8.6", diff --git a/src/core/server/app/middleware/json.ts b/src/core/server/app/middleware/json.ts index ae25bc383..af76a0112 100644 --- a/src/core/server/app/middleware/json.ts +++ b/src/core/server/app/middleware/json.ts @@ -1,3 +1,8 @@ -import express from "express"; +import bodyParser from "body-parser"; -export const jsonMiddleware = express.json({}); +/** + * jsonMiddleware is middleware that will parse the incoming JSON payloads. + * + * @param limit the amount of bytes to allow for POST requests + */ +export const jsonMiddleware = (limit: number) => bodyParser.json({ limit }); diff --git a/src/core/server/app/router/api/account.ts b/src/core/server/app/router/api/account.ts index 100fbc652..7e290dc9d 100644 --- a/src/core/server/app/router/api/account.ts +++ b/src/core/server/app/router/api/account.ts @@ -1,4 +1,5 @@ import bodyParser from "body-parser"; +import bytes from "bytes"; import { AppOptions } from "coral-server/app"; import { @@ -18,6 +19,9 @@ import { RouterOptions } from "coral-server/app/router/types"; import { createAPIRouter } from "./helpers"; +// REQUEST_MAX is the maximum request size for routes on this router. +const REQUEST_MAX = bytes("100kb"); + export function createNewAccountRouter( app: AppOptions, { passport }: Pick @@ -26,7 +30,7 @@ export function createNewAccountRouter( router.post( "/confirm", - jsonMiddleware, + jsonMiddleware(REQUEST_MAX), authenticate(passport), confirmRequestHandler(app) ); @@ -34,7 +38,7 @@ export function createNewAccountRouter( router.put("/confirm", confirmHandler(app)); router.get("/invite", inviteCheckHandler(app)); - router.put("/invite", jsonMiddleware, inviteHandler(app)); + router.put("/invite", jsonMiddleware(REQUEST_MAX), inviteHandler(app)); router.get("/notifications/unsubscribe", unsubscribeCheckHandler(app)); router.delete("/notifications/unsubscribe", unsubscribeHandler(app)); diff --git a/src/core/server/app/router/api/auth.ts b/src/core/server/app/router/api/auth.ts index 6bc5e1b56..797027eef 100644 --- a/src/core/server/app/router/api/auth.ts +++ b/src/core/server/app/router/api/auth.ts @@ -1,3 +1,4 @@ +import bytes from "bytes"; import express from "express"; import { AppOptions } from "coral-server/app"; @@ -21,6 +22,9 @@ import { RouterOptions } from "coral-server/app/router/types"; import { createAPIRouter } from "./helpers"; +// REQUEST_MAX is the maximum request size for routes on this router. +const REQUEST_MAX = bytes("100kb"); + function wrapPath( app: AppOptions, { passport }: Pick, @@ -43,21 +47,25 @@ export function createNewAuthRouter( // Mount the Local Authentication handlers. router.post( "/local", - jsonMiddleware, + jsonMiddleware(REQUEST_MAX), wrapAuthn(passport, app.signingConfig, "local") ); - router.post("/local/signup", jsonMiddleware, signupHandler(app)); + router.post("/local/signup", jsonMiddleware(REQUEST_MAX), signupHandler(app)); router.get("/local/forgot", forgotCheckHandler(app)); - router.put("/local/forgot", jsonMiddleware, forgotResetHandler(app)); - router.post("/local/forgot", jsonMiddleware, forgotHandler(app)); + router.put( + "/local/forgot", + jsonMiddleware(REQUEST_MAX), + forgotResetHandler(app) + ); + router.post("/local/forgot", jsonMiddleware(REQUEST_MAX), forgotHandler(app)); // Mount the link handler. router.post( "/link", authenticate(passport), loggedInMiddleware, - jsonMiddleware, + jsonMiddleware(REQUEST_MAX), linkHandler(app) ); diff --git a/src/core/server/app/router/api/index.ts b/src/core/server/app/router/api/index.ts index 3e3d43837..a8e2de4e2 100644 --- a/src/core/server/app/router/api/index.ts +++ b/src/core/server/app/router/api/index.ts @@ -55,7 +55,7 @@ export function createAPIRouter(app: AppOptions, options: RouterOptions) { router.use( "/graphql", authenticate(options.passport), - jsonMiddleware, + jsonMiddleware(app.config.get("max_request_size")), persistedQueryMiddleware(app), graphQLHandler(app) ); diff --git a/src/core/server/app/router/api/install.ts b/src/core/server/app/router/api/install.ts index a270548b3..ee09b6f98 100644 --- a/src/core/server/app/router/api/install.ts +++ b/src/core/server/app/router/api/install.ts @@ -1,3 +1,4 @@ +import bytes from "bytes"; import { Router } from "express"; import { AppOptions } from "coral-server/app"; @@ -7,6 +8,9 @@ import { tenantMiddleware } from "coral-server/app/middleware/tenant"; import { createAPIRouter } from "./helpers"; +// REQUEST_MAX is the maximum request size for routes on this router. +const REQUEST_MAX = bytes("100kb"); + export function createNewInstallRouter(app: AppOptions): Router { // Create a router. const router = createAPIRouter(); @@ -18,7 +22,7 @@ export function createNewInstallRouter(app: AppOptions): Router { ); router.post( "/", - jsonMiddleware, + jsonMiddleware(REQUEST_MAX), tenantMiddleware({ cache: app.tenantCache, passNoTenant: true }), installHandler(app) ); diff --git a/src/core/server/config.ts b/src/core/server/config.ts index 5151c380f..4fc5739ef 100644 --- a/src/core/server/config.ts +++ b/src/core/server/config.ts @@ -1,4 +1,5 @@ import Joi from "@hapi/joi"; +import bytes from "bytes"; import convict from "convict"; import { parseConnectionString } from "mongodb-core"; import ms from "ms"; @@ -55,6 +56,16 @@ convict.addFormat({ coerce: (val: string): number => ms(val), }); +// Add a custom format that is a number of bytes parsed with `bytes`. This +// allows more compact representations of values (10mb instead of 10e6). +convict.addFormat({ + name: "bytes", + validate: (val: number) => { + Joi.assert(val, Joi.number().positive().integer().required()); + }, + coerce: (val: string): number => bytes(val), +}); + const algorithms = [ "HS256", "HS384", @@ -188,7 +199,7 @@ const config = convict({ doc: "The keepalive timeout (in ms) that should be used to send keep alive messages through the websocket to keep the socket alive", format: "ms", - default: "30 seconds", + default: ms("30 seconds"), env: "WEBSOCKET_KEEP_ALIVE_TIMEOUT", }, disable_tenant_caching: { @@ -209,7 +220,7 @@ const config = convict({ doc: "Disables subscriptions for the comment stream for all stories across all tenants where a comment has not been left within the timeout", format: "ms", - default: "2 weeks", + default: ms("2 weeks"), env: "DISABLE_LIVE_UPDATES_TIMEOUT", }, disable_client_routes: { @@ -228,22 +239,27 @@ const config = convict({ }, scrape_max_response_size: { doc: "The maximum size (in bytes) to allow for scraping responses.", - format: Number, - default: 10e6, + format: "bytes", + default: bytes("10mb"), env: "SCRAPE_MAX_RESPONSE_SIZE", - arg: "scrapeMaxResponseSize", + }, + max_request_size: { + doc: "The maximum size (in bytes) to allow for post bodies to accept.", + format: "bytes", + default: bytes("500kb"), + env: "MAX_REQUEST_SIZE", }, scrape_timeout: { doc: "The request timeout (in ms) for scraping operations.", format: "ms", - default: "10 seconds", + default: ms("10 seconds"), env: "SCRAPE_TIMEOUT", }, perspective_timeout: { doc: "The request timeout (in ms) for perspective comment checking operations.", format: "ms", - default: "800 milliseconds", + default: ms("800 milliseconds"), env: "PERSPECTIVE_TIMEOUT", }, force_ssl: { @@ -263,7 +279,7 @@ const config = convict({ doc: "The word list timeout (in ms) that should be used to limit the amount of time the process is frozen processing a word list comparison", format: "ms", - default: "100", + default: ms("100ms"), env: "WORD_LIST_TIMEOUT", }, analytics_frontend_key: { diff --git a/src/core/server/events/listeners/perspective.ts b/src/core/server/events/listeners/perspective.ts index b2b0ec5d1..d988470be 100644 --- a/src/core/server/events/listeners/perspective.ts +++ b/src/core/server/events/listeners/perspective.ts @@ -80,11 +80,8 @@ export class PerspectiveCoralEventListener // Reconstruct the Tenant URL. const tenantURL = reconstructTenantURL(ctx.config, ctx.tenant); - // This typecast is needed because the custom `ms` format does not return the - // desired `number` type even though that's the only type it can output. - const timeout = (ctx.config.get( - "perspective_timeout" - ) as unknown) as number; + // Get the timeout value. + const timeout = ctx.config.get("perspective_timeout"); // Get the response from perspective. const result = await sendToPerspective( diff --git a/src/core/server/graph/loaders/Stories.ts b/src/core/server/graph/loaders/Stories.ts index 514f585d1..6e93e6c47 100644 --- a/src/core/server/graph/loaders/Stories.ts +++ b/src/core/server/graph/loaders/Stories.ts @@ -210,12 +210,9 @@ export default (ctx: GraphContext) => ({ }).then(primeStoriesFromConnection(ctx)), debugScrapeMetadata: new DataLoader( createManyBatchLoadFn((url: string) => - // This typecast is needed because the custom `ms` format does not return - // the desired `number` type even though that's the only type it can - // output. scraper.scrape({ url, - timeout: (ctx.config.get("scrape_timeout") as unknown) as number, + timeout: ctx.config.get("scrape_timeout"), size: ctx.config.get("scrape_max_response_size"), customUserAgent: ctx.tenant.stories.scraping.customUserAgent, proxyURL: ctx.tenant.stories.scraping.proxyURL, diff --git a/src/core/server/graph/resolvers/LiveConfiguration.ts b/src/core/server/graph/resolvers/LiveConfiguration.ts index 23e3ea355..2c7f7625e 100644 --- a/src/core/server/graph/resolvers/LiveConfiguration.ts +++ b/src/core/server/graph/resolvers/LiveConfiguration.ts @@ -18,11 +18,9 @@ export const LiveConfiguration: GQLLiveConfigurationTypeResolver 0) { // If one of these is available, use it to determine the time since the // last comment. diff --git a/src/core/server/graph/subscriptions/server.ts b/src/core/server/graph/subscriptions/server.ts index 1d9320f66..a2265a276 100644 --- a/src/core/server/graph/subscriptions/server.ts +++ b/src/core/server/graph/subscriptions/server.ts @@ -259,11 +259,7 @@ export function createSubscriptionServer( schema: GraphQLSchema, options: Options ) { - // This typecast is needed because the custom `ms` format does not return the - // desired `number` type even though that's the only type it can output. - const keepAlive = (options.config.get( - "websocket_keep_alive_timeout" - ) as unknown) as number; + const keepAlive = options.config.get("websocket_keep_alive_timeout"); return SubscriptionServer.create( { diff --git a/src/core/server/services/comments/pipeline/phases/toxic.ts b/src/core/server/services/comments/pipeline/phases/toxic.ts index f2b296774..370c16267 100644 --- a/src/core/server/services/comments/pipeline/phases/toxic.ts +++ b/src/core/server/services/comments/pipeline/phases/toxic.ts @@ -73,9 +73,8 @@ export const toxic: IntermediateModerationPhase = async ({ ); } - // This typecast is needed because the custom `ms` format does not return the - // desired `number` type even though that's the only type it can output. - const timeout = (config.get("perspective_timeout") as unknown) as number; + // Get the timeout value. + const timeout = config.get("perspective_timeout"); try { // FEATURE_FLAG:DISABLE_WARN_USER_OF_TOXIC_COMMENT diff --git a/src/core/server/services/comments/pipeline/phases/wordList.ts b/src/core/server/services/comments/pipeline/phases/wordList.ts index 71eab6880..0e6c162b0 100755 --- a/src/core/server/services/comments/pipeline/phases/wordList.ts +++ b/src/core/server/services/comments/pipeline/phases/wordList.ts @@ -27,7 +27,7 @@ export const wordList: IntermediateModerationPhase = ({ } // Get the timeout to use. - const timeout = (config.get("word_list_timeout") as unknown) as number; + const timeout = config.get("word_list_timeout"); // Test the comment for banned words. const banned = list.test(tenant, "banned", timeout, bodyText); diff --git a/src/core/server/services/stories/scraper/scraper.ts b/src/core/server/services/stories/scraper/scraper.ts index e921037ee..3cadc2aed 100644 --- a/src/core/server/services/stories/scraper/scraper.ts +++ b/src/core/server/services/stories/scraper/scraper.ts @@ -189,9 +189,7 @@ export async function scrape( storyURL = retrievedStory.url; } - // This typecast is needed because the custom `ms` format does not return the - // desired `number` type even though that's the only type it can output. - const timeout = (config.get("scrape_timeout") as unknown) as number; + const timeout = config.get("scrape_timeout"); const size = config.get("scrape_max_response_size"); // Get the metadata from the scraped html.