DocumentController.mjs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import ChatApiHandler from '../Chat/ChatApiHandler.mjs'
  2. import ProjectGetter from '../Project/ProjectGetter.mjs'
  3. import ProjectLocator from '../Project/ProjectLocator.mjs'
  4. import ProjectEntityHandler from '../Project/ProjectEntityHandler.mjs'
  5. import ProjectEntityUpdateHandler from '../Project/ProjectEntityUpdateHandler.mjs'
  6. import logger from '@overleaf/logger'
  7. import _ from 'lodash'
  8. import { plainTextResponse } from '../../infrastructure/Response.mjs'
  9. import { expressify } from '@overleaf/promise-utils'
  10. import Modules from '../../infrastructure/Modules.mjs'
  11. async function getDocument(req, res) {
  12. const { Project_id: projectId, doc_id: docId } = req.params
  13. const plain = req.query.plain === 'true'
  14. const peek = req.query.peek === 'true'
  15. const project = await ProjectGetter.promises.getProject(projectId, {
  16. rootFolder: true,
  17. overleaf: true,
  18. })
  19. if (!project) {
  20. return res.sendStatus(404)
  21. }
  22. const { path } = await ProjectLocator.promises.findElement({
  23. project,
  24. element_id: docId,
  25. type: 'doc',
  26. })
  27. const { lines, version, ranges } = await ProjectEntityHandler.promises.getDoc(
  28. projectId,
  29. docId,
  30. { peek }
  31. )
  32. const resolvedCommentIdsInProject =
  33. await ChatApiHandler.promises.getResolvedThreadIds(projectId)
  34. const commentIdsInDoc = new Set(
  35. ranges?.comments?.map(comment => comment.id) ?? []
  36. )
  37. const resolvedCommentIds = resolvedCommentIdsInProject.filter(commentId =>
  38. commentIdsInDoc.has(commentId)
  39. )
  40. if (plain) {
  41. plainTextResponse(res, lines.join('\n'))
  42. } else {
  43. const projectHistoryId = _.get(project, 'overleaf.history.id')
  44. const historyRangesSupport = _.get(
  45. project,
  46. 'overleaf.history.rangesSupportEnabled',
  47. false
  48. )
  49. const otMigrationStage = _.get(
  50. project,
  51. 'overleaf.history.otMigrationStage',
  52. 0
  53. )
  54. // all projects are now migrated to Full Project History, keeping the field
  55. // for API compatibility
  56. const projectHistoryType = 'project-history'
  57. res.json({
  58. lines,
  59. version,
  60. ranges,
  61. pathname: path.fileSystem,
  62. projectHistoryId,
  63. projectHistoryType,
  64. historyRangesSupport,
  65. otMigrationStage,
  66. resolvedCommentIds,
  67. })
  68. }
  69. }
  70. async function setDocument(req, res) {
  71. const { Project_id: projectId, doc_id: docId } = req.params
  72. const { lines, version, ranges, lastUpdatedAt, lastUpdatedBy } = req.body
  73. const result = await ProjectEntityUpdateHandler.promises.updateDocLines(
  74. projectId,
  75. docId,
  76. lines,
  77. version,
  78. ranges,
  79. lastUpdatedAt,
  80. lastUpdatedBy
  81. )
  82. logger.debug(
  83. { docId, projectId },
  84. 'finished receiving set document request from api (docupdater)'
  85. )
  86. await Modules.promises.hooks.fire('docModified', projectId, docId, ranges)
  87. res.json(result)
  88. }
  89. export default {
  90. getDocument: expressify(getDocument),
  91. setDocument: expressify(setDocument),
  92. }