NotificationsBuilder.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. const NotificationsHandler = require('./NotificationsHandler')
  2. const { promisifyAll } = require('@overleaf/promise-utils')
  3. const request = require('request')
  4. const settings = require('@overleaf/settings')
  5. function dropboxDuplicateProjectNames(userId) {
  6. return {
  7. key: `dropboxDuplicateProjectNames-${userId}`,
  8. create(projectName, callback) {
  9. if (callback == null) {
  10. callback = function () {}
  11. }
  12. NotificationsHandler.createNotification(
  13. userId,
  14. this.key,
  15. 'notification_dropbox_duplicate_project_names',
  16. { projectName },
  17. null,
  18. true,
  19. callback
  20. )
  21. },
  22. read(callback) {
  23. if (callback == null) {
  24. callback = function () {}
  25. }
  26. NotificationsHandler.markAsReadWithKey(userId, this.key, callback)
  27. },
  28. }
  29. }
  30. function dropboxUnlinkedDueToLapsedReconfirmation(userId) {
  31. return {
  32. key: 'drobox-unlinked-due-to-lapsed-reconfirmation',
  33. create(callback) {
  34. NotificationsHandler.createNotification(
  35. userId,
  36. this.key,
  37. 'notification_dropbox_unlinked_due_to_lapsed_reconfirmation',
  38. {},
  39. null,
  40. true,
  41. callback
  42. )
  43. },
  44. read(callback) {
  45. NotificationsHandler.markAsReadWithKey(userId, this.key, callback)
  46. },
  47. }
  48. }
  49. function featuresUpgradedByAffiliation(affiliation, user) {
  50. return {
  51. key: `features-updated-by=${affiliation.institutionId}`,
  52. create(callback) {
  53. if (callback == null) {
  54. callback = function () {}
  55. }
  56. const messageOpts = { institutionName: affiliation.institutionName }
  57. NotificationsHandler.createNotification(
  58. user._id,
  59. this.key,
  60. 'notification_features_upgraded_by_affiliation',
  61. messageOpts,
  62. null,
  63. false,
  64. callback
  65. )
  66. },
  67. read(callback) {
  68. if (callback == null) {
  69. callback = function () {}
  70. }
  71. NotificationsHandler.markAsReadWithKey(user._id, this.key, callback)
  72. },
  73. }
  74. }
  75. function redundantPersonalSubscription(affiliation, user) {
  76. return {
  77. key: `redundant-personal-subscription-${affiliation.institutionId}`,
  78. create(callback) {
  79. if (callback == null) {
  80. callback = function () {}
  81. }
  82. const messageOpts = { institutionName: affiliation.institutionName }
  83. NotificationsHandler.createNotification(
  84. user._id,
  85. this.key,
  86. 'notification_personal_subscription_not_required_due_to_affiliation',
  87. messageOpts,
  88. null,
  89. false,
  90. callback
  91. )
  92. },
  93. read(callback) {
  94. if (callback == null) {
  95. callback = function () {}
  96. }
  97. NotificationsHandler.markAsReadWithKey(user._id, this.key, callback)
  98. },
  99. }
  100. }
  101. function projectInvite(invite, project, sendingUser, user) {
  102. return {
  103. key: `project-invite-${invite._id}`,
  104. create(callback) {
  105. if (callback == null) {
  106. callback = function () {}
  107. }
  108. const messageOpts = {
  109. userName: sendingUser.first_name,
  110. projectName: project.name,
  111. projectId: project._id.toString(),
  112. token: invite.token,
  113. }
  114. NotificationsHandler.createNotification(
  115. user._id,
  116. this.key,
  117. 'notification_project_invite',
  118. messageOpts,
  119. invite.expires,
  120. callback
  121. )
  122. },
  123. read(callback) {
  124. if (callback == null) {
  125. callback = function () {}
  126. }
  127. NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
  128. },
  129. }
  130. }
  131. function ipMatcherAffiliation(userId) {
  132. return {
  133. create(ip, callback) {
  134. if (callback == null) {
  135. callback = function () {}
  136. }
  137. if (!settings.apis.v1.url) {
  138. // service is not configured
  139. return callback()
  140. }
  141. request(
  142. {
  143. method: 'GET',
  144. url: `${settings.apis.v1.url}/api/v2/users/${userId}/ip_matcher`,
  145. auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass },
  146. body: { ip },
  147. json: true,
  148. timeout: settings.apis.v1.timeout,
  149. },
  150. function (error, response, body) {
  151. if (error != null) {
  152. return callback(error)
  153. }
  154. if (response.statusCode !== 200) {
  155. return callback()
  156. }
  157. const key = `ip-matched-affiliation-${body.id}`
  158. const portalPath = body.portal_slug
  159. ? `/${body.is_university ? 'edu' : 'org'}/${body.portal_slug}`
  160. : undefined
  161. const messageOpts = {
  162. university_name: body.name,
  163. institutionId: body.id,
  164. content: body.enrolment_ad_html,
  165. portalPath,
  166. ssoEnabled: body.sso_enabled,
  167. }
  168. NotificationsHandler.createNotification(
  169. userId,
  170. key,
  171. 'notification_ip_matched_affiliation',
  172. messageOpts,
  173. null,
  174. false,
  175. callback
  176. )
  177. }
  178. )
  179. },
  180. read(universityId, callback) {
  181. if (callback == null) {
  182. callback = function () {}
  183. }
  184. const key = `ip-matched-affiliation-${universityId}`
  185. NotificationsHandler.markAsReadWithKey(userId, key, callback)
  186. },
  187. }
  188. }
  189. function tpdsFileLimit(userId) {
  190. return {
  191. key: `tpdsFileLimit-${userId}`,
  192. create(projectName, callback) {
  193. if (callback == null) {
  194. callback = function () {}
  195. }
  196. const messageOpts = {
  197. projectName,
  198. }
  199. NotificationsHandler.createNotification(
  200. userId,
  201. this.key,
  202. 'notification_tpds_file_limit',
  203. messageOpts,
  204. null,
  205. true,
  206. callback
  207. )
  208. },
  209. read(callback) {
  210. if (callback == null) {
  211. callback = function () {}
  212. }
  213. NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
  214. },
  215. }
  216. }
  217. function groupInvitation(userId, subscriptionId, managedUsersEnabled) {
  218. return {
  219. key: `groupInvitation-${subscriptionId}-${userId}`,
  220. create(invite, callback) {
  221. if (callback == null) {
  222. callback = function () {}
  223. }
  224. const messageOpts = {
  225. token: invite.token,
  226. inviterName: invite.inviterName,
  227. managedUsersEnabled,
  228. }
  229. NotificationsHandler.createNotification(
  230. userId,
  231. this.key,
  232. 'notification_group_invitation',
  233. messageOpts,
  234. null,
  235. true,
  236. callback
  237. )
  238. },
  239. read(callback) {
  240. if (callback == null) {
  241. callback = function () {}
  242. }
  243. NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
  244. },
  245. }
  246. }
  247. function personalAndGroupSubscriptions(userId) {
  248. return {
  249. key: 'personal-and-group-subscriptions',
  250. create(callback) {
  251. if (callback == null) {
  252. callback = function () {}
  253. }
  254. NotificationsHandler.createNotification(
  255. userId,
  256. this.key,
  257. 'notification_personal_and_group_subscriptions',
  258. {},
  259. null,
  260. false,
  261. callback
  262. )
  263. },
  264. read(callback) {
  265. if (callback == null) {
  266. callback = function () {}
  267. }
  268. NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
  269. },
  270. }
  271. }
  272. function ieeeCollabratecRetirement(userId) {
  273. return {
  274. key: 'notification-ieee-collabratec-retirement',
  275. create(callback) {
  276. NotificationsHandler.createNotification(
  277. userId,
  278. this.key,
  279. 'notification_ieee_collabratec_retirement',
  280. {},
  281. new Date('2024-08-01'),
  282. false,
  283. callback
  284. )
  285. },
  286. read(callback) {
  287. NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
  288. },
  289. }
  290. }
  291. const NotificationsBuilder = {
  292. // Note: notification keys should be url-safe
  293. dropboxUnlinkedDueToLapsedReconfirmation,
  294. dropboxDuplicateProjectNames,
  295. featuresUpgradedByAffiliation,
  296. redundantPersonalSubscription,
  297. projectInvite,
  298. ipMatcherAffiliation,
  299. tpdsFileLimit,
  300. groupInvitation,
  301. personalAndGroupSubscriptions,
  302. ieeeCollabratecRetirement,
  303. }
  304. NotificationsBuilder.promises = {
  305. dropboxUnlinkedDueToLapsedReconfirmation: function (userId) {
  306. return promisifyAll(dropboxUnlinkedDueToLapsedReconfirmation(userId))
  307. },
  308. redundantPersonalSubscription: function (affiliation, user) {
  309. return promisifyAll(redundantPersonalSubscription(affiliation, user))
  310. },
  311. dropboxDuplicateProjectNames(userId) {
  312. return promisifyAll(dropboxDuplicateProjectNames(userId))
  313. },
  314. ipMatcherAffiliation: function (userId) {
  315. return promisifyAll(ipMatcherAffiliation(userId))
  316. },
  317. groupInvitation: function (userId, groupId, managedUsersEnabled) {
  318. return promisifyAll(groupInvitation(userId, groupId, managedUsersEnabled))
  319. },
  320. projectInvite(invite, project, sendingUser, user) {
  321. return promisifyAll(projectInvite(invite, project, sendingUser, user))
  322. },
  323. personalAndGroupSubscriptions(userId) {
  324. return promisifyAll(personalAndGroupSubscriptions(userId))
  325. },
  326. ieeeCollabratecRetirement(userId) {
  327. return promisifyAll(ieeeCollabratecRetirement(userId))
  328. },
  329. }
  330. module.exports = NotificationsBuilder