UserGetter.coffee 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. mongojs = require("../../infrastructure/mongojs")
  2. metrics = require('metrics-sharelatex')
  3. logger = require('logger-sharelatex')
  4. db = mongojs.db
  5. ObjectId = mongojs.ObjectId
  6. { getUserAffiliations } = require("../Institutions/InstitutionsAPI")
  7. Errors = require("../Errors/Errors")
  8. module.exports = UserGetter =
  9. getUser: (query, projection, callback = (error, user) ->) ->
  10. return callback(new Error("no query provided")) unless query?
  11. if query?.email?
  12. return callback(new Error("Don't use getUser to find user by email"), null)
  13. if arguments.length == 2
  14. callback = projection
  15. projection = {}
  16. if typeof query == "string"
  17. try
  18. query = _id: ObjectId(query)
  19. catch e
  20. return callback(null, null)
  21. else if query instanceof ObjectId
  22. query = _id: query
  23. db.users.findOne query, projection, callback
  24. getUserEmail: (userId, callback = (error, email) ->) ->
  25. @getUser userId, { email: 1 }, (error, user) ->
  26. callback(error, user?.email)
  27. getUserFullEmails: (userId, callback = (error, emails) ->) ->
  28. @getUser userId, { email: 1, emails: 1 }, (error, user) ->
  29. return callback error if error?
  30. return callback new Error('User not Found') unless user
  31. getUserAffiliations userId, (error, affiliationsData) ->
  32. return callback error if error?
  33. callback null, decorateFullEmails(user.email, user.emails or [], affiliationsData)
  34. getUserByMainEmail: (email, projection, callback = (error, user) ->) ->
  35. email = email.trim()
  36. if arguments.length == 2
  37. callback = projection
  38. projection = {}
  39. db.users.findOne email: email, projection, callback
  40. getUserByAnyEmail: (email, projection, callback = (error, user) ->) ->
  41. email = email.trim()
  42. if arguments.length == 2
  43. callback = projection
  44. projection = {}
  45. # $exists: true MUST be set to use the partial index
  46. query = emails: { $exists: true }, 'emails.email': email
  47. db.users.findOne query, projection, (error, user) =>
  48. return callback(error, user) if error? or user?
  49. # While multiple emails are being rolled out, check for the main email as
  50. # well
  51. @getUserByMainEmail email, projection, callback
  52. getUsersByAnyConfirmedEmail: (emails, projection, callback = (error, user) ->) ->
  53. if arguments.length == 2
  54. callback = projection
  55. projection = {}
  56. # $exists: true MUST be set to use the partial index
  57. query = emails: { $exists: true, $elemMatch: { email: { $in: emails }, confirmedAt: { $exists: true }}}
  58. db.users.find query, projection, (error, users) =>
  59. callback(error, users)
  60. getUsersByHostname: (hostname, projection, callback = (error, users) ->) ->
  61. reversedHostname = hostname.trim().split('').reverse().join('')
  62. query = emails: { $exists: true }, 'emails.reversedHostname': reversedHostname
  63. db.users.find query, projection, callback
  64. getUsers: (user_ids, projection, callback = (error, users) ->) ->
  65. try
  66. user_ids = user_ids.map (u) -> ObjectId(u.toString())
  67. catch error
  68. return callback error
  69. db.users.find { _id: { $in: user_ids} }, projection, callback
  70. getUserOrUserStubById: (user_id, projection, callback = (error, user, isStub) ->) ->
  71. try
  72. query = _id: ObjectId(user_id.toString())
  73. catch e
  74. return callback(new Error(e))
  75. db.users.findOne query, projection, (error, user) ->
  76. return callback(error) if error?
  77. return callback(null, user, false) if user?
  78. db.userstubs.findOne query, projection, (error, user) ->
  79. return callback(error) if error
  80. return callback() if !user?
  81. callback(null, user, true)
  82. # check for duplicate email address. This is also enforced at the DB level
  83. ensureUniqueEmailAddress: (newEmail, callback) ->
  84. @getUserByAnyEmail newEmail, (error, user) ->
  85. return callback(new Errors.EmailExistsError('alread_exists')) if user?
  86. callback(error)
  87. decorateFullEmails = (defaultEmail, emailsData, affiliationsData) ->
  88. emailsData.map (emailData) ->
  89. emailData.default = emailData.email == defaultEmail
  90. affiliation = affiliationsData.find (aff) -> aff.email == emailData.email
  91. if affiliation?
  92. { institution, inferred, role, department } = affiliation
  93. emailData.affiliation = { institution, inferred, role, department }
  94. else
  95. emailsData.affiliation = null
  96. emailData
  97. [
  98. 'getUser',
  99. 'getUserEmail',
  100. 'getUserByMainEmail',
  101. 'getUserByAnyEmail',
  102. 'getUsers',
  103. 'getUserOrUserStubById',
  104. 'ensureUniqueEmailAddress',
  105. ].map (method) ->
  106. metrics.timeAsyncMethod UserGetter, method, 'mongo.UserGetter', logger