LaunchpadControllerTests.js 32 KB

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