|
|
@@ -1,11 +1,29 @@
|
|
|
-const { expect } = require('chai')
|
|
|
+/* eslint-disable
|
|
|
+ handle-callback-err,
|
|
|
+ max-len,
|
|
|
+ no-return-assign,
|
|
|
+ no-unused-vars,
|
|
|
+*/
|
|
|
+// TODO: This file was created by bulk-decaffeinate.
|
|
|
+// Fix any style issues and re-enable lint.
|
|
|
+/*
|
|
|
+ * decaffeinate suggestions:
|
|
|
+ * DS102: Remove unnecessary code created because of implicit returns
|
|
|
+ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
|
+ */
|
|
|
const SandboxedModule = require('sandboxed-module')
|
|
|
+const assert = require('assert')
|
|
|
const path = require('path')
|
|
|
const sinon = require('sinon')
|
|
|
+const sinonChai = require('sinon-chai')
|
|
|
+const chai = require('chai')
|
|
|
const modulePath = path.join(
|
|
|
__dirname,
|
|
|
'../../../../app/src/Features/PasswordReset/PasswordResetHandler'
|
|
|
)
|
|
|
+const should = require('chai').should()
|
|
|
+chai.use(sinonChai)
|
|
|
+const { expect } = chai
|
|
|
|
|
|
describe('PasswordResetHandler', function() {
|
|
|
beforeEach(function() {
|
|
|
@@ -21,19 +39,17 @@ describe('PasswordResetHandler', function() {
|
|
|
}
|
|
|
this.EmailHandler = { sendEmail: sinon.stub() }
|
|
|
this.AuthenticationManager = {
|
|
|
- setUserPassword: sinon.stub()
|
|
|
+ setUserPassword: sinon.stub(),
|
|
|
+ setUserPasswordInV1: sinon.stub(),
|
|
|
+ setUserPasswordInV2: sinon.stub()
|
|
|
}
|
|
|
- this.V1Api = { request: sinon.stub() }
|
|
|
this.PasswordResetHandler = SandboxedModule.require(modulePath, {
|
|
|
- globals: {
|
|
|
- console: console
|
|
|
- },
|
|
|
+ globals: { console: console },
|
|
|
requires: {
|
|
|
'../User/UserGetter': this.UserGetter,
|
|
|
'../Security/OneTimeTokenHandler': this.OneTimeTokenHandler,
|
|
|
'../Email/EmailHandler': this.EmailHandler,
|
|
|
'../Authentication/AuthenticationManager': this.AuthenticationManager,
|
|
|
- '../V1/V1Api': this.V1Api,
|
|
|
'settings-sharelatex': this.settings,
|
|
|
'logger-sharelatex': {
|
|
|
log() {},
|
|
|
@@ -42,239 +58,147 @@ describe('PasswordResetHandler', function() {
|
|
|
}
|
|
|
})
|
|
|
this.token = '12312321i'
|
|
|
- this.email = 'bob@bob.com'
|
|
|
- this.user = {
|
|
|
- _id: 'user_id_here',
|
|
|
- email: this.email
|
|
|
- }
|
|
|
+ this.user_id = 'user_id_here'
|
|
|
+ this.user = { email: (this.email = 'bob@bob.com'), _id: 'user-id' }
|
|
|
this.password = 'my great secret password'
|
|
|
this.callback = sinon.stub()
|
|
|
+ // this should not have any effect now
|
|
|
+ this.settings.overleaf = true
|
|
|
+ })
|
|
|
+
|
|
|
+ afterEach(function() {
|
|
|
+ this.settings.overleaf = false
|
|
|
})
|
|
|
|
|
|
describe('generateAndEmailResetToken', function() {
|
|
|
- describe('when in ShareLaTeX', function() {
|
|
|
- it('should check the user exists', function(done) {
|
|
|
- this.UserGetter.getUserByMainEmail.callsArgWith(1)
|
|
|
- this.UserGetter.getUserByAnyEmail.callsArgWith(1)
|
|
|
- this.OneTimeTokenHandler.getNewToken.yields()
|
|
|
+ it('should check the user exists', function() {
|
|
|
+ this.UserGetter.getUserByAnyEmail.yields()
|
|
|
+ this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
+ this.user.email,
|
|
|
+ this.callback
|
|
|
+ )
|
|
|
+ this.UserGetter.getUserByAnyEmail.should.have.been.calledWith(
|
|
|
+ this.user.email
|
|
|
+ )
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should send the email with the token', function(done) {
|
|
|
+ this.UserGetter.getUserByAnyEmail.yields(null, this.user)
|
|
|
+ this.OneTimeTokenHandler.getNewToken.yields(null, this.token)
|
|
|
+ this.EmailHandler.sendEmail.yields()
|
|
|
+ this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
+ this.user.email,
|
|
|
+ (err, status) => {
|
|
|
+ this.EmailHandler.sendEmail.called.should.equal(true)
|
|
|
+ status.should.equal('primary')
|
|
|
+ const args = this.EmailHandler.sendEmail.args[0]
|
|
|
+ args[0].should.equal('passwordResetRequested')
|
|
|
+ args[1].setNewPasswordUrl.should.equal(
|
|
|
+ `${this.settings.siteUrl}/user/password/set?passwordResetToken=${
|
|
|
+ this.token
|
|
|
+ }&email=${encodeURIComponent(this.user.email)}`
|
|
|
+ )
|
|
|
+ done()
|
|
|
+ }
|
|
|
+ )
|
|
|
+ })
|
|
|
+
|
|
|
+ describe('when the email exists', function() {
|
|
|
+ beforeEach(function() {
|
|
|
+ this.UserGetter.getUserByAnyEmail.yields(null, this.user)
|
|
|
+ this.OneTimeTokenHandler.getNewToken.yields(null, this.token)
|
|
|
+ this.EmailHandler.sendEmail.yields()
|
|
|
this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
- this.user.email,
|
|
|
- (err, status) => {
|
|
|
- if (err) {
|
|
|
- return done(err)
|
|
|
- }
|
|
|
- expect(status).to.be.null
|
|
|
- done()
|
|
|
- }
|
|
|
+ this.email,
|
|
|
+ this.callback
|
|
|
)
|
|
|
})
|
|
|
|
|
|
- it('should send the email with the token', function(done) {
|
|
|
- this.UserGetter.getUserByMainEmail.callsArgWith(1, null, this.user)
|
|
|
- this.OneTimeTokenHandler.getNewToken.yields(null, this.token)
|
|
|
- this.EmailHandler.sendEmail.callsArgWith(2)
|
|
|
- this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
- this.user.email,
|
|
|
- (err, status) => {
|
|
|
- if (err) {
|
|
|
- return done(err)
|
|
|
- }
|
|
|
- this.EmailHandler.sendEmail.called.should.equal(true)
|
|
|
- this.OneTimeTokenHandler.getNewToken.should.have.been.calledWith(
|
|
|
- 'password',
|
|
|
- {
|
|
|
- user_id: this.user._id,
|
|
|
- email: this.email
|
|
|
- }
|
|
|
- )
|
|
|
- status.should.equal('primary')
|
|
|
- const args = this.EmailHandler.sendEmail.args[0]
|
|
|
- args[0].should.equal('passwordResetRequested')
|
|
|
- args[1].setNewPasswordUrl.should.equal(
|
|
|
- `${this.settings.siteUrl}/user/password/set?passwordResetToken=${
|
|
|
- this.token
|
|
|
- }&email=${encodeURIComponent(this.user.email)}`
|
|
|
- )
|
|
|
- done()
|
|
|
+ it('should set the password token data to the user id and email', function() {
|
|
|
+ this.OneTimeTokenHandler.getNewToken.should.have.been.calledWith(
|
|
|
+ 'password',
|
|
|
+ {
|
|
|
+ email: this.email,
|
|
|
+ user_id: this.user._id
|
|
|
}
|
|
|
)
|
|
|
})
|
|
|
|
|
|
- it('should return exists == null for a holdingAccount', function(done) {
|
|
|
- this.user.holdingAccount = true
|
|
|
- this.UserGetter.getUserByMainEmail.callsArgWith(1, null, this.user)
|
|
|
- this.UserGetter.getUserByAnyEmail.callsArgWith(1)
|
|
|
- this.OneTimeTokenHandler.getNewToken.yields()
|
|
|
- this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
- this.user.email,
|
|
|
- (err, status) => {
|
|
|
- if (err) {
|
|
|
- return done(err)
|
|
|
- }
|
|
|
- expect(status).to.be.null
|
|
|
- done()
|
|
|
- }
|
|
|
+ it('should send an email with the token', function() {
|
|
|
+ this.EmailHandler.sendEmail.called.should.equal(true)
|
|
|
+ const args = this.EmailHandler.sendEmail.args[0]
|
|
|
+ args[0].should.equal('passwordResetRequested')
|
|
|
+ args[1].setNewPasswordUrl.should.equal(
|
|
|
+ `${this.settings.siteUrl}/user/password/set?passwordResetToken=${
|
|
|
+ this.token
|
|
|
+ }&email=${encodeURIComponent(this.user.email)}`
|
|
|
)
|
|
|
})
|
|
|
|
|
|
- it('should set the password token data to the user id and email', function() {
|
|
|
- this.UserGetter.getUserByMainEmail.callsArgWith(1, null, this.user)
|
|
|
- this.OneTimeTokenHandler.getNewToken.yields(null, this.token)
|
|
|
- this.EmailHandler.sendEmail.callsArgWith(2)
|
|
|
+ it('should return status == true', function() {
|
|
|
+ this.callback.calledWith(null, 'primary').should.equal(true)
|
|
|
})
|
|
|
})
|
|
|
|
|
|
- describe('when in overleaf', function() {
|
|
|
+ describe("when the email doesn't exist", function() {
|
|
|
beforeEach(function() {
|
|
|
- this.settings.overleaf = true
|
|
|
+ this.UserGetter.getUserByAnyEmail.yields(null, null)
|
|
|
+ this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
+ this.email,
|
|
|
+ this.callback
|
|
|
+ )
|
|
|
})
|
|
|
|
|
|
- describe('when the email exists', function() {
|
|
|
- beforeEach(function() {
|
|
|
- this.V1Api.request.yields(null, {}, { user_id: 42 })
|
|
|
- this.OneTimeTokenHandler.getNewToken.yields(null, this.token)
|
|
|
- this.EmailHandler.sendEmail.yields()
|
|
|
- this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
- this.email,
|
|
|
- this.callback
|
|
|
- )
|
|
|
- })
|
|
|
-
|
|
|
- it('should call the v1 api for the user', function() {
|
|
|
- this.V1Api.request
|
|
|
- .calledWith({
|
|
|
- url: '/api/v1/sharelatex/user_emails',
|
|
|
- qs: {
|
|
|
- email: this.email
|
|
|
- },
|
|
|
- expectedStatusCodes: [404]
|
|
|
- })
|
|
|
- .should.equal(true)
|
|
|
- })
|
|
|
-
|
|
|
- it('should set the password token data to the user id and email', function() {
|
|
|
- this.OneTimeTokenHandler.getNewToken.should.have.been.calledWith(
|
|
|
- 'password',
|
|
|
- {
|
|
|
- v1_user_id: 42,
|
|
|
- email: this.email
|
|
|
- }
|
|
|
- )
|
|
|
- })
|
|
|
-
|
|
|
- it('should send an email with the token', function() {
|
|
|
- this.EmailHandler.sendEmail.called.should.equal(true)
|
|
|
- const args = this.EmailHandler.sendEmail.args[0]
|
|
|
- args[0].should.equal('passwordResetRequested')
|
|
|
- args[1].setNewPasswordUrl.should.equal(
|
|
|
- `${this.settings.siteUrl}/user/password/set?passwordResetToken=${
|
|
|
- this.token
|
|
|
- }&email=${encodeURIComponent(this.user.email)}`
|
|
|
- )
|
|
|
- })
|
|
|
-
|
|
|
- it('should return status == true', function() {
|
|
|
- this.callback.calledWith(null, 'primary').should.equal(true)
|
|
|
- })
|
|
|
+ it('should not set the password token data', function() {
|
|
|
+ this.OneTimeTokenHandler.getNewToken.called.should.equal(false)
|
|
|
})
|
|
|
|
|
|
- describe("when the email doesn't exist", function() {
|
|
|
- beforeEach(function() {
|
|
|
- this.V1Api.request = sinon
|
|
|
- .stub()
|
|
|
- .yields(null, { statusCode: 404 }, {})
|
|
|
- this.UserGetter.getUserByAnyEmail.callsArgWith(1)
|
|
|
- this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
- this.email,
|
|
|
- this.callback
|
|
|
- )
|
|
|
- })
|
|
|
-
|
|
|
- it('should not set the password token data', function() {
|
|
|
- this.OneTimeTokenHandler.getNewToken.called.should.equal(false)
|
|
|
- })
|
|
|
-
|
|
|
- it('should send an email with the token', function() {
|
|
|
- this.EmailHandler.sendEmail.called.should.equal(false)
|
|
|
- })
|
|
|
-
|
|
|
- it('should return status == null', function() {
|
|
|
- this.callback.calledWith(null, null).should.equal(true)
|
|
|
- })
|
|
|
+ it('should send an email with the token', function() {
|
|
|
+ this.EmailHandler.sendEmail.called.should.equal(false)
|
|
|
})
|
|
|
|
|
|
- describe("when the user isn't on v2", function() {
|
|
|
- beforeEach(function() {
|
|
|
- this.V1Api.request = sinon
|
|
|
- .stub()
|
|
|
- .yields(null, { statusCode: 404 }, {})
|
|
|
- this.UserGetter.getUserByAnyEmail.callsArgWith(1, null, this.user)
|
|
|
- this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
- this.email,
|
|
|
- this.callback
|
|
|
- )
|
|
|
- })
|
|
|
-
|
|
|
- it('should not set the password token data', function() {
|
|
|
- this.OneTimeTokenHandler.getNewToken.called.should.equal(false)
|
|
|
- })
|
|
|
-
|
|
|
- it('should not send an email with the token', function() {
|
|
|
- this.EmailHandler.sendEmail.called.should.equal(false)
|
|
|
- })
|
|
|
-
|
|
|
- it('should return status == sharelatex', function() {
|
|
|
- this.callback.calledWith(null, 'sharelatex').should.equal(true)
|
|
|
- })
|
|
|
+ it('should return status == null', function() {
|
|
|
+ this.callback.calledWith(null, null).should.equal(true)
|
|
|
})
|
|
|
+ })
|
|
|
|
|
|
- describe('when the email is a secondary email', function() {
|
|
|
- beforeEach(function() {
|
|
|
- this.V1Api.request = sinon
|
|
|
- .stub()
|
|
|
- .yields(null, { statusCode: 404 }, {})
|
|
|
- this.user.overleaf = { id: 101 }
|
|
|
- this.UserGetter.getUserByAnyEmail.callsArgWith(1, null, this.user)
|
|
|
- this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
- this.email,
|
|
|
- this.callback
|
|
|
- )
|
|
|
- })
|
|
|
+ describe('when the email is a secondary email', function() {
|
|
|
+ beforeEach(function() {
|
|
|
+ this.UserGetter.getUserByAnyEmail.callsArgWith(1, null, this.user)
|
|
|
+ this.PasswordResetHandler.generateAndEmailResetToken(
|
|
|
+ 'secondary@email.com',
|
|
|
+ this.callback
|
|
|
+ )
|
|
|
+ })
|
|
|
|
|
|
- it('should not set the password token data', function() {
|
|
|
- this.OneTimeTokenHandler.getNewToken.called.should.equal(false)
|
|
|
- })
|
|
|
+ it('should not set the password token data', function() {
|
|
|
+ this.OneTimeTokenHandler.getNewToken.called.should.equal(false)
|
|
|
+ })
|
|
|
|
|
|
- it('should not send an email with the token', function() {
|
|
|
- this.EmailHandler.sendEmail.called.should.equal(false)
|
|
|
- })
|
|
|
+ it('should not send an email with the token', function() {
|
|
|
+ this.EmailHandler.sendEmail.called.should.equal(false)
|
|
|
+ })
|
|
|
|
|
|
- it('should return status == secondary', function() {
|
|
|
- this.callback.calledWith(null, 'secondary').should.equal(true)
|
|
|
- })
|
|
|
+ it('should return status == secondary', function() {
|
|
|
+ this.callback.calledWith(null, 'secondary').should.equal(true)
|
|
|
})
|
|
|
})
|
|
|
})
|
|
|
|
|
|
describe('setNewUserPassword', function() {
|
|
|
- describe('when no token is found', function() {
|
|
|
+ describe('when no data is found', function() {
|
|
|
beforeEach(function() {
|
|
|
this.OneTimeTokenHandler.getValueFromTokenAndExpire.yields(null, null)
|
|
|
- })
|
|
|
-
|
|
|
- it('should return found == false when', function(done) {
|
|
|
this.PasswordResetHandler.setNewUserPassword(
|
|
|
this.token,
|
|
|
this.password,
|
|
|
- (err, found) => {
|
|
|
- if (err != null) {
|
|
|
- return done(err)
|
|
|
- }
|
|
|
- expect(found).to.be.false
|
|
|
- done()
|
|
|
- }
|
|
|
+ this.callback
|
|
|
)
|
|
|
})
|
|
|
+
|
|
|
+ it('should return exists == false', function() {
|
|
|
+ this.callback.calledWith(null, false).should.equal(true)
|
|
|
+ })
|
|
|
})
|
|
|
|
|
|
describe('when the token has a user_id and email', function() {
|
|
|
@@ -336,8 +260,9 @@ describe('PasswordResetHandler', function() {
|
|
|
|
|
|
describe('when the email and user match', function() {
|
|
|
beforeEach(function() {
|
|
|
- this.UserGetter.getUserByMainEmail
|
|
|
- .withArgs(this.email)
|
|
|
+ this.PasswordResetHandler.getUserForPasswordResetToken = sinon
|
|
|
+ .stub()
|
|
|
+ .withArgs(this.token)
|
|
|
.yields(null, this.user)
|
|
|
})
|
|
|
|