ThirdPartyIdentityManager.coffee 4.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. Errors = require "../Errors/Errors"
  2. User = require("../../models/User").User
  3. UserStub = require("../../models/UserStub").UserStub
  4. UserUpdater = require "./UserUpdater"
  5. _ = require "lodash"
  6. module.exports = ThirdPartyIdentityManager =
  7. getUser: (providerId, externalUserId, callback) ->
  8. return callback(new Error "invalid arguments") unless providerId? and externalUserId?
  9. query = ThirdPartyIdentityManager._getUserQuery providerId, externalUserId
  10. User.findOne query, (err, user) ->
  11. return callback err if err?
  12. return callback(new Errors.ThirdPartyUserNotFoundError()) unless user
  13. callback null, user
  14. login: (providerId, externalUserId, externalData, callback) ->
  15. ThirdPartyIdentityManager.getUser providerId, externalUserId, (err, user) ->
  16. return callback err if err?
  17. return callback(null, user) unless externalData
  18. query = ThirdPartyIdentityManager._getUserQuery providerId, externalUserId
  19. update = ThirdPartyIdentityManager._thirdPartyIdentifierUpdate user, providerId, externalUserId, externalData
  20. User.findOneAndUpdate query, update, {new: true}, callback
  21. # attempt to login normally but check for user stub if user not found
  22. loginUserStub: (providerId, externalUserId, externalData, callback) ->
  23. ThirdPartyIdentityManager.login providerId, externalUserId, externalData, (err, user) ->
  24. return callback null, user unless err?
  25. return callback err unless err.name == "ThirdPartyUserNotFoundError"
  26. query = ThirdPartyIdentityManager._getUserQuery providerId, externalUserId
  27. UserStub.findOne query, (err, userStub) ->
  28. return callback err if err?
  29. return callback(new Errors.ThirdPartyUserNotFoundError()) unless userStub
  30. return callback(null, userStub) unless externalData
  31. update = ThirdPartyIdentityManager._thirdPartyIdentifierUpdate userStub, providerId, externalUserId, externalData
  32. UserStub.findOneAndUpdate query, update, {new: true}, callback
  33. _getUserQuery: (providerId, externalUserId) ->
  34. externalUserId = externalUserId.toString()
  35. providerId = providerId.toString()
  36. query =
  37. "thirdPartyIdentifiers.externalUserId": externalUserId
  38. "thirdPartyIdentifiers.providerId": providerId
  39. return query
  40. _thirdPartyIdentifierUpdate: (user, providerId, externalUserId, externalData) ->
  41. providerId = providerId.toString()
  42. # get third party identifier object from array
  43. thirdPartyIdentifier = user.thirdPartyIdentifiers.find (tpi) ->
  44. tpi.externalUserId == externalUserId and tpi.providerId == providerId
  45. # do recursive merge of new data over existing data
  46. _.merge(thirdPartyIdentifier.externalData, externalData)
  47. update = "thirdPartyIdentifiers.$": thirdPartyIdentifier
  48. return update
  49. # register: () ->
  50. # this should be implemented once we move to having v2 as the master
  51. # but for now we need to register with v1 then call link once that
  52. # is complete
  53. link: (user_id, providerId, externalUserId, externalData, callback, retry) ->
  54. query =
  55. _id: user_id
  56. "thirdPartyIdentifiers.providerId": $ne: providerId
  57. update = $push: thirdPartyIdentifiers:
  58. externalUserId: externalUserId
  59. externalData: externalData
  60. providerId: providerId
  61. # add new tpi only if an entry for the provider does not exist
  62. UserUpdater.updateUser query, update, (err, res) ->
  63. return callback err if err?
  64. return callback null, res if res.nModified == 1
  65. # if already retried then throw error
  66. return callback(new Error "update failed") if retry
  67. # attempt to clear existing entry then retry
  68. ThirdPartyIdentityManager.unlink user_id, providerId, (err) ->
  69. return callback err if err?
  70. ThirdPartyIdentityManager.link user_id, providerId, externalUserId, externalData, callback, true
  71. unlink: (user_id, providerId, callback) ->
  72. update = $pull: thirdPartyIdentifiers:
  73. providerId: providerId
  74. UserUpdater.updateUser user_id, update, callback
  75. # attempt to unlink user but unlink user stub if not linked to user
  76. unlinkUserStub: (user_id, providerId, callback) ->
  77. ThirdPartyIdentityManager.unlink user_id, providerId, (err, res) ->
  78. return callback err if err?
  79. return callback null, res if res.nModified == 1
  80. update = $pull: thirdPartyIdentifiers:
  81. providerId: providerId
  82. UserStub.update { _id: user_id }, update, callback