LaunchpadControllerTests.js 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. /* eslint-disable
  2. max-len,
  3. no-return-assign,
  4. no-unused-vars,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. const SandboxedModule = require('sandboxed-module')
  14. const assert = require('assert')
  15. const { expect } = require('chai')
  16. const sinon = require('sinon')
  17. const modulePath = require('path').join(
  18. __dirname,
  19. '../../../app/src/LaunchpadController.js'
  20. )
  21. describe('LaunchpadController', function () {
  22. beforeEach(function () {
  23. this.user = {
  24. _id: '323123',
  25. first_name: 'fn',
  26. last_name: 'ln',
  27. save: sinon.stub().callsArgWith(0),
  28. }
  29. this.User = {}
  30. this.LaunchpadController = SandboxedModule.require(modulePath, {
  31. requires: {
  32. '@overleaf/settings': (this.Settings = {}),
  33. '@overleaf/metrics': (this.Metrics = {}),
  34. '../../../../app/src/Features/User/UserRegistrationHandler':
  35. (this.UserRegistrationHandler = {}),
  36. '../../../../app/src/Features/Email/EmailHandler': (this.EmailHandler =
  37. {}),
  38. '../../../../app/src/Features/User/UserGetter': (this.UserGetter = {}),
  39. '../../../../app/src/models/User': { User: this.User },
  40. '../../../../app/src/Features/Authentication/AuthenticationController':
  41. (this.AuthenticationController = {}),
  42. '../../../../app/src/Features/Authentication/SessionManager':
  43. (this.SessionManager = {}),
  44. },
  45. })
  46. this.email = 'bob@smith.com'
  47. this.req = {
  48. query: {},
  49. body: {},
  50. session: {},
  51. }
  52. this.res = {
  53. render: sinon.stub(),
  54. redirect: sinon.stub(),
  55. json: sinon.stub(),
  56. send: sinon.stub(),
  57. sendStatus: sinon.stub(),
  58. locals: {
  59. translate(key) {
  60. return key
  61. },
  62. },
  63. }
  64. this.res.status = sinon.stub().returns(this.res)
  65. return (this.next = sinon.stub())
  66. })
  67. describe('launchpadPage', function () {
  68. beforeEach(function () {
  69. this._atLeastOneAdminExists = sinon.stub(
  70. this.LaunchpadController,
  71. '_atLeastOneAdminExists'
  72. )
  73. return (this.AuthenticationController.setRedirectInSession = sinon.stub())
  74. })
  75. afterEach(function () {
  76. return this._atLeastOneAdminExists.restore()
  77. })
  78. describe('when the user is not logged in', function () {
  79. beforeEach(function () {
  80. this.SessionManager.getSessionUser = sinon.stub().returns(null)
  81. return (this.res.render = sinon.stub())
  82. })
  83. describe('when there are no admins', function () {
  84. beforeEach(function () {
  85. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  86. return this.LaunchpadController.launchpadPage(
  87. this.req,
  88. this.res,
  89. this.next
  90. )
  91. })
  92. it('should render the launchpad page', function () {
  93. const viewPath = require('path').join(
  94. __dirname,
  95. '../../../app/views/launchpad'
  96. )
  97. this.res.render.callCount.should.equal(1)
  98. return this.res.render
  99. .calledWith(viewPath, {
  100. adminUserExists: false,
  101. authMethod: 'local',
  102. })
  103. .should.equal(true)
  104. })
  105. })
  106. describe('when there is at least one admin', function () {
  107. beforeEach(function () {
  108. this._atLeastOneAdminExists.callsArgWith(0, null, true)
  109. return this.LaunchpadController.launchpadPage(
  110. this.req,
  111. this.res,
  112. this.next
  113. )
  114. })
  115. it('should redirect to login page', function () {
  116. this.AuthenticationController.setRedirectInSession.callCount.should.equal(
  117. 1
  118. )
  119. this.res.redirect.calledWith('/login').should.equal(true)
  120. })
  121. it('should not render the launchpad page', function () {
  122. return this.res.render.callCount.should.equal(0)
  123. })
  124. })
  125. })
  126. describe('when the user is logged in', function () {
  127. beforeEach(function () {
  128. this.user = {
  129. _id: 'abcd',
  130. email: 'abcd@example.com',
  131. }
  132. this.SessionManager.getSessionUser = sinon.stub().returns(this.user)
  133. this._atLeastOneAdminExists.callsArgWith(0, null, true)
  134. this.res.render = sinon.stub()
  135. return (this.res.redirect = sinon.stub())
  136. })
  137. describe('when the user is an admin', function () {
  138. beforeEach(function () {
  139. this.UserGetter.getUser = sinon
  140. .stub()
  141. .callsArgWith(2, null, { isAdmin: true })
  142. return this.LaunchpadController.launchpadPage(
  143. this.req,
  144. this.res,
  145. this.next
  146. )
  147. })
  148. it('should render the launchpad page', function () {
  149. const viewPath = require('path').join(
  150. __dirname,
  151. '../../../app/views/launchpad'
  152. )
  153. this.res.render.callCount.should.equal(1)
  154. return this.res.render
  155. .calledWith(viewPath, {
  156. wsUrl: undefined,
  157. adminUserExists: true,
  158. authMethod: 'local',
  159. })
  160. .should.equal(true)
  161. })
  162. })
  163. describe('when the user is not an admin', function () {
  164. beforeEach(function () {
  165. this.UserGetter.getUser = sinon
  166. .stub()
  167. .callsArgWith(2, null, { isAdmin: false })
  168. return this.LaunchpadController.launchpadPage(
  169. this.req,
  170. this.res,
  171. this.next
  172. )
  173. })
  174. it('should redirect to restricted page', function () {
  175. this.res.redirect.callCount.should.equal(1)
  176. return this.res.redirect.calledWith('/restricted').should.equal(true)
  177. })
  178. })
  179. })
  180. })
  181. describe('_atLeastOneAdminExists', function () {
  182. describe('when there are no admins', function () {
  183. beforeEach(function () {
  184. return (this.UserGetter.getUser = sinon
  185. .stub()
  186. .callsArgWith(2, null, null))
  187. })
  188. it('should callback with false', function (done) {
  189. return this.LaunchpadController._atLeastOneAdminExists(
  190. (err, exists) => {
  191. expect(err).to.equal(null)
  192. expect(exists).to.equal(false)
  193. return done()
  194. }
  195. )
  196. })
  197. })
  198. describe('when there are some admins', function () {
  199. beforeEach(function () {
  200. return (this.UserGetter.getUser = sinon
  201. .stub()
  202. .callsArgWith(2, null, { _id: 'abcd' }))
  203. })
  204. it('should callback with true', function (done) {
  205. return this.LaunchpadController._atLeastOneAdminExists(
  206. (err, exists) => {
  207. expect(err).to.equal(null)
  208. expect(exists).to.equal(true)
  209. return done()
  210. }
  211. )
  212. })
  213. })
  214. describe('when getUser produces an error', function () {
  215. beforeEach(function () {
  216. return (this.UserGetter.getUser = sinon
  217. .stub()
  218. .callsArgWith(2, new Error('woops')))
  219. })
  220. it('should produce an error', function (done) {
  221. return this.LaunchpadController._atLeastOneAdminExists(
  222. (err, exists) => {
  223. expect(err).to.not.equal(null)
  224. expect(err).to.be.instanceof(Error)
  225. expect(exists).to.equal(undefined)
  226. return done()
  227. }
  228. )
  229. })
  230. })
  231. })
  232. describe('sendTestEmail', function () {
  233. beforeEach(function () {
  234. this.EmailHandler.sendEmail = sinon.stub().callsArgWith(2, null)
  235. this.req.body.email = 'someone@example.com'
  236. this.res.sendStatus = sinon.stub()
  237. return (this.next = sinon.stub())
  238. })
  239. it('should produce a 200 response', function () {
  240. this.LaunchpadController.sendTestEmail(this.req, this.res, this.next)
  241. this.res.json
  242. .calledWith({
  243. message: 'email_sent',
  244. })
  245. .should.equal(true)
  246. })
  247. it('should not call next with an error', function () {
  248. this.LaunchpadController.sendTestEmail(this.req, this.res, this.next)
  249. return this.next.callCount.should.equal(0)
  250. })
  251. it('should have called sendEmail', function () {
  252. this.LaunchpadController.sendTestEmail(this.req, this.res, this.next)
  253. this.EmailHandler.sendEmail.callCount.should.equal(1)
  254. return this.EmailHandler.sendEmail
  255. .calledWith('testEmail')
  256. .should.equal(true)
  257. })
  258. describe('when sendEmail produces an error', function () {
  259. beforeEach(function () {
  260. return (this.EmailHandler.sendEmail = sinon
  261. .stub()
  262. .callsArgWith(2, new Error('woops')))
  263. })
  264. it('should call next with an error', function () {
  265. this.LaunchpadController.sendTestEmail(this.req, this.res, this.next)
  266. this.next.callCount.should.equal(1)
  267. return expect(this.next.lastCall.args[0]).to.be.instanceof(Error)
  268. })
  269. })
  270. describe('when no email address is supplied', function () {
  271. beforeEach(function () {
  272. return (this.req.body.email = undefined)
  273. })
  274. it('should produce a 400 response', function () {
  275. this.LaunchpadController.sendTestEmail(this.req, this.res, this.next)
  276. this.res.status.calledWith(400).should.equal(true)
  277. this.res.json
  278. .calledWith({
  279. message: 'no email address supplied',
  280. })
  281. .should.equal(true)
  282. })
  283. })
  284. })
  285. describe('registerAdmin', function () {
  286. beforeEach(function () {
  287. return (this._atLeastOneAdminExists = sinon.stub(
  288. this.LaunchpadController,
  289. '_atLeastOneAdminExists'
  290. ))
  291. })
  292. afterEach(function () {
  293. return this._atLeastOneAdminExists.restore()
  294. })
  295. describe('when all goes well', function () {
  296. beforeEach(function () {
  297. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  298. this.email = 'someone@example.com'
  299. this.password = 'a_really_bad_password'
  300. this.req.body.email = this.email
  301. this.req.body.password = this.password
  302. this.user = {
  303. _id: 'abcdef',
  304. email: this.email,
  305. }
  306. this.UserRegistrationHandler.registerNewUser = sinon
  307. .stub()
  308. .callsArgWith(1, null, this.user)
  309. this.User.updateOne = sinon.stub().callsArgWith(2, null)
  310. this.AuthenticationController.setRedirectInSession = sinon.stub()
  311. this.res.json = sinon.stub()
  312. this.next = sinon.stub()
  313. return this.LaunchpadController.registerAdmin(
  314. this.req,
  315. this.res,
  316. this.next
  317. )
  318. })
  319. it('should send back a json response', function () {
  320. this.res.json.callCount.should.equal(1)
  321. expect(this.res.json).to.have.been.calledWith({ redir: '/launchpad' })
  322. })
  323. it('should have checked for existing admins', function () {
  324. return this._atLeastOneAdminExists.callCount.should.equal(1)
  325. })
  326. it('should have called registerNewUser', function () {
  327. this.UserRegistrationHandler.registerNewUser.callCount.should.equal(1)
  328. return this.UserRegistrationHandler.registerNewUser
  329. .calledWith({ email: this.email, password: this.password })
  330. .should.equal(true)
  331. })
  332. it('should have updated the user to make them an admin', function () {
  333. this.User.updateOne.callCount.should.equal(1)
  334. return this.User.updateOne
  335. .calledWithMatch(
  336. { _id: this.user._id },
  337. {
  338. $set: {
  339. isAdmin: true,
  340. emails: [{ email: this.user.email }],
  341. },
  342. }
  343. )
  344. .should.equal(true)
  345. })
  346. })
  347. describe('when no email is supplied', function () {
  348. beforeEach(function () {
  349. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  350. this.email = undefined
  351. this.password = 'a_really_bad_password'
  352. this.req.body.email = this.email
  353. this.req.body.password = this.password
  354. this.user = {
  355. _id: 'abcdef',
  356. email: this.email,
  357. }
  358. this.UserRegistrationHandler.registerNewUser = sinon.stub()
  359. this.User.updateOne = sinon.stub()
  360. this.AuthenticationController.setRedirectInSession = sinon.stub()
  361. this.res.sendStatus = sinon.stub()
  362. this.next = sinon.stub()
  363. return this.LaunchpadController.registerAdmin(
  364. this.req,
  365. this.res,
  366. this.next
  367. )
  368. })
  369. it('should send a 400 response', function () {
  370. this.res.sendStatus.callCount.should.equal(1)
  371. return this.res.sendStatus.calledWith(400).should.equal(true)
  372. })
  373. it('should not check for existing admins', function () {
  374. return this._atLeastOneAdminExists.callCount.should.equal(0)
  375. })
  376. it('should not call registerNewUser', function () {
  377. return this.UserRegistrationHandler.registerNewUser.callCount.should.equal(
  378. 0
  379. )
  380. })
  381. })
  382. describe('when no password is supplied', function () {
  383. beforeEach(function () {
  384. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  385. this.email = 'someone@example.com'
  386. this.password = undefined
  387. this.req.body.email = this.email
  388. this.req.body.password = this.password
  389. this.user = {
  390. _id: 'abcdef',
  391. email: this.email,
  392. }
  393. this.UserRegistrationHandler.registerNewUser = sinon.stub()
  394. this.User.updateOne = sinon.stub()
  395. this.AuthenticationController.setRedirectInSession = sinon.stub()
  396. this.res.sendStatus = sinon.stub()
  397. this.next = sinon.stub()
  398. return this.LaunchpadController.registerAdmin(
  399. this.req,
  400. this.res,
  401. this.next
  402. )
  403. })
  404. it('should send a 400 response', function () {
  405. this.res.sendStatus.callCount.should.equal(1)
  406. return this.res.sendStatus.calledWith(400).should.equal(true)
  407. })
  408. it('should not check for existing admins', function () {
  409. return this._atLeastOneAdminExists.callCount.should.equal(0)
  410. })
  411. it('should not call registerNewUser', function () {
  412. return this.UserRegistrationHandler.registerNewUser.callCount.should.equal(
  413. 0
  414. )
  415. })
  416. })
  417. describe('when there are already existing admins', function () {
  418. beforeEach(function () {
  419. this._atLeastOneAdminExists.callsArgWith(0, null, true)
  420. this.email = 'someone@example.com'
  421. this.password = 'a_really_bad_password'
  422. this.req.body.email = this.email
  423. this.req.body.password = this.password
  424. this.user = {
  425. _id: 'abcdef',
  426. email: this.email,
  427. }
  428. this.UserRegistrationHandler.registerNewUser = sinon.stub()
  429. this.User.updateOne = sinon.stub()
  430. this.AuthenticationController.setRedirectInSession = sinon.stub()
  431. this.res.sendStatus = sinon.stub()
  432. this.next = sinon.stub()
  433. return this.LaunchpadController.registerAdmin(
  434. this.req,
  435. this.res,
  436. this.next
  437. )
  438. })
  439. it('should send a 403 response', function () {
  440. this.res.sendStatus.callCount.should.equal(1)
  441. return this.res.sendStatus.calledWith(403).should.equal(true)
  442. })
  443. it('should not call registerNewUser', function () {
  444. return this.UserRegistrationHandler.registerNewUser.callCount.should.equal(
  445. 0
  446. )
  447. })
  448. })
  449. describe('when checking admins produces an error', function () {
  450. beforeEach(function () {
  451. this._atLeastOneAdminExists.callsArgWith(0, new Error('woops'))
  452. this.email = 'someone@example.com'
  453. this.password = 'a_really_bad_password'
  454. this.req.body.email = this.email
  455. this.req.body.password = this.password
  456. this.user = {
  457. _id: 'abcdef',
  458. email: this.email,
  459. }
  460. this.UserRegistrationHandler.registerNewUser = sinon.stub()
  461. this.User.updateOne = sinon.stub()
  462. this.AuthenticationController.setRedirectInSession = sinon.stub()
  463. this.res.sendStatus = sinon.stub()
  464. this.next = sinon.stub()
  465. return this.LaunchpadController.registerAdmin(
  466. this.req,
  467. this.res,
  468. this.next
  469. )
  470. })
  471. it('should call next with an error', function () {
  472. this.next.callCount.should.equal(1)
  473. return expect(this.next.lastCall.args[0]).to.be.instanceof(Error)
  474. })
  475. it('should have checked for existing admins', function () {
  476. return this._atLeastOneAdminExists.callCount.should.equal(1)
  477. })
  478. it('should not call registerNewUser', function () {
  479. return this.UserRegistrationHandler.registerNewUser.callCount.should.equal(
  480. 0
  481. )
  482. })
  483. })
  484. describe('when registerNewUser produces an error', function () {
  485. beforeEach(function () {
  486. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  487. this.email = 'someone@example.com'
  488. this.password = 'a_really_bad_password'
  489. this.req.body.email = this.email
  490. this.req.body.password = this.password
  491. this.user = {
  492. _id: 'abcdef',
  493. email: this.email,
  494. }
  495. this.UserRegistrationHandler.registerNewUser = sinon
  496. .stub()
  497. .callsArgWith(1, new Error('woops'))
  498. this.User.updateOne = sinon.stub()
  499. this.AuthenticationController.setRedirectInSession = sinon.stub()
  500. this.res.json = sinon.stub()
  501. this.next = sinon.stub()
  502. return this.LaunchpadController.registerAdmin(
  503. this.req,
  504. this.res,
  505. this.next
  506. )
  507. })
  508. it('should call next with an error', function () {
  509. this.next.callCount.should.equal(1)
  510. return expect(this.next.lastCall.args[0]).to.be.instanceof(Error)
  511. })
  512. it('should have checked for existing admins', function () {
  513. return this._atLeastOneAdminExists.callCount.should.equal(1)
  514. })
  515. it('should have called registerNewUser', function () {
  516. this.UserRegistrationHandler.registerNewUser.callCount.should.equal(1)
  517. return this.UserRegistrationHandler.registerNewUser
  518. .calledWith({ email: this.email, password: this.password })
  519. .should.equal(true)
  520. })
  521. it('should not call update', function () {
  522. return this.User.updateOne.callCount.should.equal(0)
  523. })
  524. })
  525. describe('when user update produces an error', function () {
  526. beforeEach(function () {
  527. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  528. this.email = 'someone@example.com'
  529. this.password = 'a_really_bad_password'
  530. this.req.body.email = this.email
  531. this.req.body.password = this.password
  532. this.user = {
  533. _id: 'abcdef',
  534. email: this.email,
  535. }
  536. this.UserRegistrationHandler.registerNewUser = sinon
  537. .stub()
  538. .callsArgWith(1, null, this.user)
  539. this.User.updateOne = sinon.stub().callsArgWith(2, new Error('woops'))
  540. this.AuthenticationController.setRedirectInSession = sinon.stub()
  541. this.res.json = sinon.stub()
  542. this.next = sinon.stub()
  543. return this.LaunchpadController.registerAdmin(
  544. this.req,
  545. this.res,
  546. this.next
  547. )
  548. })
  549. it('should call next with an error', function () {
  550. this.next.callCount.should.equal(1)
  551. return expect(this.next.lastCall.args[0]).to.be.instanceof(Error)
  552. })
  553. it('should have checked for existing admins', function () {
  554. return this._atLeastOneAdminExists.callCount.should.equal(1)
  555. })
  556. it('should have called registerNewUser', function () {
  557. this.UserRegistrationHandler.registerNewUser.callCount.should.equal(1)
  558. return this.UserRegistrationHandler.registerNewUser
  559. .calledWith({ email: this.email, password: this.password })
  560. .should.equal(true)
  561. })
  562. })
  563. describe('when overleaf', function () {
  564. beforeEach(function () {
  565. this.Settings.overleaf = { one: 1 }
  566. this.Settings.createV1AccountOnLogin = true
  567. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  568. this.email = 'someone@example.com'
  569. this.password = 'a_really_bad_password'
  570. this.req.body.email = this.email
  571. this.req.body.password = this.password
  572. this.user = {
  573. _id: 'abcdef',
  574. email: this.email,
  575. }
  576. this.UserRegistrationHandler.registerNewUser = sinon
  577. .stub()
  578. .callsArgWith(1, null, this.user)
  579. this.User.updateOne = sinon.stub().callsArgWith(2, null)
  580. this.AuthenticationController.setRedirectInSession = sinon.stub()
  581. this.UserGetter.getUser = sinon
  582. .stub()
  583. .callsArgWith(1, null, { _id: '1234' })
  584. this.res.json = sinon.stub()
  585. this.next = sinon.stub()
  586. return this.LaunchpadController.registerAdmin(
  587. this.req,
  588. this.res,
  589. this.next
  590. )
  591. })
  592. it('should send back a json response', function () {
  593. this.res.json.callCount.should.equal(1)
  594. expect(this.res.json).to.have.been.calledWith({ redir: '/launchpad' })
  595. })
  596. it('should have checked for existing admins', function () {
  597. return this._atLeastOneAdminExists.callCount.should.equal(1)
  598. })
  599. it('should have called registerNewUser', function () {
  600. this.UserRegistrationHandler.registerNewUser.callCount.should.equal(1)
  601. return this.UserRegistrationHandler.registerNewUser
  602. .calledWith({ email: this.email, password: this.password })
  603. .should.equal(true)
  604. })
  605. it('should have updated the user to make them an admin', function () {
  606. return this.User.updateOne
  607. .calledWith(
  608. { _id: this.user._id },
  609. {
  610. $set: {
  611. isAdmin: true,
  612. emails: [{ email: this.user.email }],
  613. },
  614. }
  615. )
  616. .should.equal(true)
  617. })
  618. })
  619. })
  620. describe('registerExternalAuthAdmin', function () {
  621. beforeEach(function () {
  622. this.Settings.ldap = { one: 1 }
  623. return (this._atLeastOneAdminExists = sinon.stub(
  624. this.LaunchpadController,
  625. '_atLeastOneAdminExists'
  626. ))
  627. })
  628. afterEach(function () {
  629. return this._atLeastOneAdminExists.restore()
  630. })
  631. describe('when all goes well', function () {
  632. beforeEach(function () {
  633. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  634. this.email = 'someone@example.com'
  635. this.req.body.email = this.email
  636. this.user = {
  637. _id: 'abcdef',
  638. email: this.email,
  639. }
  640. this.UserRegistrationHandler.registerNewUser = sinon
  641. .stub()
  642. .callsArgWith(1, null, this.user)
  643. this.User.updateOne = sinon.stub().callsArgWith(2, null)
  644. this.AuthenticationController.setRedirectInSession = sinon.stub()
  645. this.res.json = sinon.stub()
  646. this.next = sinon.stub()
  647. return this.LaunchpadController.registerExternalAuthAdmin('ldap')(
  648. this.req,
  649. this.res,
  650. this.next
  651. )
  652. })
  653. it('should send back a json response', function () {
  654. this.res.json.callCount.should.equal(1)
  655. return expect(this.res.json.lastCall.args[0].email).to.equal(this.email)
  656. })
  657. it('should have checked for existing admins', function () {
  658. return this._atLeastOneAdminExists.callCount.should.equal(1)
  659. })
  660. it('should have called registerNewUser', function () {
  661. this.UserRegistrationHandler.registerNewUser.callCount.should.equal(1)
  662. return this.UserRegistrationHandler.registerNewUser
  663. .calledWith({
  664. email: this.email,
  665. password: 'password_here',
  666. first_name: this.email,
  667. last_name: '',
  668. })
  669. .should.equal(true)
  670. })
  671. it('should have updated the user to make them an admin', function () {
  672. this.User.updateOne.callCount.should.equal(1)
  673. return this.User.updateOne
  674. .calledWith(
  675. { _id: this.user._id },
  676. {
  677. $set: { isAdmin: true },
  678. emails: [{ email: this.user.email }],
  679. }
  680. )
  681. .should.equal(true)
  682. })
  683. it('should have set a redirect in session', function () {
  684. this.AuthenticationController.setRedirectInSession.callCount.should.equal(
  685. 1
  686. )
  687. return this.AuthenticationController.setRedirectInSession
  688. .calledWith(this.req, '/launchpad')
  689. .should.equal(true)
  690. })
  691. })
  692. describe('when the authMethod is invalid', function () {
  693. beforeEach(function () {
  694. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  695. this.email = undefined
  696. this.req.body.email = this.email
  697. this.user = {
  698. _id: 'abcdef',
  699. email: this.email,
  700. }
  701. this.UserRegistrationHandler.registerNewUser = sinon.stub()
  702. this.User.updateOne = sinon.stub()
  703. this.AuthenticationController.setRedirectInSession = sinon.stub()
  704. this.res.sendStatus = sinon.stub()
  705. this.next = sinon.stub()
  706. return this.LaunchpadController.registerExternalAuthAdmin(
  707. 'NOTAVALIDAUTHMETHOD'
  708. )(this.req, this.res, this.next)
  709. })
  710. it('should send a 403 response', function () {
  711. this.res.sendStatus.callCount.should.equal(1)
  712. return this.res.sendStatus.calledWith(403).should.equal(true)
  713. })
  714. it('should not check for existing admins', function () {
  715. return this._atLeastOneAdminExists.callCount.should.equal(0)
  716. })
  717. it('should not call registerNewUser', function () {
  718. return this.UserRegistrationHandler.registerNewUser.callCount.should.equal(
  719. 0
  720. )
  721. })
  722. })
  723. describe('when no email is supplied', function () {
  724. beforeEach(function () {
  725. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  726. this.email = undefined
  727. this.req.body.email = this.email
  728. this.user = {
  729. _id: 'abcdef',
  730. email: this.email,
  731. }
  732. this.UserRegistrationHandler.registerNewUser = sinon.stub()
  733. this.User.updateOne = sinon.stub()
  734. this.AuthenticationController.setRedirectInSession = sinon.stub()
  735. this.res.sendStatus = sinon.stub()
  736. this.next = sinon.stub()
  737. return this.LaunchpadController.registerExternalAuthAdmin('ldap')(
  738. this.req,
  739. this.res,
  740. this.next
  741. )
  742. })
  743. it('should send a 400 response', function () {
  744. this.res.sendStatus.callCount.should.equal(1)
  745. return this.res.sendStatus.calledWith(400).should.equal(true)
  746. })
  747. it('should not check for existing admins', function () {
  748. return this._atLeastOneAdminExists.callCount.should.equal(0)
  749. })
  750. it('should not call registerNewUser', function () {
  751. return this.UserRegistrationHandler.registerNewUser.callCount.should.equal(
  752. 0
  753. )
  754. })
  755. })
  756. describe('when there are already existing admins', function () {
  757. beforeEach(function () {
  758. this._atLeastOneAdminExists.callsArgWith(0, null, true)
  759. this.email = 'someone@example.com'
  760. this.req.body.email = this.email
  761. this.user = {
  762. _id: 'abcdef',
  763. email: this.email,
  764. }
  765. this.UserRegistrationHandler.registerNewUser = sinon.stub()
  766. this.User.updateOne = sinon.stub()
  767. this.AuthenticationController.setRedirectInSession = sinon.stub()
  768. this.res.sendStatus = sinon.stub()
  769. this.next = sinon.stub()
  770. return this.LaunchpadController.registerExternalAuthAdmin('ldap')(
  771. this.req,
  772. this.res,
  773. this.next
  774. )
  775. })
  776. it('should send a 403 response', function () {
  777. this.res.sendStatus.callCount.should.equal(1)
  778. return this.res.sendStatus.calledWith(403).should.equal(true)
  779. })
  780. it('should not call registerNewUser', function () {
  781. return this.UserRegistrationHandler.registerNewUser.callCount.should.equal(
  782. 0
  783. )
  784. })
  785. })
  786. describe('when checking admins produces an error', function () {
  787. beforeEach(function () {
  788. this._atLeastOneAdminExists.callsArgWith(0, new Error('woops'))
  789. this.email = 'someone@example.com'
  790. this.req.body.email = this.email
  791. this.user = {
  792. _id: 'abcdef',
  793. email: this.email,
  794. }
  795. this.UserRegistrationHandler.registerNewUser = sinon.stub()
  796. this.User.updateOne = sinon.stub()
  797. this.AuthenticationController.setRedirectInSession = sinon.stub()
  798. this.res.sendStatus = sinon.stub()
  799. this.next = sinon.stub()
  800. return this.LaunchpadController.registerExternalAuthAdmin('ldap')(
  801. this.req,
  802. this.res,
  803. this.next
  804. )
  805. })
  806. it('should call next with an error', function () {
  807. this.next.callCount.should.equal(1)
  808. return expect(this.next.lastCall.args[0]).to.be.instanceof(Error)
  809. })
  810. it('should have checked for existing admins', function () {
  811. return this._atLeastOneAdminExists.callCount.should.equal(1)
  812. })
  813. it('should not call registerNewUser', function () {
  814. return this.UserRegistrationHandler.registerNewUser.callCount.should.equal(
  815. 0
  816. )
  817. })
  818. })
  819. describe('when registerNewUser produces an error', function () {
  820. beforeEach(function () {
  821. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  822. this.email = 'someone@example.com'
  823. this.req.body.email = this.email
  824. this.user = {
  825. _id: 'abcdef',
  826. email: this.email,
  827. }
  828. this.UserRegistrationHandler.registerNewUser = sinon
  829. .stub()
  830. .callsArgWith(1, new Error('woops'))
  831. this.User.updateOne = sinon.stub()
  832. this.AuthenticationController.setRedirectInSession = sinon.stub()
  833. this.res.json = sinon.stub()
  834. this.next = sinon.stub()
  835. return this.LaunchpadController.registerExternalAuthAdmin('ldap')(
  836. this.req,
  837. this.res,
  838. this.next
  839. )
  840. })
  841. it('should call next with an error', function () {
  842. this.next.callCount.should.equal(1)
  843. return expect(this.next.lastCall.args[0]).to.be.instanceof(Error)
  844. })
  845. it('should have checked for existing admins', function () {
  846. return this._atLeastOneAdminExists.callCount.should.equal(1)
  847. })
  848. it('should have called registerNewUser', function () {
  849. this.UserRegistrationHandler.registerNewUser.callCount.should.equal(1)
  850. return this.UserRegistrationHandler.registerNewUser
  851. .calledWith({
  852. email: this.email,
  853. password: 'password_here',
  854. first_name: this.email,
  855. last_name: '',
  856. })
  857. .should.equal(true)
  858. })
  859. it('should not call update', function () {
  860. return this.User.updateOne.callCount.should.equal(0)
  861. })
  862. })
  863. describe('when user update produces an error', function () {
  864. beforeEach(function () {
  865. this._atLeastOneAdminExists.callsArgWith(0, null, false)
  866. this.email = 'someone@example.com'
  867. this.req.body.email = this.email
  868. this.user = {
  869. _id: 'abcdef',
  870. email: this.email,
  871. }
  872. this.UserRegistrationHandler.registerNewUser = sinon
  873. .stub()
  874. .callsArgWith(1, null, this.user)
  875. this.User.updateOne = sinon.stub().callsArgWith(2, new Error('woops'))
  876. this.AuthenticationController.setRedirectInSession = sinon.stub()
  877. this.res.json = sinon.stub()
  878. this.next = sinon.stub()
  879. return this.LaunchpadController.registerExternalAuthAdmin('ldap')(
  880. this.req,
  881. this.res,
  882. this.next
  883. )
  884. })
  885. it('should call next with an error', function () {
  886. this.next.callCount.should.equal(1)
  887. return expect(this.next.lastCall.args[0]).to.be.instanceof(Error)
  888. })
  889. it('should have checked for existing admins', function () {
  890. return this._atLeastOneAdminExists.callCount.should.equal(1)
  891. })
  892. it('should have called registerNewUser', function () {
  893. this.UserRegistrationHandler.registerNewUser.callCount.should.equal(1)
  894. return this.UserRegistrationHandler.registerNewUser
  895. .calledWith({
  896. email: this.email,
  897. password: 'password_here',
  898. first_name: this.email,
  899. last_name: '',
  900. })
  901. .should.equal(true)
  902. })
  903. })
  904. })
  905. })