mongodb.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. const mongodb = require('mongodb-legacy')
  2. const OError = require('@overleaf/o-error')
  3. const Settings = require('@overleaf/settings')
  4. const Mongoose = require('./Mongoose')
  5. const { addConnectionDrainer } = require('./GracefulShutdown')
  6. // Ensure Mongoose is using the same mongodb instance as the mongodb module,
  7. // otherwise we will get multiple versions of the ObjectId class. Mongoose
  8. // patches ObjectId, so loading multiple versions of the mongodb module can
  9. // cause problems with ObjectId comparisons.
  10. if (Mongoose.mongo.ObjectId !== mongodb.ObjectId) {
  11. throw new OError(
  12. 'FATAL ERROR: Mongoose is using a different mongodb instance'
  13. )
  14. }
  15. const { ObjectId, ReadPreference } = mongodb
  16. if (
  17. typeof global.beforeEach === 'function' &&
  18. process.argv.join(' ').match(/unit/)
  19. ) {
  20. throw new Error(
  21. 'It looks like unit tests are running, but you are connecting to Mongo. Missing a stub?'
  22. )
  23. }
  24. const READ_PREFERENCE_PRIMARY = ReadPreference.primary.mode
  25. const READ_PREFERENCE_SECONDARY = Settings.mongo.hasSecondaries
  26. ? ReadPreference.secondary.mode
  27. : ReadPreference.secondaryPreferred.mode
  28. let setupDbPromise
  29. async function waitForDb() {
  30. if (!setupDbPromise) {
  31. setupDbPromise = setupDb()
  32. }
  33. await setupDbPromise
  34. }
  35. const db = {}
  36. const mongoClient = new mongodb.MongoClient(
  37. Settings.mongo.url,
  38. Settings.mongo.options
  39. )
  40. addConnectionDrainer('mongodb', async () => {
  41. await mongoClient.close()
  42. })
  43. async function setupDb() {
  44. const internalDb = mongoClient.db()
  45. db.contacts = internalDb.collection('contacts')
  46. db.deletedFiles = internalDb.collection('deletedFiles')
  47. db.deletedProjects = internalDb.collection('deletedProjects')
  48. db.deletedSubscriptions = internalDb.collection('deletedSubscriptions')
  49. db.deletedUsers = internalDb.collection('deletedUsers')
  50. db.dropboxEntities = internalDb.collection('dropboxEntities')
  51. db.dropboxProjects = internalDb.collection('dropboxProjects')
  52. db.docHistory = internalDb.collection('docHistory')
  53. db.docHistoryIndex = internalDb.collection('docHistoryIndex')
  54. db.docSnapshots = internalDb.collection('docSnapshots')
  55. db.docs = internalDb.collection('docs')
  56. db.feedbacks = internalDb.collection('feedbacks')
  57. db.githubSyncEntityVersions = internalDb.collection(
  58. 'githubSyncEntityVersions'
  59. )
  60. db.githubSyncProjectStates = internalDb.collection('githubSyncProjectStates')
  61. db.githubSyncUserCredentials = internalDb.collection(
  62. 'githubSyncUserCredentials'
  63. )
  64. db.globalMetrics = internalDb.collection('globalMetrics')
  65. db.grouppolicies = internalDb.collection('grouppolicies')
  66. db.institutions = internalDb.collection('institutions')
  67. db.messages = internalDb.collection('messages')
  68. db.migrations = internalDb.collection('migrations')
  69. db.notifications = internalDb.collection('notifications')
  70. db.oauthAccessTokens = internalDb.collection('oauthAccessTokens')
  71. db.oauthApplications = internalDb.collection('oauthApplications')
  72. db.oauthAuthorizationCodes = internalDb.collection('oauthAuthorizationCodes')
  73. db.projectAuditLogEntries = internalDb.collection('projectAuditLogEntries')
  74. db.projectHistoryChunks = internalDb.collection('projectHistoryChunks')
  75. db.projectHistoryFailures = internalDb.collection('projectHistoryFailures')
  76. db.projectHistoryLabels = internalDb.collection('projectHistoryLabels')
  77. db.projectHistoryMetaData = internalDb.collection('projectHistoryMetaData')
  78. db.projectHistorySyncState = internalDb.collection('projectHistorySyncState')
  79. db.projectInvites = internalDb.collection('projectInvites')
  80. db.projects = internalDb.collection('projects')
  81. db.publishers = internalDb.collection('publishers')
  82. db.rooms = internalDb.collection('rooms')
  83. db.samlCache = internalDb.collection('samlCache')
  84. db.samlLogs = internalDb.collection('samlLogs')
  85. db.spellingPreferences = internalDb.collection('spellingPreferences')
  86. db.splittests = internalDb.collection('splittests')
  87. db.ssoConfigs = internalDb.collection('ssoConfigs')
  88. db.subscriptions = internalDb.collection('subscriptions')
  89. db.surveys = internalDb.collection('surveys')
  90. db.systemmessages = internalDb.collection('systemmessages')
  91. db.tags = internalDb.collection('tags')
  92. db.teamInvites = internalDb.collection('teamInvites')
  93. db.tokens = internalDb.collection('tokens')
  94. db.userAuditLogEntries = internalDb.collection('userAuditLogEntries')
  95. db.users = internalDb.collection('users')
  96. db.onboardingDataCollection = internalDb.collection(
  97. 'onboardingDataCollection'
  98. )
  99. await mongoClient.connect()
  100. }
  101. async function getCollectionNames() {
  102. const internalDb = mongoClient.db()
  103. const collections = await internalDb.collections()
  104. return collections.map(collection => collection.collectionName)
  105. }
  106. async function dropTestDatabase() {
  107. const internalDb = mongoClient.db()
  108. const dbName = internalDb.databaseName
  109. const env = process.env.NODE_ENV
  110. if (dbName !== 'test-overleaf' || env !== 'test') {
  111. throw new OError(
  112. `Refusing to clear database '${dbName}' in environment '${env}'`
  113. )
  114. }
  115. await internalDb.dropDatabase()
  116. }
  117. /**
  118. * WARNING: Consider using a pre-populated collection from `db` to avoid typos!
  119. */
  120. async function getCollectionInternal(name) {
  121. const internalDb = mongoClient.db()
  122. return internalDb.collection(name)
  123. }
  124. module.exports = {
  125. db,
  126. ObjectId,
  127. getCollectionNames,
  128. getCollectionInternal,
  129. dropTestDatabase,
  130. waitForDb,
  131. READ_PREFERENCE_PRIMARY,
  132. READ_PREFERENCE_SECONDARY,
  133. }