ThirdPartyIdentityManagerTests.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. const sinon = require('sinon')
  2. const chai = require('chai')
  3. const { expect } = chai
  4. const SandboxedModule = require('sandboxed-module')
  5. const modulePath =
  6. '../../../../app/src/Features/User/ThirdPartyIdentityManager.js'
  7. describe('ThirdPartyIdentityManager', function() {
  8. beforeEach(function() {
  9. this.userId = 'a1b2c3'
  10. this.user = {
  11. _id: this.userId,
  12. email: 'example@overleaf.com'
  13. }
  14. this.externalUserId = 'id789'
  15. this.externalData = {}
  16. this.ThirdPartyIdentityManager = SandboxedModule.require(modulePath, {
  17. globals: {
  18. console: console
  19. },
  20. requires: {
  21. '../../../../app/src/Features/Email/EmailHandler': (this.EmailHandler = {
  22. sendEmail: sinon.stub().yields()
  23. }),
  24. Errors: (this.Errors = {
  25. ThirdPartyIdentityExistsError: sinon.stub(),
  26. ThirdPartyUserNotFoundError: sinon.stub()
  27. }),
  28. 'logger-sharelatex': (this.logger = {
  29. error: sinon.stub()
  30. }),
  31. '../../../../app/src/models/User': {
  32. User: (this.User = {
  33. findOneAndUpdate: sinon.stub().yields(undefined, this.user),
  34. findOne: sinon.stub()
  35. })
  36. },
  37. 'settings-sharelatex': {
  38. oauthProviders: {
  39. google: {
  40. name: 'Google'
  41. },
  42. orcid: {
  43. name: 'Orcid'
  44. }
  45. }
  46. }
  47. }
  48. })
  49. })
  50. describe('link', function() {
  51. it('should send email alert', async function() {
  52. await this.ThirdPartyIdentityManager.promises.link(
  53. this.userId,
  54. 'google',
  55. this.externalUserId,
  56. this.externalData
  57. )
  58. const emailCall = this.EmailHandler.sendEmail.getCall(0)
  59. expect(emailCall.args[0]).to.equal('securityAlert')
  60. expect(emailCall.args[1].actionDescribed).to.contain(
  61. 'a Google account was linked'
  62. )
  63. })
  64. describe('errors', function() {
  65. const anError = new Error('oops')
  66. describe('EmailHandler', function() {
  67. beforeEach(function() {
  68. this.EmailHandler.sendEmail.yields(anError)
  69. })
  70. it('should log but not return the error', function(done) {
  71. this.ThirdPartyIdentityManager.link(
  72. this.userId,
  73. 'google',
  74. this.externalUserId,
  75. this.externalData,
  76. error => {
  77. expect(error).to.not.exist
  78. const loggerCall = this.logger.error.getCall(0)
  79. expect(loggerCall.args[0]).to.deep.equal({
  80. error: anError,
  81. userId: this.userId
  82. })
  83. expect(loggerCall.args[1]).to.contain(
  84. 'could not send security alert email when Google linked'
  85. )
  86. done()
  87. }
  88. )
  89. })
  90. })
  91. })
  92. })
  93. describe('unlink', function() {
  94. it('should send email alert', async function() {
  95. await this.ThirdPartyIdentityManager.promises.unlink(this.userId, 'orcid')
  96. const emailCall = this.EmailHandler.sendEmail.getCall(0)
  97. expect(emailCall.args[0]).to.equal('securityAlert')
  98. expect(emailCall.args[1].actionDescribed).to.contain(
  99. 'an Orcid account is no longer linked'
  100. )
  101. })
  102. describe('errors', function() {
  103. const anError = new Error('oops')
  104. describe('EmailHandler', function() {
  105. beforeEach(function() {
  106. this.EmailHandler.sendEmail.yields(anError)
  107. })
  108. it('should log but not return the error', function(done) {
  109. this.ThirdPartyIdentityManager.unlink(
  110. this.userId,
  111. 'google',
  112. error => {
  113. expect(error).to.not.exist
  114. const loggerCall = this.logger.error.getCall(0)
  115. expect(loggerCall.args[0]).to.deep.equal({
  116. error: anError,
  117. userId: this.userId
  118. })
  119. expect(loggerCall.args[1]).to.contain(
  120. 'could not send security alert email when Google no longer linked'
  121. )
  122. done()
  123. }
  124. )
  125. })
  126. })
  127. })
  128. })
  129. })