diff --git a/server/middlewares/authentication.test.ts b/server/middlewares/authentication.test.ts index 81e61fdf4..7a29c10bd 100644 --- a/server/middlewares/authentication.test.ts +++ b/server/middlewares/authentication.test.ts @@ -1,3 +1,4 @@ +import { DefaultState } from "koa"; import randomstring from "randomstring"; import ApiKey from "@server/models/ApiKey"; import { buildUser, buildTeam } from "@server/test/factories"; @@ -9,37 +10,35 @@ setupTestDatabase(); describe("Authentication middleware", () => { describe("with JWT", () => { it("should authenticate with correct token", async () => { - const state = {}; + const state = {} as DefaultState; const user = await buildUser(); const authMiddleware = auth(); await authMiddleware( { - // @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock; }' is missing the f... Remove this comment to see the full error message + // @ts-expect-error mock request request: { get: jest.fn(() => `Bearer ${user.getJwtToken()}`), }, - // @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message state, cache: {}, }, jest.fn() ); - // @ts-expect-error ts-migrate(2339) FIXME: Property 'user' does not exist on type '{}'. expect(state.user.id).toEqual(user.id); }); + it("should return error with invalid token", async () => { - const state = {}; + const state = {} as DefaultState; const user = await buildUser(); const authMiddleware = auth(); try { await authMiddleware( { - // @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock; }' is missing the f... Remove this comment to see the full error message + // @ts-expect-error mock request request: { get: jest.fn(() => `Bearer ${user.getJwtToken()}error`), }, - // @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message state, cache: {}, }, @@ -52,7 +51,7 @@ describe("Authentication middleware", () => { }); describe("with API key", () => { it("should authenticate user with valid API key", async () => { - const state = {}; + const state = {} as DefaultState; const user = await buildUser(); const authMiddleware = auth(); const key = await ApiKey.create({ @@ -60,31 +59,28 @@ describe("Authentication middleware", () => { }); await authMiddleware( { - // @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock; }' is missing the f... Remove this comment to see the full error message + // @ts-expect-error mock request request: { get: jest.fn(() => `Bearer ${key.secret}`), }, - // @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message state, cache: {}, }, jest.fn() ); - // @ts-expect-error ts-migrate(2339) FIXME: Property 'user' does not exist on type '{}'. expect(state.user.id).toEqual(user.id); }); it("should return error with invalid API key", async () => { - const state = {}; + const state = {} as DefaultState; const authMiddleware = auth(); try { await authMiddleware( { - // @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock; }' is missing the f... Remove this comment to see the full error message + // @ts-expect-error mock request request: { get: jest.fn(() => `Bearer ${randomstring.generate(38)}`), }, - // @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message state, cache: {}, }, @@ -97,17 +93,16 @@ describe("Authentication middleware", () => { }); it("should return error message if no auth token is available", async () => { - const state = {}; + const state = {} as DefaultState; const authMiddleware = auth(); try { await authMiddleware( { - // @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock; }' is missing the f... Remove this comment to see the full error message + // @ts-expect-error mock request request: { get: jest.fn(() => "error"), }, - // @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message state, cache: {}, }, @@ -121,54 +116,49 @@ describe("Authentication middleware", () => { }); it("should allow passing auth token as a GET param", async () => { - const state = {}; + const state = {} as DefaultState; const user = await buildUser(); const authMiddleware = auth(); await authMiddleware( { request: { - // @ts-expect-error ts-migrate(2322) FIXME: Type 'Mock' is not assignable to type '(... Remove this comment to see the full error message + // @ts-expect-error mock request get: jest.fn(() => null), query: { token: user.getJwtToken(), }, }, - body: {}, - // @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message state, cache: {}, }, jest.fn() ); - // @ts-expect-error ts-migrate(2339) FIXME: Property 'user' does not exist on type '{}'. expect(state.user.id).toEqual(user.id); }); it("should allow passing auth token in body params", async () => { - const state = {}; + const state = {} as DefaultState; const user = await buildUser(); const authMiddleware = auth(); await authMiddleware( { request: { - // @ts-expect-error ts-migrate(2322) FIXME: Type 'Mock' is not assignable to type '(... Remove this comment to see the full error message + // @ts-expect-error mock request get: jest.fn(() => null), + body: { + token: user.getJwtToken(), + }, }, - body: { - token: user.getJwtToken(), - }, - // @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message state, cache: {}, }, jest.fn() ); - // @ts-expect-error ts-migrate(2339) FIXME: Property 'user' does not exist on type '{}'. expect(state.user.id).toEqual(user.id); }); it("should return an error for suspended users", async () => { - const state = {}; + const state = {} as DefaultState; const admin = await buildUser(); const user = await buildUser({ suspendedAt: new Date(), @@ -180,11 +170,10 @@ describe("Authentication middleware", () => { try { await authMiddleware( { - // @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock; }' is missing the f... Remove this comment to see the full error message + // @ts-expect-error mock request request: { get: jest.fn(() => `Bearer ${user.getJwtToken()}`), }, - // @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message state, cache: {}, }, @@ -201,7 +190,7 @@ describe("Authentication middleware", () => { }); it("should return an error for deleted team", async () => { - const state = {}; + const state = {} as DefaultState; const team = await buildTeam(); const user = await buildUser({ teamId: team.id, @@ -213,11 +202,10 @@ describe("Authentication middleware", () => { try { await authMiddleware( { - // @ts-expect-error ts-migrate(2740) FIXME: Type '{ get: Mock; }' is missing the f... Remove this comment to see the full error message + // @ts-expect-error mock request request: { get: jest.fn(() => `Bearer ${user.getJwtToken()}`), }, - // @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'DefaultState ... Remove this comment to see the full error message state, cache: {}, }, diff --git a/server/middlewares/authentication.ts b/server/middlewares/authentication.ts index c1b1da205..299e47d16 100644 --- a/server/middlewares/authentication.ts +++ b/server/middlewares/authentication.ts @@ -43,13 +43,12 @@ export default function auth(options: AuthenticationOptions = {}) { ); } } else if ( - ctx.body && - typeof ctx.body === "object" && - "token" in ctx.body + ctx.request.body && + typeof ctx.request.body === "object" && + "token" in ctx.request.body ) { - // @ts-expect-error ts-migrate(2571) FIXME: Object is of type 'unknown'. - token = ctx.body.token; - } else if (ctx.request.query.token) { + token = ctx.request.body.token; + } else if (ctx.request.query?.token) { token = ctx.request.query.token; } else { token = ctx.cookies.get("accessToken"); diff --git a/server/middlewares/methodOverride.ts b/server/middlewares/methodOverride.ts deleted file mode 100644 index e80639a27..000000000 --- a/server/middlewares/methodOverride.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Context, Next } from "koa"; -import queryString from "query-string"; - -export default function methodOverride() { - return async function methodOverrideMiddleware(ctx: Context, next: Next) { - // TODO: Need to remove this use of ctx.body to enable proper typing of requests - if (ctx.method === "POST") { - ctx.body = ctx.request.body; - } else if (ctx.method === "GET") { - ctx.body = queryString.parse(ctx.querystring); - } - - return next(); - }; -} diff --git a/server/policies/team.ts b/server/policies/team.ts index af22bbc72..4567bc2b5 100644 --- a/server/policies/team.ts +++ b/server/policies/team.ts @@ -13,7 +13,7 @@ allow(User, "share", Team, (user, team) => { allow(User, "createTeam", Team, () => { if (env.DEPLOYMENT !== "hosted") { - throw "createTeam only available on cloud"; + throw new Error("createTeam only available on cloud"); } }); diff --git a/server/routes/api/apiKeys.ts b/server/routes/api/apiKeys.ts index fc5e33104..31f4ffa5f 100644 --- a/server/routes/api/apiKeys.ts +++ b/server/routes/api/apiKeys.ts @@ -9,7 +9,7 @@ import pagination from "./middlewares/pagination"; const router = new Router(); router.post("apiKeys.create", auth({ member: true }), async (ctx) => { - const { name } = ctx.body; + const { name } = ctx.request.body; assertPresent(name, "name is required"); const { user } = ctx.state; @@ -58,7 +58,7 @@ router.post( ); router.post("apiKeys.delete", auth({ member: true }), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; const key = await ApiKey.findByPk(id); diff --git a/server/routes/api/attachments.ts b/server/routes/api/attachments.ts index 8adfc411f..e66e95386 100644 --- a/server/routes/api/attachments.ts +++ b/server/routes/api/attachments.ts @@ -19,13 +19,13 @@ const router = new Router(); const AWS_S3_ACL = process.env.AWS_S3_ACL || "private"; router.post("attachments.create", auth(), async (ctx) => { - const isPublic = ctx.body.public; + const isPublic = ctx.request.body.public; const { name, documentId, contentType = "application/octet-stream", size, - } = ctx.body; + } = ctx.request.body; assertPresent(name, "name is required"); assertPresent(size, "size is required"); @@ -118,7 +118,7 @@ router.post("attachments.create", auth(), async (ctx) => { }); router.post("attachments.delete", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; const attachment = await Attachment.findByPk(id, { @@ -147,7 +147,7 @@ router.post("attachments.delete", auth(), async (ctx) => { }); const handleAttachmentsRedirect = async (ctx: ContextWithState) => { - const { id } = ctx.body as { id?: string }; + const { id } = (ctx.request.body ?? ctx.request.query) as { id?: string }; assertUuid(id, "id is required"); const { user } = ctx.state; diff --git a/server/routes/api/authenticationProviders.ts b/server/routes/api/authenticationProviders.ts index 030283f94..4715ace1b 100644 --- a/server/routes/api/authenticationProviders.ts +++ b/server/routes/api/authenticationProviders.ts @@ -12,7 +12,7 @@ import allAuthenticationProviders from "../auth/providers"; const router = new Router(); router.post("authenticationProviders.info", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; const authenticationProvider = await AuthenticationProvider.findByPk(id); @@ -25,7 +25,7 @@ router.post("authenticationProviders.info", auth(), async (ctx) => { }); router.post("authenticationProviders.update", auth(), async (ctx) => { - const { id, isEnabled } = ctx.body; + const { id, isEnabled } = ctx.request.body; assertUuid(id, "id is required"); assertPresent(isEnabled, "isEnabled is required"); const { user } = ctx.state; diff --git a/server/routes/api/collections.ts b/server/routes/api/collections.ts index 26bd0a397..5a11723db 100644 --- a/server/routes/api/collections.ts +++ b/server/routes/api/collections.ts @@ -61,8 +61,8 @@ router.post("collections.create", auth(), async (ctx) => { sharing, icon, sort = Collection.DEFAULT_SORT, - } = ctx.body; - let { index } = ctx.body; + } = ctx.request.body; + let { index } = ctx.request.body; assertPresent(name, "name is required"); if (color) { @@ -131,7 +131,7 @@ router.post("collections.create", auth(), async (ctx) => { }); router.post("collections.info", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertPresent(id, "id is required"); const { user } = ctx.state; const collection = await Collection.scope({ @@ -151,7 +151,10 @@ router.post( auth(), rateLimiter(RateLimiterStrategy.TenPerHour), async (ctx) => { - const { attachmentId, format = FileOperationFormat.MarkdownZip } = ctx.body; + const { + attachmentId, + format = FileOperationFormat.MarkdownZip, + } = ctx.request.body; assertUuid(attachmentId, "attachmentId is required"); const { user } = ctx.state; @@ -201,7 +204,11 @@ router.post( ); router.post("collections.add_group", auth(), async (ctx) => { - const { id, groupId, permission = CollectionPermission.ReadWrite } = ctx.body; + const { + id, + groupId, + permission = CollectionPermission.ReadWrite, + } = ctx.request.body; assertUuid(id, "id is required"); assertUuid(groupId, "groupId is required"); assertCollectionPermission(permission); @@ -255,7 +262,7 @@ router.post("collections.add_group", auth(), async (ctx) => { }); router.post("collections.remove_group", auth(), async (ctx) => { - const { id, groupId } = ctx.body; + const { id, groupId } = ctx.request.body; assertUuid(id, "id is required"); assertUuid(groupId, "groupId is required"); @@ -290,7 +297,7 @@ router.post( auth(), pagination(), async (ctx) => { - const { id, query, permission } = ctx.body; + const { id, query, permission } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; @@ -351,7 +358,7 @@ router.post( ); router.post("collections.add_user", auth(), async (ctx) => { - const { id, userId, permission } = ctx.body; + const { id, userId, permission } = ctx.request.body; assertUuid(id, "id is required"); assertUuid(userId, "userId is required"); @@ -411,7 +418,7 @@ router.post("collections.add_user", auth(), async (ctx) => { }); router.post("collections.remove_user", auth(), async (ctx) => { - const { id, userId } = ctx.body; + const { id, userId } = ctx.request.body; assertUuid(id, "id is required"); assertUuid(userId, "userId is required"); @@ -442,7 +449,7 @@ router.post("collections.remove_user", auth(), async (ctx) => { }); router.post("collections.memberships", auth(), pagination(), async (ctx) => { - const { id, query, permission } = ctx.body; + const { id, query, permission } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; @@ -505,7 +512,7 @@ router.post( auth(), rateLimiter(RateLimiterStrategy.TenPerHour), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; const team = await Team.findByPk(user.teamId); @@ -572,7 +579,7 @@ router.post("collections.update", auth(), async (ctx) => { color, sort, sharing, - } = ctx.body; + } = ctx.request.body; if (color) { assertHexColor(color, "Invalid hex value (please use format #FFFFFF)"); @@ -724,7 +731,7 @@ router.post("collections.list", auth(), pagination(), async (ctx) => { }); router.post("collections.delete", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; const { user } = ctx.state; assertUuid(id, "id is required"); @@ -768,8 +775,8 @@ router.post("collections.delete", auth(), async (ctx) => { }); router.post("collections.move", auth(), async (ctx) => { - const id = ctx.body.id; - let index = ctx.body.index; + const id = ctx.request.body.id; + let index = ctx.request.body.index; assertPresent(index, "index is required"); assertIndexCharacters(index); assertUuid(id, "id must be a uuid"); diff --git a/server/routes/api/cron.ts b/server/routes/api/cron.ts index 52df20e3f..c8b7da4ed 100644 --- a/server/routes/api/cron.ts +++ b/server/routes/api/cron.ts @@ -12,10 +12,16 @@ import InviteReminderTask from "@server/queues/tasks/InviteReminderTask"; const router = new Router(); const cronHandler = async (ctx: Context) => { - const { token, limit = 500 } = ctx.body as { token?: string; limit: number }; + const { token, limit = 500 } = (ctx.request.body ?? ctx.request.query) as { + token?: string; + limit: number; + }; + + if (!token || typeof token !== "string") { + throw AuthenticationError("Token is required"); + } if ( - !token || token.length !== env.UTILS_SECRET.length || !crypto.timingSafeEqual( Buffer.from(env.UTILS_SECRET), diff --git a/server/routes/api/developer.ts b/server/routes/api/developer.ts index a0bf673f0..ebd5bfa0c 100644 --- a/server/routes/api/developer.ts +++ b/server/routes/api/developer.ts @@ -20,9 +20,9 @@ function dev() { } router.post("developer.create_test_users", dev(), auth(), async (ctx) => { - const { count = 10 } = ctx.body; + const { count = 10 } = ctx.request.body; const { user } = ctx.state; - const invites = Array(count) + const invites = Array(Math.min(count, 100)) .fill(0) .map(() => { const rando = randomstring.generate(10); diff --git a/server/routes/api/documents.ts b/server/routes/api/documents.ts index ab027e222..e1b3c2732 100644 --- a/server/routes/api/documents.ts +++ b/server/routes/api/documents.ts @@ -51,12 +51,13 @@ import pagination from "./middlewares/pagination"; const router = new Router(); router.post("documents.list", auth(), pagination(), async (ctx) => { - let { sort = "updatedAt" } = ctx.body; - const { template, backlinkDocumentId, parentDocumentId } = ctx.body; + let { sort = "updatedAt" } = ctx.request.body; + const { template, backlinkDocumentId, parentDocumentId } = ctx.request.body; // collection and user are here for backwards compatibility - const collectionId = ctx.body.collectionId || ctx.body.collection; - const createdById = ctx.body.userId || ctx.body.user; - let direction = ctx.body.direction; + const collectionId = + ctx.request.body.collectionId || ctx.request.body.collection; + const createdById = ctx.request.body.userId || ctx.request.body.user; + let direction = ctx.request.body.direction; if (direction !== "ASC") { direction = "DESC"; } @@ -171,10 +172,10 @@ router.post( auth({ member: true }), pagination(), async (ctx) => { - const { sort = "updatedAt" } = ctx.body; + const { sort = "updatedAt" } = ctx.request.body; assertSort(sort, Document); - let direction = ctx.body.direction; + let direction = ctx.request.body.direction; if (direction !== "ASC") { direction = "DESC"; } @@ -220,10 +221,10 @@ router.post( auth({ member: true }), pagination(), async (ctx) => { - const { sort = "deletedAt" } = ctx.body; + const { sort = "deletedAt" } = ctx.request.body; assertSort(sort, Document); - let direction = ctx.body.direction; + let direction = ctx.request.body.direction; if (direction !== "ASC") { direction = "DESC"; } @@ -279,8 +280,8 @@ router.post( ); router.post("documents.viewed", auth(), pagination(), async (ctx) => { - let { direction } = ctx.body; - const { sort = "updatedAt" } = ctx.body; + let { direction } = ctx.request.body; + const { sort = "updatedAt" } = ctx.request.body; assertSort(sort, Document); if (direction !== "ASC") { @@ -332,8 +333,8 @@ router.post("documents.viewed", auth(), pagination(), async (ctx) => { }); router.post("documents.drafts", auth(), pagination(), async (ctx) => { - let { direction } = ctx.body; - const { collectionId, dateFilter, sort = "updatedAt" } = ctx.body; + let { direction } = ctx.request.body; + const { collectionId, dateFilter, sort = "updatedAt" } = ctx.request.body; assertSort(sort, Document); if (direction !== "ASC") { @@ -403,7 +404,7 @@ router.post( optional: true, }), async (ctx) => { - const { id, shareId, apiVersion } = ctx.body; + const { id, shareId, apiVersion } = ctx.request.body; assertPresent(id || shareId, "id or shareId is required"); const { user } = ctx.state; const { document, share, collection } = await documentLoader({ @@ -441,7 +442,7 @@ router.post( optional: true, }), async (ctx) => { - const { id, shareId } = ctx.body; + const { id, shareId } = ctx.request.body; assertPresent(id || shareId, "id or shareId is required"); const { user } = ctx.state; @@ -488,7 +489,7 @@ router.post( ); router.post("documents.restore", auth({ member: true }), async (ctx) => { - const { id, collectionId, revisionId } = ctx.body; + const { id, collectionId, revisionId } = ctx.request.body; assertPresent(id, "id is required"); const { user } = ctx.state; const document = await Document.findByPk(id, { @@ -585,7 +586,7 @@ router.post("documents.restore", auth({ member: true }), async (ctx) => { }); router.post("documents.search_titles", auth(), pagination(), async (ctx) => { - const { query } = ctx.body; + const { query } = ctx.request.body; const { offset, limit } = ctx.state.pagination; const { user } = ctx.state; @@ -651,12 +652,18 @@ router.post( userId, dateFilter, shareId, - } = ctx.body; + } = ctx.request.body; assertNotEmpty(query, "query is required"); const { offset, limit } = ctx.state.pagination; - const snippetMinWords = parseInt(ctx.body.snippetMinWords || 20, 10); - const snippetMaxWords = parseInt(ctx.body.snippetMaxWords || 30, 10); + const snippetMinWords = parseInt( + ctx.request.body.snippetMinWords || 20, + 10 + ); + const snippetMaxWords = parseInt( + ctx.request.body.snippetMaxWords || 30, + 10 + ); // this typing is a bit ugly, would be better to use a type like ContextWithState // but that doesn't adequately handle cases when auth is optional @@ -765,7 +772,7 @@ router.post( ); router.post("documents.templatize", auth({ member: true }), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertPresent(id, "id is required"); const { user } = ctx.state; @@ -821,7 +828,7 @@ router.post("documents.update", auth(), async (ctx) => { lastRevision, templateId, append, - } = ctx.body; + } = ctx.request.body; const editorVersion = ctx.headers["x-editor-version"] as string | undefined; assertPresent(id, "id is required"); if (append) { @@ -872,7 +879,7 @@ router.post("documents.update", auth(), async (ctx) => { }); router.post("documents.move", auth(), async (ctx) => { - const { id, collectionId, parentDocumentId, index } = ctx.body; + const { id, collectionId, parentDocumentId, index } = ctx.request.body; assertUuid(id, "id must be a uuid"); assertUuid(collectionId, "collectionId must be a uuid"); @@ -938,7 +945,7 @@ router.post("documents.move", auth(), async (ctx) => { }); router.post("documents.archive", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertPresent(id, "id is required"); const { user } = ctx.state; @@ -967,7 +974,7 @@ router.post("documents.archive", auth(), async (ctx) => { }); router.post("documents.delete", auth(), async (ctx) => { - const { id, permanent } = ctx.body; + const { id, permanent } = ctx.request.body; assertPresent(id, "id is required"); const { user } = ctx.state; @@ -1028,7 +1035,7 @@ router.post("documents.delete", auth(), async (ctx) => { }); router.post("documents.unpublish", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertPresent(id, "id is required"); const { user } = ctx.state; @@ -1062,7 +1069,7 @@ router.post("documents.unpublish", auth(), async (ctx) => { }); router.post("documents.import", auth(), async (ctx) => { - const { publish, collectionId, parentDocumentId, index } = ctx.body; + const { publish, collectionId, parentDocumentId, index } = ctx.request.body; if (!ctx.is("multipart/form-data")) { throw InvalidRequestError("Request type must be multipart/form-data"); @@ -1160,7 +1167,7 @@ router.post("documents.create", auth(), async (ctx) => { templateId, template, index, - } = ctx.body; + } = ctx.request.body; const editorVersion = ctx.headers["x-editor-version"] as string | undefined; assertUuid(collectionId, "collectionId must be an uuid"); diff --git a/server/routes/api/events.ts b/server/routes/api/events.ts index f9830cc6e..52a3dd53d 100644 --- a/server/routes/api/events.ts +++ b/server/routes/api/events.ts @@ -11,7 +11,7 @@ const router = new Router(); router.post("events.list", auth(), pagination(), async (ctx) => { const { user } = ctx.state; - let { direction } = ctx.body; + let { direction } = ctx.request.body; const { sort = "createdAt", actorId, @@ -19,7 +19,7 @@ router.post("events.list", auth(), pagination(), async (ctx) => { collectionId, name, auditLog = false, - } = ctx.body; + } = ctx.request.body; if (direction !== "ASC") { direction = "DESC"; } diff --git a/server/routes/api/fileOperations.ts b/server/routes/api/fileOperations.ts index e790577c7..a956e69d4 100644 --- a/server/routes/api/fileOperations.ts +++ b/server/routes/api/fileOperations.ts @@ -15,7 +15,7 @@ import pagination from "./middlewares/pagination"; const router = new Router(); router.post("fileOperations.info", auth({ admin: true }), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; const fileOperation = await FileOperation.findByPk(id, { @@ -34,8 +34,8 @@ router.post( auth({ admin: true }), pagination(), async (ctx) => { - let { direction } = ctx.body; - const { sort = "createdAt", type } = ctx.body; + let { direction } = ctx.request.body; + const { sort = "createdAt", type } = ctx.request.body; assertIn(type, Object.values(FileOperationType)); assertSort(sort, FileOperation); @@ -70,7 +70,7 @@ router.post( ); const handleFileOperationsRedirect = async (ctx: ContextWithState) => { - const { id } = ctx.body as { id?: string }; + const { id } = (ctx.request.body ?? ctx.request.query) as { id?: string }; assertUuid(id, "id is required"); const { user } = ctx.state; @@ -99,7 +99,7 @@ router.post( ); router.post("fileOperations.delete", auth({ admin: true }), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; diff --git a/server/routes/api/groups.ts b/server/routes/api/groups.ts index f90bf5890..1fdbdc6fc 100644 --- a/server/routes/api/groups.ts +++ b/server/routes/api/groups.ts @@ -16,8 +16,8 @@ import pagination from "./middlewares/pagination"; const router = new Router(); router.post("groups.list", auth(), pagination(), async (ctx) => { - let { direction } = ctx.body; - const { sort = "updatedAt" } = ctx.body; + let { direction } = ctx.request.body; + const { sort = "updatedAt" } = ctx.request.body; if (direction !== "ASC") { direction = "DESC"; } @@ -53,7 +53,7 @@ router.post("groups.list", auth(), pagination(), async (ctx) => { }); router.post("groups.info", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; @@ -67,7 +67,7 @@ router.post("groups.info", auth(), async (ctx) => { }); router.post("groups.create", auth(), async (ctx) => { - const { name } = ctx.body; + const { name } = ctx.request.body; assertPresent(name, "name is required"); const { user } = ctx.state; @@ -99,7 +99,7 @@ router.post("groups.create", auth(), async (ctx) => { }); router.post("groups.update", auth(), async (ctx) => { - const { id, name } = ctx.body; + const { id, name } = ctx.request.body; assertPresent(name, "name is required"); assertUuid(id, "id is required"); @@ -130,7 +130,7 @@ router.post("groups.update", auth(), async (ctx) => { }); router.post("groups.delete", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; @@ -155,7 +155,7 @@ router.post("groups.delete", auth(), async (ctx) => { }); router.post("groups.memberships", auth(), pagination(), async (ctx) => { - const { id, query } = ctx.body; + const { id, query } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; @@ -200,7 +200,7 @@ router.post("groups.memberships", auth(), pagination(), async (ctx) => { }); router.post("groups.add_user", auth(), async (ctx) => { - const { id, userId } = ctx.body; + const { id, userId } = ctx.request.body; assertUuid(id, "id is required"); assertUuid(userId, "userId is required"); @@ -260,7 +260,7 @@ router.post("groups.add_user", auth(), async (ctx) => { }); router.post("groups.remove_user", auth(), async (ctx) => { - const { id, userId } = ctx.body; + const { id, userId } = ctx.request.body; assertUuid(id, "id is required"); assertUuid(userId, "userId is required"); diff --git a/server/routes/api/hooks.test.ts b/server/routes/api/hooks.test.ts index 5f6fe1609..ab8632fe4 100644 --- a/server/routes/api/hooks.test.ts +++ b/server/routes/api/hooks.test.ts @@ -4,7 +4,7 @@ import { buildDocument, buildIntegration } from "@server/test/factories"; import { seed, getTestServer } from "@server/test/support"; import * as Slack from "@server/utils/slack"; -jest.mock("../../utils/slack", () => ({ +jest.mock("@server/utils/slack", () => ({ post: jest.fn(), })); diff --git a/server/routes/api/hooks.ts b/server/routes/api/hooks.ts index 0de8d780b..e1854a68e 100644 --- a/server/routes/api/hooks.ts +++ b/server/routes/api/hooks.ts @@ -40,9 +40,9 @@ function verifySlackToken(token: string) { // triggered by a user posting a getoutline.com link in Slack router.post("hooks.unfurl", async (ctx) => { - const { challenge, token, event } = ctx.body; + const { challenge, token, event } = ctx.request.body; if (challenge) { - return (ctx.body = ctx.body.challenge); + return (ctx.body = ctx.request.body.challenge); } assertPresent(token, "token is required"); @@ -95,11 +95,15 @@ router.post("hooks.unfurl", async (ctx) => { ts: event.message_ts, unfurls, }); + + ctx.body = { + success: true, + }; }); // triggered by interactions with actions, dialogs, message buttons in Slack router.post("hooks.interactive", async (ctx) => { - const { payload } = ctx.body; + const { payload } = ctx.request.body; assertPresent(payload, "payload is required"); const data = JSON.parse(payload); @@ -137,7 +141,7 @@ router.post("hooks.interactive", async (ctx) => { // triggered by the /outline command in Slack router.post("hooks.slack", async (ctx) => { - const { token, team_id, user_id, text = "" } = ctx.body; + const { token, team_id, user_id, text = "" } = ctx.request.body; assertPresent(token, "token is required"); assertPresent(team_id, "team_id is required"); assertPresent(user_id, "user_id is required"); diff --git a/server/routes/api/index.ts b/server/routes/api/index.ts index 7b1a890e5..be3425435 100644 --- a/server/routes/api/index.ts +++ b/server/routes/api/index.ts @@ -5,7 +5,6 @@ import userAgent, { UserAgentContext } from "koa-useragent"; import env from "@server/env"; import { NotFoundError } from "@server/errors"; import errorHandling from "@server/middlewares/errorHandling"; -import methodOverride from "@server/middlewares/methodOverride"; import { defaultRateLimiter } from "@server/middlewares/rateLimiter"; import { AuthenticatedState } from "@server/types"; import apiKeys from "./apiKeys"; @@ -52,7 +51,6 @@ api.use( }) ); api.use(userAgent); -api.use(methodOverride()); api.use(apiWrapper()); api.use(editor()); diff --git a/server/routes/api/integrations.ts b/server/routes/api/integrations.ts index 69e6d8993..a3392b48d 100644 --- a/server/routes/api/integrations.ts +++ b/server/routes/api/integrations.ts @@ -20,8 +20,8 @@ import pagination from "./middlewares/pagination"; const router = new Router(); router.post("integrations.list", auth(), pagination(), async (ctx) => { - let { direction } = ctx.body; - const { sort = "updatedAt" } = ctx.body; + let { direction } = ctx.request.body; + const { sort = "updatedAt" } = ctx.request.body; if (direction !== "ASC") { direction = "DESC"; } @@ -44,7 +44,7 @@ router.post("integrations.list", auth(), pagination(), async (ctx) => { }); router.post("integrations.create", auth({ admin: true }), async (ctx) => { - const { type, service, settings } = ctx.body; + const { type, service, settings } = ctx.request.body; assertIn(type, Object.values(IntegrationType)); @@ -71,7 +71,7 @@ router.post("integrations.create", auth({ admin: true }), async (ctx) => { }); router.post("integrations.update", auth({ admin: true }), async (ctx) => { - const { id, events = [], settings } = ctx.body; + const { id, events = [], settings } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; @@ -100,7 +100,7 @@ router.post("integrations.update", auth({ admin: true }), async (ctx) => { }); router.post("integrations.delete", auth({ admin: true }), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; diff --git a/server/routes/api/middlewares/apiWrapper.ts b/server/routes/api/middlewares/apiWrapper.ts index f2cd564c6..f717ca1eb 100644 --- a/server/routes/api/middlewares/apiWrapper.ts +++ b/server/routes/api/middlewares/apiWrapper.ts @@ -7,11 +7,10 @@ export default function apiWrapper() { const ok = ctx.status < 400; if ( - typeof ctx.body !== "string" && + typeof ctx.body === "object" && !(ctx.body instanceof stream.Readable) ) { ctx.body = { - // @ts-expect-error ts-migrate(2698) FIXME: Spread types may only be created from object types... Remove this comment to see the full error message ...ctx.body, status: ctx.status, ok, diff --git a/server/routes/api/notificationSettings.ts b/server/routes/api/notificationSettings.ts index 75f481a44..9f27dc077 100644 --- a/server/routes/api/notificationSettings.ts +++ b/server/routes/api/notificationSettings.ts @@ -10,7 +10,7 @@ import { assertPresent, assertUuid } from "@server/validation"; const router = new Router(); router.post("notificationSettings.create", auth(), async (ctx) => { - const { event } = ctx.body; + const { event } = ctx.request.body; assertPresent(event, "event is required"); const { user } = ctx.state; @@ -42,7 +42,7 @@ router.post("notificationSettings.list", auth(), async (ctx) => { }); router.post("notificationSettings.delete", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; @@ -57,7 +57,10 @@ router.post("notificationSettings.delete", auth(), async (ctx) => { }); const handleUnsubscribe = async (ctx: ContextWithState) => { - const { id, token } = ctx.body as { id?: string; token?: string }; + const { id, token } = (ctx.request.body ?? ctx.request.query) as { + id?: string; + token?: string; + }; assertUuid(id, "id is required"); assertPresent(token, "token is required"); diff --git a/server/routes/api/pins.ts b/server/routes/api/pins.ts index fe53d7c10..d19e1d58d 100644 --- a/server/routes/api/pins.ts +++ b/server/routes/api/pins.ts @@ -17,8 +17,8 @@ import pagination from "./middlewares/pagination"; const router = new Router(); router.post("pins.create", auth(), async (ctx) => { - const { documentId, collectionId } = ctx.body; - const { index } = ctx.body; + const { documentId, collectionId } = ctx.request.body; + const { index } = ctx.request.body; assertUuid(documentId, "documentId is required"); const { user } = ctx.state; @@ -56,7 +56,7 @@ router.post("pins.create", auth(), async (ctx) => { }); router.post("pins.list", auth(), pagination(), async (ctx) => { - const { collectionId } = ctx.body; + const { collectionId } = ctx.request.body; const { user } = ctx.state; const [pins, collectionIds] = await Promise.all([ @@ -99,7 +99,7 @@ router.post("pins.list", auth(), pagination(), async (ctx) => { }); router.post("pins.update", auth(), async (ctx) => { - const { id, index } = ctx.body; + const { id, index } = ctx.request.body; assertUuid(id, "id is required"); assertIndexCharacters(index); @@ -131,7 +131,7 @@ router.post("pins.update", auth(), async (ctx) => { }); router.post("pins.delete", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; diff --git a/server/routes/api/revisions.ts b/server/routes/api/revisions.ts index c7c681941..86dc42283 100644 --- a/server/routes/api/revisions.ts +++ b/server/routes/api/revisions.ts @@ -13,7 +13,7 @@ import pagination from "./middlewares/pagination"; const router = new Router(); router.post("revisions.info", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; const revision = await Revision.findByPk(id, { @@ -39,7 +39,7 @@ router.post("revisions.info", auth(), async (ctx) => { }); router.post("revisions.diff", auth(), async (ctx) => { - const { id, compareToId } = ctx.body; + const { id, compareToId } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; @@ -93,8 +93,8 @@ router.post("revisions.diff", auth(), async (ctx) => { }); router.post("revisions.list", auth(), pagination(), async (ctx) => { - let { direction } = ctx.body; - const { documentId, sort = "updatedAt" } = ctx.body; + let { direction } = ctx.request.body; + const { documentId, sort = "updatedAt" } = ctx.request.body; if (direction !== "ASC") { direction = "DESC"; } diff --git a/server/routes/api/searches.ts b/server/routes/api/searches.ts index 18194c0b4..f9a3578af 100644 --- a/server/routes/api/searches.ts +++ b/server/routes/api/searches.ts @@ -26,7 +26,7 @@ router.post("searches.list", auth(), pagination(), async (ctx) => { }); router.post("searches.delete", auth(), async (ctx) => { - const { id, query } = ctx.body; + const { id, query } = ctx.request.body; assertPresent(id || query, "id or query is required"); if (id) { assertUuid(id, "id is must be a uuid"); diff --git a/server/routes/api/shares.ts b/server/routes/api/shares.ts index c77f19be4..96240fd84 100644 --- a/server/routes/api/shares.ts +++ b/server/routes/api/shares.ts @@ -11,7 +11,7 @@ import pagination from "./middlewares/pagination"; const router = new Router(); router.post("shares.info", auth(), async (ctx) => { - const { id, documentId } = ctx.body; + const { id, documentId } = ctx.request.body; assertPresent(id || documentId, "id or documentId is required"); if (id) { assertUuid(id, "id is must be a uuid"); @@ -92,8 +92,8 @@ router.post("shares.info", auth(), async (ctx) => { }); router.post("shares.list", auth(), pagination(), async (ctx) => { - let { direction } = ctx.body; - const { sort = "updatedAt" } = ctx.body; + let { direction } = ctx.request.body; + const { sort = "updatedAt" } = ctx.request.body; if (direction !== "ASC") { direction = "DESC"; } @@ -162,7 +162,7 @@ router.post("shares.list", auth(), pagination(), async (ctx) => { }); router.post("shares.update", auth(), async (ctx) => { - const { id, includeChildDocuments, published } = ctx.body; + const { id, includeChildDocuments, published } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; @@ -211,7 +211,7 @@ router.post("shares.update", auth(), async (ctx) => { }); router.post("shares.create", auth(), async (ctx) => { - const { documentId } = ctx.body; + const { documentId } = ctx.request.body; assertPresent(documentId, "documentId is required"); const { user } = ctx.state; @@ -263,7 +263,7 @@ router.post("shares.create", auth(), async (ctx) => { }); router.post("shares.revoke", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; diff --git a/server/routes/api/stars.ts b/server/routes/api/stars.ts index 8e0a0f34f..e3361cd10 100644 --- a/server/routes/api/stars.ts +++ b/server/routes/api/stars.ts @@ -19,8 +19,8 @@ import pagination from "./middlewares/pagination"; const router = new Router(); router.post("stars.create", auth(), async (ctx) => { - const { documentId, collectionId } = ctx.body; - const { index } = ctx.body; + const { documentId, collectionId } = ctx.request.body; + const { index } = ctx.request.body; const { user } = ctx.state; assertUuid( @@ -116,7 +116,7 @@ router.post("stars.list", auth(), pagination(), async (ctx) => { }); router.post("stars.update", auth(), async (ctx) => { - const { id, index } = ctx.body; + const { id, index } = ctx.request.body; assertUuid(id, "id is required"); assertIndexCharacters(index); @@ -139,7 +139,7 @@ router.post("stars.update", auth(), async (ctx) => { }); router.post("stars.delete", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; diff --git a/server/routes/api/subscriptions.ts b/server/routes/api/subscriptions.ts index 54990bf9d..9706def00 100644 --- a/server/routes/api/subscriptions.ts +++ b/server/routes/api/subscriptions.ts @@ -13,7 +13,7 @@ const router = new Router(); router.post("subscriptions.list", auth(), pagination(), async (ctx) => { const { user } = ctx.state; - const { documentId, event } = ctx.body; + const { documentId, event } = ctx.request.body; assertUuid(documentId, "documentId is required"); @@ -46,7 +46,7 @@ router.post("subscriptions.list", auth(), pagination(), async (ctx) => { router.post("subscriptions.info", auth(), async (ctx) => { const { user } = ctx.state; - const { documentId, event } = ctx.body; + const { documentId, event } = ctx.request.body; assertUuid(documentId, "documentId is required"); @@ -77,7 +77,7 @@ router.post("subscriptions.info", auth(), async (ctx) => { router.post("subscriptions.create", auth(), async (ctx) => { const { user } = ctx.state; - const { documentId, event } = ctx.body; + const { documentId, event } = ctx.request.body; assertUuid(documentId, "documentId is required"); @@ -111,7 +111,7 @@ router.post("subscriptions.create", auth(), async (ctx) => { router.post("subscriptions.delete", auth(), async (ctx) => { const { user } = ctx.state; - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); diff --git a/server/routes/api/team.test.ts b/server/routes/api/team.test.ts index 79926c848..7cbceb3fd 100644 --- a/server/routes/api/team.test.ts +++ b/server/routes/api/team.test.ts @@ -23,7 +23,7 @@ describe("teams.create", () => { }); it("requires a cloud hosted deployment", async () => { - env.DEPLOYMENT = "self-hosted"; + env.DEPLOYMENT = ""; const team = await buildTeam(); const user = await buildAdmin({ teamId: team.id }); const res = await server.post("/api/teams.create", { diff --git a/server/routes/api/team.ts b/server/routes/api/team.ts index 771abb58e..7985a58fc 100644 --- a/server/routes/api/team.ts +++ b/server/routes/api/team.ts @@ -32,7 +32,7 @@ router.post( inviteRequired, allowedDomains, preferences, - } = ctx.body; + } = ctx.request.body; const { user } = ctx.state; const team = await Team.findByPk(user.teamId, { @@ -78,7 +78,7 @@ router.post( rateLimiter(RateLimiterStrategy.FivePerHour), async (ctx) => { const { user } = ctx.state; - const { name } = ctx.body; + const { name } = ctx.request.body; const existingTeam = await Team.scope( "withAuthenticationProviders" diff --git a/server/routes/api/users.ts b/server/routes/api/users.ts index 2f863a20a..c5171c7bf 100644 --- a/server/routes/api/users.ts +++ b/server/routes/api/users.ts @@ -37,8 +37,8 @@ const router = new Router(); const emailEnabled = !!(env.SMTP_HOST || env.ENVIRONMENT === "development"); router.post("users.list", auth(), pagination(), async (ctx) => { - let { direction } = ctx.body; - const { sort = "createdAt", query, filter, ids } = ctx.body; + let { direction } = ctx.request.body; + const { sort = "createdAt", query, filter, ids } = ctx.request.body; if (direction !== "ASC") { direction = "DESC"; } @@ -162,7 +162,7 @@ router.post("users.count", auth(), async (ctx) => { }); router.post("users.info", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; const actor = ctx.state.user; const user = id ? await User.findByPk(id) : actor; authorize(actor, "read", user); @@ -178,7 +178,7 @@ router.post("users.info", auth(), async (ctx) => { router.post("users.update", auth(), async (ctx) => { const { user } = ctx.state; - const { name, avatarUrl, language, preferences } = ctx.body; + const { name, avatarUrl, language, preferences } = ctx.request.body; if (name) { user.name = name; } @@ -216,7 +216,7 @@ router.post("users.update", auth(), async (ctx) => { // Admin specific router.post("users.promote", auth(), async (ctx) => { - const userId = ctx.body.id; + const userId = ctx.request.body.id; const teamId = ctx.state.user.teamId; const actor = ctx.state.user; assertPresent(userId, "id is required"); @@ -245,8 +245,8 @@ router.post("users.promote", auth(), async (ctx) => { }); router.post("users.demote", auth(), async (ctx) => { - const userId = ctx.body.id; - let { to } = ctx.body; + const userId = ctx.request.body.id; + let { to } = ctx.request.body; const actor = ctx.state.user as User; assertPresent(userId, "id is required"); @@ -274,7 +274,7 @@ router.post("users.demote", auth(), async (ctx) => { }); router.post("users.suspend", auth(), async (ctx) => { - const userId = ctx.body.id; + const userId = ctx.request.body.id; const actor = ctx.state.user; assertPresent(userId, "id is required"); const user = await User.findByPk(userId, { @@ -298,7 +298,7 @@ router.post("users.suspend", auth(), async (ctx) => { }); router.post("users.activate", auth(), async (ctx) => { - const userId = ctx.body.id; + const userId = ctx.request.body.id; const actor = ctx.state.user; assertPresent(userId, "id is required"); const user = await User.findByPk(userId, { @@ -326,7 +326,7 @@ router.post( auth(), rateLimiter(RateLimiterStrategy.TenPerHour), async (ctx) => { - const { invites } = ctx.body; + const { invites } = ctx.request.body; assertArray(invites, "invites must be an array"); const { user } = ctx.state; const team = await Team.findByPk(user.teamId); @@ -348,7 +348,7 @@ router.post( ); router.post("users.resendInvite", auth(), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; const actor = ctx.state.user; await sequelize.transaction(async (transaction) => { @@ -415,7 +415,7 @@ router.post( auth(), rateLimiter(RateLimiterStrategy.TenPerHour), async (ctx) => { - const { id, code = "" } = ctx.body; + const { id, code = "" } = ctx.request.body; let user: User; if (id) { diff --git a/server/routes/api/views.ts b/server/routes/api/views.ts index c0c55afcf..5f2e3bbe6 100644 --- a/server/routes/api/views.ts +++ b/server/routes/api/views.ts @@ -10,7 +10,7 @@ import { assertUuid } from "@server/validation"; const router = new Router(); router.post("views.list", auth(), async (ctx) => { - const { documentId, includeSuspended = false } = ctx.body; + const { documentId, includeSuspended = false } = ctx.request.body; assertUuid(documentId, "documentId is required"); const { user } = ctx.state; @@ -30,7 +30,7 @@ router.post( auth(), rateLimiter(RateLimiterStrategy.OneThousandPerHour), async (ctx) => { - const { documentId } = ctx.body; + const { documentId } = ctx.request.body; assertUuid(documentId, "documentId is required"); const { user } = ctx.state; diff --git a/server/routes/api/webhookSubscriptions.ts b/server/routes/api/webhookSubscriptions.ts index 5cf7883d9..5d05d93ec 100644 --- a/server/routes/api/webhookSubscriptions.ts +++ b/server/routes/api/webhookSubscriptions.ts @@ -84,7 +84,7 @@ router.post( "webhookSubscriptions.delete", auth({ admin: true }), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; const webhookSubscription = await WebhookSubscription.findByPk(id); @@ -113,7 +113,7 @@ router.post( "webhookSubscriptions.update", auth({ admin: true }), async (ctx) => { - const { id } = ctx.body; + const { id } = ctx.request.body; assertUuid(id, "id is required"); const { user } = ctx.state; diff --git a/server/routes/auth/providers/email.ts b/server/routes/auth/providers/email.ts index a614163c8..53e8a4421 100644 --- a/server/routes/auth/providers/email.ts +++ b/server/routes/auth/providers/email.ts @@ -8,7 +8,6 @@ import WelcomeEmail from "@server/emails/templates/WelcomeEmail"; import env from "@server/env"; import { AuthorizationError } from "@server/errors"; import errorHandling from "@server/middlewares/errorHandling"; -import methodOverride from "@server/middlewares/methodOverride"; import { rateLimiter } from "@server/middlewares/rateLimiter"; import { User, Team } from "@server/models"; import { signIn } from "@server/utils/authentication"; @@ -22,14 +21,12 @@ export const config = { enabled: true, }; -router.use(methodOverride()); - router.post( "email", errorHandling(), rateLimiter(RateLimiterStrategy.TenPerHour), async (ctx) => { - const { email } = ctx.body; + const { email } = ctx.request.body; assertEmail(email, "email is required"); const domain = parseDomain(ctx.request.hostname);