LaunchpadControllerTests.js 32 KB

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