diff --git a/package.json b/package.json index 4bc562454..5cf338265 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "katex": "^0.16.4", "kbar": "0.1.0-beta.40", "koa": "^2.13.4", - "koa-body": "^4.2.0", + "koa-body": "^6.0.1", "koa-compress": "^5.1.0", "koa-helmet": "^6.1.0", "koa-logger": "^3.2.1", diff --git a/server/routes/api/cron.ts b/server/routes/api/cron.ts index 606cc102a..7a46b9bce 100644 --- a/server/routes/api/cron.ts +++ b/server/routes/api/cron.ts @@ -8,12 +8,10 @@ import tasks from "@server/queues/tasks"; const router = new Router(); const cronHandler = async (ctx: Context) => { - const { token, limit = 500 } = (ctx.method === "POST" - ? ctx.request.body - : ctx.request.query) as { - token?: string; - limit: number; - }; + const token = + ctx.method === "POST" ? ctx.request.body?.token : ctx.query.token; + const limit = + (ctx.method === "POST" ? ctx.request.body?.limit : ctx.query.limit) ?? 500; if (!token || typeof token !== "string") { throw AuthenticationError("Token is required"); diff --git a/server/routes/api/documents/documents.ts b/server/routes/api/documents/documents.ts index 3b4eaf048..0245e6d3c 100644 --- a/server/routes/api/documents/documents.ts +++ b/server/routes/api/documents/documents.ts @@ -13,6 +13,7 @@ import documentMover from "@server/commands/documentMover"; import documentPermanentDeleter from "@server/commands/documentPermanentDeleter"; import documentUpdater from "@server/commands/documentUpdater"; import { sequelize } from "@server/database/sequelize"; +import env from "@server/env"; import { NotFoundError, InvalidRequestError, @@ -44,10 +45,10 @@ import { } from "@server/presenters"; import { APIContext } from "@server/types"; import { RateLimiterStrategy } from "@server/utils/RateLimiter"; +import { getFileFromRequest } from "@server/utils/koa"; import { getTeamFromContext } from "@server/utils/passport"; import slugify from "@server/utils/slugify"; import { assertPresent } from "@server/validation"; -import env from "../../../env"; import pagination from "../middlewares/pagination"; import * as T from "./schema"; @@ -1111,9 +1112,7 @@ router.post( const { collectionId, parentDocumentId, publish } = ctx.input.body; - const file = ctx.request.files - ? Object.values(ctx.request.files)[0] - : undefined; + const file = getFileFromRequest(ctx.request); if (!file) { throw InvalidRequestError("Request must include a file parameter"); } @@ -1151,12 +1150,12 @@ router.post( }); } - const content = await fs.readFile(file.path); + const content = await fs.readFile(file.filepath); const document = await sequelize.transaction(async (transaction) => { const { text, title } = await documentImporter({ user, - fileName: file.name, - mimeType: file.type, + fileName: file.originalFilename ?? file.newFilename, + mimeType: file.mimetype ?? "", content, ip: ctx.request.ip, transaction, diff --git a/server/utils/koa.ts b/server/utils/koa.ts new file mode 100644 index 000000000..14a48bb9b --- /dev/null +++ b/server/utils/koa.ts @@ -0,0 +1,25 @@ +import formidable from "formidable"; +import { Request } from "koa"; +import { isArray } from "lodash"; + +/** + * Get the first file from an incoming koa request + * + * @param request The incoming request + * @returns The first file or undefined + */ +export const getFileFromRequest = ( + request: Request +): formidable.File | undefined => { + const { files } = request; + if (!files) { + return undefined; + } + + const file = Object.values(files)[0]; + if (!file) { + return undefined; + } + + return isArray(file) ? file[0] : file; +}; diff --git a/yarn.lock b/yarn.lock index ff057651c..524d96791 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2552,6 +2552,14 @@ dependencies: "@types/node" "*" +"@types/co-body@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/co-body/-/co-body-6.1.0.tgz#b52625390eb0d113c9b697ea92c3ffae7740cdb9" + integrity sha512-3e0q2jyDAnx/DSZi0z2H0yoZ2wt5yRDZ+P7ymcMObvq0ufWRT4tsajyO+Q1VwVWiv9PRR4W3YEjEzBjeZlhF+w== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/connect@*": version "3.4.35" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" @@ -2640,11 +2648,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== -"@types/events@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" - integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== - "@types/express-serve-static-core@^4.17.18": version "4.17.24" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz#ea41f93bf7e0d59cd5a76665068ed6aab6815c07" @@ -2671,14 +2674,6 @@ "@types/qs" "*" "@types/serve-static" "*" -"@types/formidable@^1.0.31": - version "1.0.31" - resolved "https://registry.yarnpkg.com/@types/formidable/-/formidable-1.0.31.tgz#274f9dc2d0a1a9ce1feef48c24ca0859e7ec947b" - integrity sha512-dIhM5t8lRP0oWe2HF8MuPvdd1TpPTjhDMAqemcq6oIZQCBQTovhBAdTQ5L5veJB4pdQChadmHuxtB0YzqvfU3Q== - dependencies: - "@types/events" "*" - "@types/node" "*" - "@types/formidable@^2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@types/formidable/-/formidable-2.0.5.tgz#e54e31d242ef750ac2d05aa163fa0274c8e6ef9c" @@ -2896,10 +2891,10 @@ dependencies: koa-useragent "*" -"@types/koa@*", "@types/koa@^2.13.1", "@types/koa@^2.13.4": - version "2.13.4" - resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.4.tgz#10620b3f24a8027ef5cbae88b393d1b31205726b" - integrity sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw== +"@types/koa@*", "@types/koa@^2.13.1", "@types/koa@^2.13.4", "@types/koa@^2.13.5": + version "2.13.5" + resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.5.tgz#64b3ca4d54e08c0062e89ec666c9f45443b21a61" + integrity sha512-HSUOdzKz3by4fnqagwthW/1w/yJspTgppyyalPVbgZf8jQWvdIXcVW5h2DGtw4zYntOaeRGx49r1hxoPWrD4aA== dependencies: "@types/accepts" "*" "@types/content-disposition" "*" @@ -4362,7 +4357,7 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -bytes@^3.0.0, bytes@^3.1.0: +bytes@3.1.2, bytes@^3.0.0, bytes@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== @@ -4651,15 +4646,15 @@ cluster-key-slot@^1.1.0: resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw== -co-body@^5.1.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/co-body/-/co-body-5.2.0.tgz#5a0a658c46029131e0e3a306f67647302f71c124" - integrity sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ== +co-body@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/co-body/-/co-body-6.1.0.tgz#d87a8efc3564f9bfe3aced8ef5cd04c7a8766547" + integrity sha512-m7pOT6CdLN7FuXUcpuz/8lfQ/L77x8SchHCF4G0RBTJO20Wzmhn5Sp4/5WsKy8OSpifBSUrmg83qEqaDHdyFuQ== dependencies: inflation "^2.0.0" - qs "^6.4.0" - raw-body "^2.2.0" - type-is "^1.6.14" + qs "^6.5.2" + raw-body "^2.3.3" + type-is "^1.6.16" co@^4.6.0: version "4.6.0" @@ -6800,11 +6795,6 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -formidable@^1.1.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9" - integrity sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q== - formidable@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.0.1.tgz#4310bc7965d185536f9565184dee74fbb75557ff" @@ -8808,14 +8798,17 @@ kleur@^4.1.4: resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.4.tgz#8c202987d7e577766d039a8cd461934c01cda04d" integrity sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA== -koa-body@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/koa-body/-/koa-body-4.2.0.tgz#37229208b820761aca5822d14c5fc55cee31b26f" - integrity sha512-wdGu7b9amk4Fnk/ytH8GuWwfs4fsB5iNkY8kZPpgQVb04QZSv85T0M8reb+cJmvLE8cjPYvBzRikD3s6qz8OoA== +koa-body@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/koa-body/-/koa-body-6.0.1.tgz#46c490033cceebb2874c53cfbb04c45562cf3c84" + integrity sha512-M8ZvMD8r+kPHy28aWP9VxL7kY8oPWA+C7ZgCljrCMeaU7uX6wsIQgDHskyrAr9sw+jqnIXyv4Mlxri5R4InIJg== dependencies: - "@types/formidable" "^1.0.31" - co-body "^5.1.1" - formidable "^1.1.1" + "@types/co-body" "^6.1.0" + "@types/formidable" "^2.0.5" + "@types/koa" "^2.13.5" + co-body "^6.1.0" + formidable "^2.0.1" + zod "^3.19.1" koa-compose@^3.0.0, koa-compose@^3.2.1: version "3.2.1" @@ -10788,7 +10781,7 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -qs@6.9.3, qs@6.9.7, qs@^6.10.3, qs@^6.4.0: +qs@6.9.3, qs@6.9.7, qs@^6.10.3, qs@^6.5.2: version "6.9.7" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== @@ -10894,6 +10887,16 @@ raw-body@^2.2.0: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@^2.3.3: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + react-avatar-editor@^13.0.0: version "13.0.0" resolved "https://registry.yarnpkg.com/react-avatar-editor/-/react-avatar-editor-13.0.0.tgz#55013625ee9ae715c1fe2dc553b8079994d8a5f2" @@ -12767,7 +12770,7 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -type-is@^1.6.14, type-is@^1.6.16: +type-is@^1.6.16: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== @@ -13689,7 +13692,7 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zod@^3.20.2: - version "3.20.2" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.20.2.tgz#068606642c8f51b3333981f91c0a8ab37dfc2807" - integrity sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ== +zod@^3.19.1, zod@^3.20.2: + version "3.20.6" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.20.6.tgz#2f2f08ff81291d47d99e86140fedb4e0db08361a" + integrity sha512-oyu0m54SGCtzh6EClBVqDDlAYRz4jrVtKwQ7ZnsEmMI9HnzuZFj8QFwAY1M5uniIYACdGvv0PBWPF2kO0aNofA==