mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Fix regressions with password reset
fixes #5564 - adds missing part of `/setup/` url in authentication middleware - ensures data is passed through from API to model in correct (new) format for password reset - re-adds missing/incorrectly commented out auth tests, and verifies that reset as far as token validation
This commit is contained in:
parent
f1b558eb68
commit
4ba77e0da4
3 changed files with 126 additions and 63 deletions
|
@ -136,7 +136,12 @@ authentication = {
|
||||||
|
|
||||||
return settings.read({context: {internal: true}, key: 'dbHash'}).then(function (response) {
|
return settings.read({context: {internal: true}, key: 'dbHash'}).then(function (response) {
|
||||||
var dbHash = response.settings[0].value;
|
var dbHash = response.settings[0].value;
|
||||||
return dataProvider.User.resetPassword(resetToken, newPassword, ne2Password, dbHash);
|
return dataProvider.User.resetPassword({
|
||||||
|
token: resetToken,
|
||||||
|
newPassword: newPassword,
|
||||||
|
ne2Password: ne2Password,
|
||||||
|
dbHash: dbHash
|
||||||
|
});
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
return Promise.resolve({passwordreset: [{message: 'Password changed successfully.'}]});
|
return Promise.resolve({passwordreset: [{message: 'Password changed successfully.'}]});
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
|
@ -174,7 +179,12 @@ authentication = {
|
||||||
|
|
||||||
return settings.read({context: {internal: true}, key: 'dbHash'}).then(function (response) {
|
return settings.read({context: {internal: true}, key: 'dbHash'}).then(function (response) {
|
||||||
var dbHash = response.settings[0].value;
|
var dbHash = response.settings[0].value;
|
||||||
return dataProvider.User.resetPassword(resetToken, newPassword, ne2Password, dbHash);
|
return dataProvider.User.resetPassword({
|
||||||
|
token: resetToken,
|
||||||
|
newPassword: newPassword,
|
||||||
|
ne2Password: ne2Password,
|
||||||
|
dbHash: dbHash
|
||||||
|
});
|
||||||
}).then(function (user) {
|
}).then(function (user) {
|
||||||
// Setting the slug to '' has the model regenerate the slug from the user's name
|
// Setting the slug to '' has the model regenerate the slug from the user's name
|
||||||
return dataProvider.User.edit({name: name, email: email, slug: ''}, {id: user.id});
|
return dataProvider.User.edit({name: name, email: email, slug: ''}, {id: user.id});
|
||||||
|
|
|
@ -112,7 +112,7 @@ middleware = {
|
||||||
|
|
||||||
if (subPath.indexOf('/ghost/api/') === 0
|
if (subPath.indexOf('/ghost/api/') === 0
|
||||||
&& (path.indexOf('/ghost/api/v0.1/authentication/') !== 0
|
&& (path.indexOf('/ghost/api/v0.1/authentication/') !== 0
|
||||||
|| (path.indexOf('/ghost/api/v0.1/authentication/') === 0 && req.method === 'PUT'))) {
|
|| (path.indexOf('/ghost/api/v0.1/authentication/setup/') === 0 && req.method === 'PUT'))) {
|
||||||
return passport.authenticate('bearer', {session: false, failWithError: true},
|
return passport.authenticate('bearer', {session: false, failWithError: true},
|
||||||
function authenticate(err, user, info) {
|
function authenticate(err, user, info) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -2,19 +2,53 @@
|
||||||
/*jshint expr:true*/
|
/*jshint expr:true*/
|
||||||
var testUtils = require('../../utils'),
|
var testUtils = require('../../utils'),
|
||||||
should = require('should'),
|
should = require('should'),
|
||||||
|
sinon = require('sinon'),
|
||||||
Promise = require('bluebird'),
|
Promise = require('bluebird'),
|
||||||
rewire = require('rewire'),
|
|
||||||
|
|
||||||
// Stuff we are testing
|
// Stuff we are testing
|
||||||
mail = rewire('../../../server/api/mail'),
|
|
||||||
AuthAPI = require('../../../server/api/authentication'),
|
AuthAPI = require('../../../server/api/authentication'),
|
||||||
context = testUtils.context;
|
mail = require('../../../server/api/mail'),
|
||||||
|
context = testUtils.context,
|
||||||
|
|
||||||
|
sandbox = sinon.sandbox.create();
|
||||||
|
|
||||||
describe('Authentication API', function () {
|
describe('Authentication API', function () {
|
||||||
|
var testInvite = {
|
||||||
|
invitation: [{
|
||||||
|
token: 'abc',
|
||||||
|
password: 'abcdefgh',
|
||||||
|
email: 'test@testghost.org',
|
||||||
|
name: 'Jo Bloggs'
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
testGenerateReset = {
|
||||||
|
passwordreset: [{
|
||||||
|
email: 'jbloggs@example.com'
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
testReset = {
|
||||||
|
passwordreset: [{
|
||||||
|
token: 'abc',
|
||||||
|
newPassword: 'abcdefgh',
|
||||||
|
ne2Password: 'abcdefgh'
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
// Keep the DB clean
|
// Keep the DB clean
|
||||||
before(testUtils.teardown);
|
before(testUtils.teardown);
|
||||||
afterEach(testUtils.teardown);
|
afterEach(testUtils.teardown);
|
||||||
|
|
||||||
|
// Stub mail
|
||||||
|
beforeEach(function () {
|
||||||
|
sandbox.stub(mail, 'send', function () {
|
||||||
|
return Promise.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
afterEach(function () {
|
||||||
|
sandbox.restore();
|
||||||
|
});
|
||||||
|
|
||||||
should.exist(AuthAPI);
|
should.exist(AuthAPI);
|
||||||
|
|
||||||
describe('Setup', function () {
|
describe('Setup', function () {
|
||||||
|
@ -37,13 +71,7 @@ describe('Authentication API', function () {
|
||||||
email: 'test@example.com',
|
email: 'test@example.com',
|
||||||
password: 'areallygoodpassword',
|
password: 'areallygoodpassword',
|
||||||
blogTitle: 'a test blog'
|
blogTitle: 'a test blog'
|
||||||
},
|
};
|
||||||
|
|
||||||
send = mail.__get__('mail.send');
|
|
||||||
|
|
||||||
mail.__set__('mail.send', function () {
|
|
||||||
return Promise.resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
AuthAPI.setup({setup: [setupData]}).then(function (result) {
|
AuthAPI.setup({setup: [setupData]}).then(function (result) {
|
||||||
should.exist(result);
|
should.exist(result);
|
||||||
|
@ -59,14 +87,51 @@ describe('Authentication API', function () {
|
||||||
newUser.email.should.equal(setupData.email);
|
newUser.email.should.equal(setupData.email);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch(done).finally(function () {
|
}).catch(done);
|
||||||
mail.__set__('mail.send', send);
|
});
|
||||||
|
|
||||||
|
it('should not allow an invitation to be accepted', function (done) {
|
||||||
|
AuthAPI.acceptInvitation(testInvite).then(function () {
|
||||||
|
done(new Error('Invitation was allowed to be accepted'));
|
||||||
|
}).catch(function (err) {
|
||||||
|
should.exist(err);
|
||||||
|
|
||||||
|
err.name.should.equal('NoPermissionError');
|
||||||
|
err.code.should.equal(403);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not generate a password reset token', function (done) {
|
||||||
|
AuthAPI.generateResetToken(testGenerateReset).then(function () {
|
||||||
|
done(new Error('Reset token was generated'));
|
||||||
|
}).catch(function (err) {
|
||||||
|
should.exist(err);
|
||||||
|
|
||||||
|
err.name.should.equal('NoPermissionError');
|
||||||
|
err.code.should.equal(403);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not allow a password reset', function (done) {
|
||||||
|
AuthAPI.resetPassword(testReset).then(function () {
|
||||||
|
done(new Error('Password was reset'));
|
||||||
|
}).catch(function (err) {
|
||||||
|
should.exist(err);
|
||||||
|
|
||||||
|
err.name.should.equal('NoPermissionError');
|
||||||
|
err.code.should.equal(403);
|
||||||
|
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Completed', function () {
|
describe('Completed', function () {
|
||||||
beforeEach(testUtils.setup('owner'));
|
beforeEach(testUtils.setup('roles', 'owner', 'settings', 'perms:setting', 'perms:mail', 'perms:init'));
|
||||||
|
|
||||||
it('should report that setup has been completed', function (done) {
|
it('should report that setup has been completed', function (done) {
|
||||||
AuthAPI.isSetup().then(function (result) {
|
AuthAPI.isSetup().then(function (result) {
|
||||||
|
@ -96,6 +161,41 @@ describe('Authentication API', function () {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should allow an invitation to be accepted, but fail on token validation', function (done) {
|
||||||
|
AuthAPI.acceptInvitation(testInvite).then(function () {
|
||||||
|
done(new Error('invitation did not fail on token validation'));
|
||||||
|
}).catch(function (err) {
|
||||||
|
should.exist(err);
|
||||||
|
|
||||||
|
err.name.should.equal('UnauthorizedError');
|
||||||
|
err.code.should.equal(401);
|
||||||
|
err.message.should.equal('Invalid token structure');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate a password reset token', function (done) {
|
||||||
|
AuthAPI.generateResetToken(testGenerateReset).then(function (result) {
|
||||||
|
result.should.exist;
|
||||||
|
result.passwordreset.should.be.an.Array.with.lengthOf(1);
|
||||||
|
result.passwordreset[0].should.have.property('message', 'Check your email for further instructions.');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow a password reset', function (done) {
|
||||||
|
AuthAPI.resetPassword(testReset).then(function () {
|
||||||
|
done(new Error('password reset did not fail on token validation'));
|
||||||
|
}).catch(function (err) {
|
||||||
|
should.exist(err);
|
||||||
|
|
||||||
|
err.name.should.equal('UnauthorizedError');
|
||||||
|
err.code.should.equal(401);
|
||||||
|
err.message.should.equal('Invalid token structure');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -204,51 +304,4 @@ describe('Authentication API', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// describe('Authentication', function () {
|
|
||||||
|
|
||||||
// describe('Setup not completed', function () {
|
|
||||||
|
|
||||||
// beforeEach(testUtils.setup());
|
|
||||||
|
|
||||||
// it('should not allow an invitation to be accepted', function (done) {
|
|
||||||
// AuthAPI.acceptInvitation().then(function () {
|
|
||||||
// done(new Error('Invitation was allowed to be accepted'));
|
|
||||||
// }).catch(function (err) {
|
|
||||||
// should.exist(err);
|
|
||||||
|
|
||||||
// err.name.should.equal('NoPermissionError');
|
|
||||||
// err.code.should.equal(403);
|
|
||||||
|
|
||||||
// done();
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should not generate a password reset token', function (done) {
|
|
||||||
// AuthAPI.generateResetToken().then(function () {
|
|
||||||
// done(new Error('Reset token was generated'));
|
|
||||||
// }).catch(function (err) {
|
|
||||||
// should.exist(err);
|
|
||||||
|
|
||||||
// err.name.should.equal('NoPermissionError');
|
|
||||||
// err.code.should.equal(403);
|
|
||||||
|
|
||||||
// done();
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should not allow a password reset', function (done) {
|
|
||||||
// AuthAPI.resetPassword().then(function () {
|
|
||||||
// done(new Error('Password was reset'));
|
|
||||||
// }).catch(function (err) {
|
|
||||||
// should.exist(err);
|
|
||||||
|
|
||||||
// err.name.should.equal('NoPermissionError');
|
|
||||||
// err.code.should.equal(403);
|
|
||||||
|
|
||||||
// done();
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue