diff --git a/server/routes/api/authenticationProviders/authenticationProviders.ts b/server/routes/api/authenticationProviders/authenticationProviders.ts index 01c754e07..79b873485 100644 --- a/server/routes/api/authenticationProviders/authenticationProviders.ts +++ b/server/routes/api/authenticationProviders/authenticationProviders.ts @@ -1,6 +1,6 @@ import Router from "koa-router"; -import { sequelize } from "@server/database/sequelize"; import auth from "@server/middlewares/authentication"; +import { transaction } from "@server/middlewares/transaction"; import validate from "@server/middlewares/validate"; import { AuthenticationProvider, Event } from "@server/models"; import AuthenticationHelper from "@server/models/helpers/AuthenticationHelper"; @@ -36,45 +36,38 @@ router.post( "authenticationProviders.update", auth({ admin: true }), validate(T.AuthenticationProvidersUpdateSchema), + transaction(), async (ctx: APIContext) => { + const { transaction } = ctx.state; const { id, isEnabled } = ctx.input.body; const { user } = ctx.state.auth; - const authenticationProvider = await sequelize.transaction( - async (transaction) => { - const authenticationProvider = await AuthenticationProvider.findByPk( - id, - { - transaction, - lock: transaction.LOCK.UPDATE, - } - ); + const authenticationProvider = await AuthenticationProvider.findByPk(id, { + transaction, + lock: transaction.LOCK.UPDATE, + }); - authorize(user, "update", authenticationProvider); - const enabled = !!isEnabled; + authorize(user, "update", authenticationProvider); + const enabled = !!isEnabled; - if (enabled) { - await authenticationProvider.enable({ transaction }); - } else { - await authenticationProvider.disable({ transaction }); - } + if (enabled) { + await authenticationProvider.enable({ transaction }); + } else { + await authenticationProvider.disable({ transaction }); + } - await Event.create( - { - name: "authenticationProviders.update", - data: { - enabled, - }, - modelId: id, - teamId: user.teamId, - actorId: user.id, - ip: ctx.request.ip, - }, - { transaction } - ); - - return authenticationProvider; - } + await Event.create( + { + name: "authenticationProviders.update", + data: { + enabled, + }, + modelId: id, + teamId: user.teamId, + actorId: user.id, + ip: ctx.request.ip, + }, + { transaction } ); ctx.body = { diff --git a/server/routes/api/documents/documents.ts b/server/routes/api/documents/documents.ts index dc6b42f71..25f152e84 100644 --- a/server/routes/api/documents/documents.ts +++ b/server/routes/api/documents/documents.ts @@ -12,7 +12,6 @@ import documentLoader from "@server/commands/documentLoader"; 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, @@ -24,6 +23,7 @@ import { import Logger from "@server/logging/Logger"; import auth from "@server/middlewares/authentication"; import { rateLimiter } from "@server/middlewares/rateLimiter"; +import { transaction } from "@server/middlewares/transaction"; import validate from "@server/middlewares/validate"; import { Backlink, @@ -891,7 +891,9 @@ router.post( "documents.update", auth(), validate(T.DocumentsUpdateSchema), + transaction(), async (ctx: APIContext) => { + const { transaction } = ctx.state; const { id, apiVersion, insightsEnabled, publish, collectionId, ...input } = ctx.input.body; const editorVersion = ctx.headers["x-editor-version"] as string | undefined; @@ -922,28 +924,24 @@ router.post( authorize(user, "createDocument", collection); } - collection = await sequelize.transaction(async (transaction) => { - await documentUpdater({ - document, - user, - ...input, - publish, - collectionId, - insightsEnabled, - editorVersion, - transaction, - ip: ctx.request.ip, - }); - - if (!document.collectionId) { - return null; - } - - return await Collection.scope({ - method: ["withMembership", user.id], - }).findByPk(document.collectionId, { transaction }); + await documentUpdater({ + document, + user, + ...input, + publish, + collectionId, + insightsEnabled, + editorVersion, + transaction, + ip: ctx.request.ip, }); + collection = document.collectionId + ? await Collection.scope({ + method: ["withMembership", user.id], + }).findByPk(document.collectionId, { transaction }) + : null; + document.updatedBy = user; document.collection = collection; @@ -966,7 +964,9 @@ router.post( "documents.move", auth(), validate(T.DocumentsMoveSchema), + transaction(), async (ctx: APIContext) => { + const { transaction } = ctx.state; const { id, collectionId, parentDocumentId, index } = ctx.input.body; const { user } = ctx.state.auth; const document = await Document.findByPk(id, { @@ -990,18 +990,15 @@ router.post( } } - const { documents, collections, collectionChanged } = - await sequelize.transaction(async (transaction) => - documentMover({ - user, - document, - collectionId, - parentDocumentId, - index, - ip: ctx.request.ip, - transaction, - }) - ); + const { documents, collections, collectionChanged } = await documentMover({ + user, + document, + collectionId, + parentDocumentId, + index, + ip: ctx.request.ip, + transaction, + }); ctx.body = { data: { @@ -1167,6 +1164,7 @@ router.post( "documents.import", auth(), validate(T.DocumentsImportSchema), + transaction(), async (ctx: APIContext) => { if (!ctx.is("multipart/form-data")) { throw InvalidRequestError("Request type must be multipart/form-data"); @@ -1187,6 +1185,7 @@ router.post( ); } + const { transaction } = ctx.state; const { user } = ctx.state.auth; const collection = await Collection.scope({ @@ -1213,28 +1212,26 @@ router.post( } const content = await fs.readFile(file.filepath); - const document = await sequelize.transaction(async (transaction) => { - const { text, state, title } = await documentImporter({ - user, - fileName: file.originalFilename ?? file.newFilename, - mimeType: file.mimetype ?? "", - content, - ip: ctx.request.ip, - transaction, - }); + const { text, state, title } = await documentImporter({ + user, + fileName: file.originalFilename ?? file.newFilename, + mimeType: file.mimetype ?? "", + content, + ip: ctx.request.ip, + transaction, + }); - return documentCreator({ - source: "import", - title, - text, - state, - publish, - collectionId, - parentDocumentId, - user, - ip: ctx.request.ip, - transaction, - }); + const document = await documentCreator({ + source: "import", + title, + text, + state, + publish, + collectionId, + parentDocumentId, + user, + ip: ctx.request.ip, + transaction, }); document.collection = collection; @@ -1250,6 +1247,7 @@ router.post( "documents.create", auth(), validate(T.DocumentsCreateSchema), + transaction(), async (ctx: APIContext) => { const { title = "", @@ -1263,6 +1261,7 @@ router.post( } = ctx.input.body; const editorVersion = ctx.headers["x-editor-version"] as string | undefined; + const { transaction } = ctx.state; const { user } = ctx.state.auth; let collection; @@ -1302,22 +1301,20 @@ router.post( authorize(user, "read", templateDocument); } - const document = await sequelize.transaction(async (transaction) => - documentCreator({ - title, - text, - publish, - collectionId, - parentDocumentId, - templateDocument, - template, - fullWidth, - user, - editorVersion, - ip: ctx.request.ip, - transaction, - }) - ); + const document = await documentCreator({ + title, + text, + publish, + collectionId, + parentDocumentId, + templateDocument, + template, + fullWidth, + user, + editorVersion, + ip: ctx.request.ip, + transaction, + }); document.collection = collection; diff --git a/server/routes/api/stars/stars.ts b/server/routes/api/stars/stars.ts index af5a6e782..b2bc6b734 100644 --- a/server/routes/api/stars/stars.ts +++ b/server/routes/api/stars/stars.ts @@ -3,8 +3,8 @@ import { Sequelize } from "sequelize"; import starCreator from "@server/commands/starCreator"; import starDestroyer from "@server/commands/starDestroyer"; import starUpdater from "@server/commands/starUpdater"; -import { sequelize } from "@server/database/sequelize"; import auth from "@server/middlewares/authentication"; +import { transaction } from "@server/middlewares/transaction"; import validate from "@server/middlewares/validate"; import { Document, Star, Collection } from "@server/models"; import { authorize } from "@server/policies"; @@ -24,7 +24,9 @@ router.post( "stars.create", auth(), validate(T.StarsCreateSchema), + transaction(), async (ctx: APIContext) => { + const { transaction } = ctx.state; const { documentId, collectionId, index } = ctx.input.body; const { user } = ctx.state.auth; @@ -42,16 +44,15 @@ router.post( authorize(user, "star", collection); } - const star = await sequelize.transaction(async (transaction) => - starCreator({ - user, - documentId, - collectionId, - ip: ctx.request.ip, - index, - transaction, - }) - ); + const star = await starCreator({ + user, + documentId, + collectionId, + ip: ctx.request.ip, + index, + transaction, + }); + ctx.body = { data: presentStar(star), policies: presentPolicies(user, [star]), diff --git a/server/routes/api/teams/teams.ts b/server/routes/api/teams/teams.ts index 0fe6cfd1f..0fd94da2f 100644 --- a/server/routes/api/teams/teams.ts +++ b/server/routes/api/teams/teams.ts @@ -2,7 +2,6 @@ import invariant from "invariant"; import Router from "koa-router"; import teamCreator from "@server/commands/teamCreator"; import teamUpdater from "@server/commands/teamUpdater"; -import { sequelize } from "@server/database/sequelize"; import auth from "@server/middlewares/authentication"; import { rateLimiter } from "@server/middlewares/rateLimiter"; import { transaction } from "@server/middlewares/transaction"; @@ -49,7 +48,9 @@ router.post( "teams.create", rateLimiter(RateLimiterStrategy.FivePerHour), auth(), + transaction(), async (ctx: APIContext) => { + const { transaction } = ctx.state; const { user } = ctx.state.auth; const { name } = ctx.request.body; @@ -73,42 +74,38 @@ router.post( "Team must have at least one authentication provider" ); - const [team, newUser] = await sequelize.transaction(async (transaction) => { - const team = await teamCreator({ - name, - subdomain: name, - authenticationProviders, - ip: ctx.ip, - transaction, - }); - - const newUser = await User.create( - { - teamId: team.id, - name: user.name, - email: user.email, - isAdmin: true, - }, - { transaction } - ); - - await Event.create( - { - name: "users.create", - actorId: user.id, - userId: newUser.id, - teamId: newUser.teamId, - data: { - name: newUser.name, - }, - ip: ctx.ip, - }, - { transaction } - ); - - return [team, newUser]; + const team = await teamCreator({ + name, + subdomain: name, + authenticationProviders, + ip: ctx.ip, + transaction, }); + const newUser = await User.create( + { + teamId: team.id, + name: user.name, + email: user.email, + isAdmin: true, + }, + { transaction } + ); + + await Event.create( + { + name: "users.create", + actorId: user.id, + userId: newUser.id, + teamId: newUser.teamId, + data: { + name: newUser.name, + }, + ip: ctx.ip, + }, + { transaction } + ); + ctx.body = { success: true, data: {