AdminController.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /* eslint-disable
  2. n/handle-callback-err,
  3. max-len
  4. */
  5. // TODO: This file was created by bulk-decaffeinate.
  6. // Fix any style issues and re-enable lint.
  7. /*
  8. * decaffeinate suggestions:
  9. * DS101: Remove unnecessary use of Array.from
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * DS103: Rewrite code to no longer use __guard__
  12. * DS205: Consider reworking code to avoid use of IIFEs
  13. * DS207: Consider shorter variations of null checks
  14. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  15. */
  16. const metrics = require('@overleaf/metrics')
  17. const logger = require('@overleaf/logger')
  18. const _ = require('lodash')
  19. const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
  20. const Settings = require('@overleaf/settings')
  21. const TpdsUpdateSender = require('../ThirdPartyDataStore/TpdsUpdateSender')
  22. const TpdsProjectFlusher = require('../ThirdPartyDataStore/TpdsProjectFlusher')
  23. const EditorRealTimeController = require('../Editor/EditorRealTimeController')
  24. const SystemMessageManager = require('../SystemMessages/SystemMessageManager')
  25. const {
  26. addOptionalCleanupHandlerAfterDrainingConnections,
  27. } = require('../../infrastructure/GracefulShutdown')
  28. const oneMinInMs = 60 * 1000
  29. function updateOpenConnetionsMetrics() {
  30. metrics.gauge(
  31. 'open_connections.socketio',
  32. __guard__(
  33. __guard__(
  34. __guard__(require('../../infrastructure/Server').io, x2 => x2.sockets),
  35. x1 => x1.clients()
  36. ),
  37. x => x.length
  38. )
  39. )
  40. metrics.gauge(
  41. 'open_connections.http',
  42. _.size(__guard__(require('http').globalAgent, x3 => x3.sockets))
  43. )
  44. metrics.gauge(
  45. 'open_connections.https',
  46. _.size(__guard__(require('https').globalAgent, x4 => x4.sockets))
  47. )
  48. }
  49. const intervalHandle = setInterval(updateOpenConnetionsMetrics, oneMinInMs)
  50. addOptionalCleanupHandlerAfterDrainingConnections(
  51. 'collect connection metrics',
  52. () => {
  53. clearInterval(intervalHandle)
  54. }
  55. )
  56. const AdminController = {
  57. _sendDisconnectAllUsersMessage: delay => {
  58. return EditorRealTimeController.emitToAll(
  59. 'forceDisconnect',
  60. 'Sorry, we are performing a quick update to the editor and need to close it down. Please refresh the page to continue.',
  61. delay
  62. )
  63. },
  64. index: (req, res, next) => {
  65. let agents, url
  66. let agent
  67. const openSockets = {}
  68. const object = require('http').globalAgent.sockets
  69. for (url in object) {
  70. agents = object[url]
  71. openSockets[`http://${url}`] = (() => {
  72. const result = []
  73. for (agent of Array.from(agents)) {
  74. result.push(agent._httpMessage.path)
  75. }
  76. return result
  77. })()
  78. }
  79. const object1 = require('https').globalAgent.sockets
  80. for (url in object1) {
  81. agents = object1[url]
  82. openSockets[`https://${url}`] = (() => {
  83. const result1 = []
  84. for (agent of Array.from(agents)) {
  85. result1.push(agent._httpMessage.path)
  86. }
  87. return result1
  88. })()
  89. }
  90. return SystemMessageManager.getMessagesFromDB(function (
  91. error,
  92. systemMessages
  93. ) {
  94. if (error != null) {
  95. return next(error)
  96. }
  97. return res.render('admin/index', {
  98. title: 'System Admin',
  99. openSockets,
  100. systemMessages,
  101. })
  102. })
  103. },
  104. disconnectAllUsers: (req, res) => {
  105. logger.warn('disconecting everyone')
  106. const delay = (req.query && req.query.delay) > 0 ? req.query.delay : 10
  107. AdminController._sendDisconnectAllUsersMessage(delay)
  108. return res.sendStatus(200)
  109. },
  110. openEditor(req, res) {
  111. logger.warn('opening editor')
  112. Settings.editorIsOpen = true
  113. return res.sendStatus(200)
  114. },
  115. closeEditor(req, res) {
  116. logger.warn('closing editor')
  117. Settings.editorIsOpen = req.body.isOpen
  118. return res.sendStatus(200)
  119. },
  120. writeAllToMongo(req, res) {
  121. logger.debug('writing all docs to mongo')
  122. Settings.mongo.writeAll = true
  123. return DocumentUpdaterHandler.flushAllDocsToMongo(function () {
  124. logger.debug('all docs have been saved to mongo')
  125. return res.sendStatus(200)
  126. })
  127. },
  128. flushProjectToTpds(req, res) {
  129. return TpdsProjectFlusher.flushProjectToTpds(req.body.project_id, err =>
  130. res.sendStatus(200)
  131. )
  132. },
  133. pollDropboxForUser(req, res) {
  134. const { user_id: userId } = req.body
  135. return TpdsUpdateSender.pollDropboxForUser(userId, () =>
  136. res.sendStatus(200)
  137. )
  138. },
  139. createMessage(req, res, next) {
  140. return SystemMessageManager.createMessage(
  141. req.body.content,
  142. function (error) {
  143. if (error != null) {
  144. return next(error)
  145. }
  146. return res.sendStatus(200)
  147. }
  148. )
  149. },
  150. clearMessages(req, res, next) {
  151. return SystemMessageManager.clearMessages(function (error) {
  152. if (error != null) {
  153. return next(error)
  154. }
  155. return res.sendStatus(200)
  156. })
  157. },
  158. }
  159. function __guard__(value, transform) {
  160. return typeof value !== 'undefined' && value !== null
  161. ? transform(value)
  162. : undefined
  163. }
  164. module.exports = AdminController