UserCreatorTests.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. const SandboxedModule = require('sandboxed-module')
  2. const chai = require('chai')
  3. const sinon = require('sinon')
  4. const assert = chai.assert
  5. const modulePath = '../../../../app/src/Features/User/UserCreator.js'
  6. describe('UserCreator', function() {
  7. beforeEach(function() {
  8. const self = this
  9. this.user = { _id: '12390i', ace: {} }
  10. this.user.save = sinon.stub().resolves(self.user)
  11. this.UserModel = class Project {
  12. constructor() {
  13. return self.user
  14. }
  15. }
  16. this.UserCreator = SandboxedModule.require(modulePath, {
  17. globals: {
  18. console: console
  19. },
  20. requires: {
  21. '../../models/User': {
  22. User: this.UserModel
  23. },
  24. 'logger-sharelatex': (this.Logger = {
  25. error: sinon.stub()
  26. }),
  27. 'metrics-sharelatex': { timeAsyncMethod() {} },
  28. '../../infrastructure/Features': (this.Features = {
  29. hasFeature: sinon.stub().returns(false)
  30. }),
  31. './UserDeleter': (this.UserDeleter = {
  32. promises: {
  33. deleteNewUser: sinon.stub().resolves()
  34. }
  35. }),
  36. './UserGetter': (this.UserGetter = {
  37. promises: {
  38. getUser: sinon.stub().resolves(this.user)
  39. }
  40. }),
  41. './UserUpdater': (this.UserUpdater = {
  42. promises: {
  43. addAffiliationForNewUser: sinon
  44. .stub()
  45. .resolves({ n: 1, nModified: 1, ok: 1 }),
  46. updateUser: sinon.stub().resolves()
  47. }
  48. })
  49. }
  50. })
  51. this.email = 'bob.oswald@gmail.com'
  52. })
  53. describe('createNewUser', function() {
  54. describe('with callbacks', function() {
  55. it('should take the opts and put them in the model', async function() {
  56. const user = await this.UserCreator.promises.createNewUser({
  57. email: this.email,
  58. holdingAccount: true
  59. })
  60. assert.equal(user.email, this.email)
  61. assert.equal(user.holdingAccount, true)
  62. assert.equal(user.first_name, 'bob.oswald')
  63. })
  64. it('should use the start of the email if the first name is empty string', async function() {
  65. const user = await this.UserCreator.promises.createNewUser({
  66. email: this.email,
  67. holdingAccount: true,
  68. first_name: ''
  69. })
  70. assert.equal(user.email, this.email)
  71. assert.equal(user.holdingAccount, true)
  72. assert.equal(user.first_name, 'bob.oswald')
  73. })
  74. it('should use the first name if passed', async function() {
  75. const user = await this.UserCreator.promises.createNewUser({
  76. email: this.email,
  77. holdingAccount: true,
  78. first_name: 'fiiirstname'
  79. })
  80. assert.equal(user.email, this.email)
  81. assert.equal(user.holdingAccount, true)
  82. assert.equal(user.first_name, 'fiiirstname')
  83. })
  84. it('should use the last name if passed', async function() {
  85. const user = await this.UserCreator.promises.createNewUser({
  86. email: this.email,
  87. holdingAccount: true,
  88. last_name: 'lastNammmmeee'
  89. })
  90. assert.equal(user.email, this.email)
  91. assert.equal(user.holdingAccount, true)
  92. assert.equal(user.last_name, 'lastNammmmeee')
  93. })
  94. it('should set emails attribute', async function() {
  95. const user = await this.UserCreator.promises.createNewUser({
  96. email: this.email
  97. })
  98. user.email.should.equal(this.email)
  99. user.emails.length.should.equal(1)
  100. user.emails[0].email.should.equal(this.email)
  101. user.emails[0].createdAt.should.be.a('date')
  102. user.emails[0].reversedHostname.should.equal('moc.liamg')
  103. })
  104. describe('with affiliations feature', function() {
  105. let attributes, user
  106. beforeEach(function() {
  107. attributes = { email: this.email }
  108. this.Features.hasFeature = sinon
  109. .stub()
  110. .withArgs('affiliations')
  111. .returns(true)
  112. })
  113. describe('when v1 affiliations API does not return an error', function() {
  114. beforeEach(async function() {
  115. user = await this.UserCreator.promises.createNewUser(attributes)
  116. })
  117. it('should flag that affiliation is unchecked', function() {
  118. user.emails[0].affiliationUnchecked.should.equal(true)
  119. })
  120. it('should try to add affiliation to v1', function() {
  121. sinon.assert.calledOnce(
  122. this.UserUpdater.promises.addAffiliationForNewUser
  123. )
  124. sinon.assert.calledWithMatch(
  125. this.UserUpdater.promises.addAffiliationForNewUser,
  126. user._id,
  127. this.email
  128. )
  129. })
  130. it('should query for updated user data', function() {
  131. sinon.assert.calledOnce(this.UserGetter.promises.getUser)
  132. })
  133. })
  134. describe('when v1 affiliations API does return an error', function() {
  135. beforeEach(async function() {
  136. this.UserUpdater.promises.addAffiliationForNewUser.rejects()
  137. user = await this.UserCreator.promises.createNewUser(attributes)
  138. })
  139. it('should flag that affiliation is unchecked', function() {
  140. user.emails[0].affiliationUnchecked.should.equal(true)
  141. })
  142. it('should try to add affiliation to v1', function() {
  143. sinon.assert.calledOnce(
  144. this.UserUpdater.promises.addAffiliationForNewUser
  145. )
  146. sinon.assert.calledWithMatch(
  147. this.UserUpdater.promises.addAffiliationForNewUser,
  148. user._id,
  149. this.email
  150. )
  151. })
  152. it('should not query for updated user data', function() {
  153. sinon.assert.notCalled(this.UserGetter.promises.getUser)
  154. })
  155. it('should log error', function() {
  156. sinon.assert.calledOnce(this.Logger.error)
  157. })
  158. })
  159. describe('when v1 affiliations API returns an error and requireAffiliation=true', function() {
  160. beforeEach(async function() {
  161. this.UserUpdater.promises.addAffiliationForNewUser.rejects()
  162. user = await this.UserCreator.promises.createNewUser(attributes)
  163. })
  164. it('should flag that affiliation is unchecked', function() {
  165. user.emails[0].affiliationUnchecked.should.equal(true)
  166. })
  167. it('should try to add affiliation to v1', function() {
  168. sinon.assert.calledOnce(
  169. this.UserUpdater.promises.addAffiliationForNewUser
  170. )
  171. sinon.assert.calledWithMatch(
  172. this.UserUpdater.promises.addAffiliationForNewUser,
  173. user._id,
  174. this.email
  175. )
  176. })
  177. it('should not query for updated user data', function() {
  178. sinon.assert.notCalled(this.UserGetter.promises.getUser)
  179. })
  180. it('should log error', function() {
  181. sinon.assert.calledOnce(this.Logger.error)
  182. })
  183. })
  184. })
  185. it('should not add affiliation when without affiliation feature', async function() {
  186. const attributes = { email: this.email }
  187. await this.UserCreator.promises.createNewUser(attributes)
  188. sinon.assert.notCalled(
  189. this.UserUpdater.promises.addAffiliationForNewUser
  190. )
  191. })
  192. })
  193. describe('with promises', function() {
  194. it('should take the opts and put them in the model', async function() {
  195. const opts = {
  196. email: this.email,
  197. holdingAccount: true
  198. }
  199. const user = await this.UserCreator.promises.createNewUser(opts)
  200. assert.equal(user.email, this.email)
  201. assert.equal(user.holdingAccount, true)
  202. assert.equal(user.first_name, 'bob.oswald')
  203. })
  204. it('should add affiliation when with affiliation feature', async function() {
  205. this.Features.hasFeature = sinon
  206. .stub()
  207. .withArgs('affiliations')
  208. .returns(true)
  209. const attributes = { email: this.email }
  210. const user = await this.UserCreator.promises.createNewUser(attributes)
  211. sinon.assert.calledOnce(
  212. this.UserUpdater.promises.addAffiliationForNewUser
  213. )
  214. sinon.assert.calledWithMatch(
  215. this.UserUpdater.promises.addAffiliationForNewUser,
  216. user._id,
  217. this.email
  218. )
  219. })
  220. it('should not add affiliation when without affiliation feature', async function() {
  221. this.Features.hasFeature = sinon.stub().returns(false)
  222. const attributes = { email: this.email }
  223. await this.UserCreator.promises.createNewUser(attributes)
  224. sinon.assert.notCalled(
  225. this.UserUpdater.promises.addAffiliationForNewUser
  226. )
  227. })
  228. it('should include SAML provider ID with email', async function() {
  229. const attributes = {
  230. email: this.email,
  231. samlIdentifiers: [{ email: this.email, providerId: '1' }]
  232. }
  233. const user = await this.UserCreator.promises.createNewUser(attributes)
  234. assert.equal(user.emails[0].samlProviderId, '1')
  235. })
  236. })
  237. })
  238. })