mongodb.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. const READ_PREFERENCE_PRIMARY = ReadPreference.primary.mode
  17. const READ_PREFERENCE_SECONDARY = Settings.mongo.hasSecondaries
  18. ? ReadPreference.secondary.mode
  19. : ReadPreference.secondaryPreferred.mode
  20. const mongoClient = new mongodb.MongoClient(
  21. Settings.mongo.url,
  22. Settings.mongo.options
  23. )
  24. addConnectionDrainer('mongodb', async () => {
  25. await mongoClient.close()
  26. })
  27. const internalDb = mongoClient.db()
  28. const db = {
  29. contacts: internalDb.collection('contacts'),
  30. deletedFiles: internalDb.collection('deletedFiles'),
  31. deletedProjects: internalDb.collection('deletedProjects'),
  32. deletedSubscriptions: internalDb.collection('deletedSubscriptions'),
  33. deletedUsers: internalDb.collection('deletedUsers'),
  34. dropboxEntities: internalDb.collection('dropboxEntities'),
  35. dropboxProjects: internalDb.collection('dropboxProjects'),
  36. docHistory: internalDb.collection('docHistory'),
  37. docHistoryIndex: internalDb.collection('docHistoryIndex'),
  38. docSnapshots: internalDb.collection('docSnapshots'),
  39. docs: internalDb.collection('docs'),
  40. feedbacks: internalDb.collection('feedbacks'),
  41. githubSyncEntityVersions: internalDb.collection('githubSyncEntityVersions'),
  42. githubSyncProjectStates: internalDb.collection('githubSyncProjectStates'),
  43. githubSyncUserCredentials: internalDb.collection('githubSyncUserCredentials'),
  44. globalMetrics: internalDb.collection('globalMetrics'),
  45. grouppolicies: internalDb.collection('grouppolicies'),
  46. institutions: internalDb.collection('institutions'),
  47. messages: internalDb.collection('messages'),
  48. migrations: internalDb.collection('migrations'),
  49. notifications: internalDb.collection('notifications'),
  50. oauthAccessTokens: internalDb.collection('oauthAccessTokens'),
  51. oauthApplications: internalDb.collection('oauthApplications'),
  52. oauthAuthorizationCodes: internalDb.collection('oauthAuthorizationCodes'),
  53. projectAuditLogEntries: internalDb.collection('projectAuditLogEntries'),
  54. projectHistoryChunks: internalDb.collection('projectHistoryChunks'),
  55. projectHistoryFailures: internalDb.collection('projectHistoryFailures'),
  56. projectHistoryGlobalBlobs: internalDb.collection('projectHistoryGlobalBlobs'),
  57. projectHistoryLabels: internalDb.collection('projectHistoryLabels'),
  58. projectHistoryMetaData: internalDb.collection('projectHistoryMetaData'),
  59. projectHistorySyncState: internalDb.collection('projectHistorySyncState'),
  60. projectInvites: internalDb.collection('projectInvites'),
  61. projects: internalDb.collection('projects'),
  62. publishers: internalDb.collection('publishers'),
  63. rooms: internalDb.collection('rooms'),
  64. samlCache: internalDb.collection('samlCache'),
  65. samlLogs: internalDb.collection('samlLogs'),
  66. spellingPreferences: internalDb.collection('spellingPreferences'),
  67. splittests: internalDb.collection('splittests'),
  68. ssoConfigs: internalDb.collection('ssoConfigs'),
  69. subscriptions: internalDb.collection('subscriptions'),
  70. surveys: internalDb.collection('surveys'),
  71. systemmessages: internalDb.collection('systemmessages'),
  72. tags: internalDb.collection('tags'),
  73. teamInvites: internalDb.collection('teamInvites'),
  74. tokens: internalDb.collection('tokens'),
  75. userAuditLogEntries: internalDb.collection('userAuditLogEntries'),
  76. users: internalDb.collection('users'),
  77. onboardingDataCollection: internalDb.collection('onboardingDataCollection'),
  78. }
  79. const connectionPromise = mongoClient.connect()
  80. async function getCollectionNames() {
  81. const internalDb = mongoClient.db()
  82. const collections = await internalDb.collections()
  83. return collections.map(collection => collection.collectionName)
  84. }
  85. async function cleanupTestDatabase() {
  86. ensureTestDatabase()
  87. const collectionNames = await getCollectionNames()
  88. const collections = []
  89. for (const name of collectionNames) {
  90. if (name in db && name !== 'migrations') {
  91. collections.push(db[name])
  92. }
  93. }
  94. await Promise.all(collections.map(coll => coll.deleteMany({})))
  95. }
  96. async function dropTestDatabase() {
  97. ensureTestDatabase()
  98. await mongoClient.db().dropDatabase()
  99. }
  100. function ensureTestDatabase() {
  101. const internalDb = mongoClient.db()
  102. const dbName = internalDb.databaseName
  103. const env = process.env.NODE_ENV
  104. if (dbName !== 'test-overleaf' || env !== 'test') {
  105. throw new OError(
  106. `Refusing to clear database '${dbName}' in environment '${env}'`
  107. )
  108. }
  109. }
  110. /**
  111. * WARNING: Consider using a pre-populated collection from `db` to avoid typos!
  112. */
  113. async function getCollectionInternal(name) {
  114. const internalDb = mongoClient.db()
  115. return internalDb.collection(name)
  116. }
  117. module.exports = {
  118. db,
  119. ObjectId,
  120. connectionPromise,
  121. getCollectionNames,
  122. getCollectionInternal,
  123. cleanupTestDatabase,
  124. dropTestDatabase,
  125. READ_PREFERENCE_PRIMARY,
  126. READ_PREFERENCE_SECONDARY,
  127. }