ThirdPartyIdentityManager.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. const Errors = require('../Errors/Errors')
  2. const { User } = require('../../models/User')
  3. const UserUpdater = require('./UserUpdater')
  4. const _ = require('lodash')
  5. const ThirdPartyIdentityManager = (module.exports = {
  6. getUser(providerId, externalUserId, callback) {
  7. if (providerId == null || externalUserId == null) {
  8. return callback(new Error('invalid arguments'))
  9. }
  10. const query = ThirdPartyIdentityManager._getUserQuery(
  11. providerId,
  12. externalUserId
  13. )
  14. User.findOne(query, function(err, user) {
  15. if (err != null) {
  16. return callback(err)
  17. }
  18. if (!user) {
  19. return callback(new Errors.ThirdPartyUserNotFoundError())
  20. }
  21. callback(null, user)
  22. })
  23. },
  24. login(providerId, externalUserId, externalData, callback) {
  25. ThirdPartyIdentityManager.getUser(providerId, externalUserId, function(
  26. err,
  27. user
  28. ) {
  29. if (err != null) {
  30. return callback(err)
  31. }
  32. if (!externalData) {
  33. return callback(null, user)
  34. }
  35. const query = ThirdPartyIdentityManager._getUserQuery(
  36. providerId,
  37. externalUserId
  38. )
  39. const update = ThirdPartyIdentityManager._thirdPartyIdentifierUpdate(
  40. user,
  41. providerId,
  42. externalUserId,
  43. externalData
  44. )
  45. User.findOneAndUpdate(query, update, { new: true }, callback)
  46. })
  47. },
  48. _getUserQuery(providerId, externalUserId) {
  49. externalUserId = externalUserId.toString()
  50. providerId = providerId.toString()
  51. const query = {
  52. 'thirdPartyIdentifiers.externalUserId': externalUserId,
  53. 'thirdPartyIdentifiers.providerId': providerId
  54. }
  55. return query
  56. },
  57. _thirdPartyIdentifierUpdate(user, providerId, externalUserId, externalData) {
  58. providerId = providerId.toString()
  59. // get third party identifier object from array
  60. const thirdPartyIdentifier = user.thirdPartyIdentifiers.find(
  61. tpi =>
  62. tpi.externalUserId === externalUserId && tpi.providerId === providerId
  63. )
  64. // do recursive merge of new data over existing data
  65. _.merge(thirdPartyIdentifier.externalData, externalData)
  66. const update = { 'thirdPartyIdentifiers.$': thirdPartyIdentifier }
  67. return update
  68. },
  69. // register: () ->
  70. // this should be implemented once we move to having v2 as the master
  71. // but for now we need to register with v1 then call link once that
  72. // is complete
  73. link(userId, providerId, externalUserId, externalData, callback, retry) {
  74. const query = {
  75. _id: userId,
  76. 'thirdPartyIdentifiers.providerId': {
  77. $ne: providerId
  78. }
  79. }
  80. const update = {
  81. $push: {
  82. thirdPartyIdentifiers: {
  83. externalUserId,
  84. externalData,
  85. providerId
  86. }
  87. }
  88. }
  89. // add new tpi only if an entry for the provider does not exist
  90. UserUpdater.updateUser(query, update, function(err, res) {
  91. if (err != null) {
  92. return callback(err)
  93. }
  94. if (res.nModified === 1) {
  95. return callback(null, res)
  96. }
  97. // if already retried then throw error
  98. if (retry) {
  99. return callback(new Error('update failed'))
  100. }
  101. // attempt to clear existing entry then retry
  102. ThirdPartyIdentityManager.unlink(userId, providerId, function(err) {
  103. if (err != null) {
  104. return callback(err)
  105. }
  106. ThirdPartyIdentityManager.link(
  107. userId,
  108. providerId,
  109. externalUserId,
  110. externalData,
  111. callback,
  112. true
  113. )
  114. })
  115. })
  116. },
  117. unlink(userId, providerId, callback) {
  118. const update = {
  119. $pull: {
  120. thirdPartyIdentifiers: {
  121. providerId
  122. }
  123. }
  124. }
  125. UserUpdater.updateUser(userId, update, callback)
  126. }
  127. })