mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
adds put route to authentication setup
closes #5342 - adds put version of authentication/setup that allows for updating of owner/settings values - doesn't send welcome email - adds tests for new put route
This commit is contained in:
parent
64e20735a3
commit
a2a0ba9023
4 changed files with 171 additions and 52 deletions
|
@ -9,6 +9,45 @@ var _ = require('lodash'),
|
||||||
config = require('../config'),
|
config = require('../config'),
|
||||||
authentication;
|
authentication;
|
||||||
|
|
||||||
|
function setupTasks(object) {
|
||||||
|
var setupUser,
|
||||||
|
internal = {context: {internal: true}};
|
||||||
|
|
||||||
|
return utils.checkObject(object, 'setup').then(function (checkedSetupData) {
|
||||||
|
setupUser = {
|
||||||
|
name: checkedSetupData.setup[0].name,
|
||||||
|
email: checkedSetupData.setup[0].email,
|
||||||
|
password: checkedSetupData.setup[0].password,
|
||||||
|
blogTitle: checkedSetupData.setup[0].blogTitle,
|
||||||
|
status: 'active'
|
||||||
|
};
|
||||||
|
|
||||||
|
return dataProvider.User.findOne({role: 'Owner', status: 'all'});
|
||||||
|
}).then(function (ownerUser) {
|
||||||
|
if (ownerUser) {
|
||||||
|
return dataProvider.User.setup(setupUser, _.extend({id: ownerUser.id}, internal));
|
||||||
|
} else {
|
||||||
|
return dataProvider.Role.findOne({name: 'Owner'}).then(function (ownerRole) {
|
||||||
|
setupUser.roles = [ownerRole.id];
|
||||||
|
return dataProvider.User.add(setupUser, internal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).then(function (user) {
|
||||||
|
var userSettings = [];
|
||||||
|
|
||||||
|
// Handles the additional values set by the setup screen.
|
||||||
|
if (!_.isEmpty(setupUser.blogTitle)) {
|
||||||
|
userSettings.push({key: 'title', value: setupUser.blogTitle});
|
||||||
|
userSettings.push({key: 'description', value: 'Thoughts, stories and ideas.'});
|
||||||
|
}
|
||||||
|
|
||||||
|
setupUser = user.toJSON(internal);
|
||||||
|
return settings.edit({settings: userSettings}, {context: {user: setupUser.id}});
|
||||||
|
}).then(function () {
|
||||||
|
return Promise.resolve(setupUser);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ## Authentication API Methods
|
* ## Authentication API Methods
|
||||||
*
|
*
|
||||||
|
@ -153,7 +192,7 @@ authentication = {
|
||||||
* @param {string} options.email The email to check for an invitation on
|
* @param {string} options.email The email to check for an invitation on
|
||||||
* @returns {Promise(Invitation}} An invitation status
|
* @returns {Promise(Invitation}} An invitation status
|
||||||
*/
|
*/
|
||||||
isInvitation: function (options) {
|
isInvitation: function isInvitation(options) {
|
||||||
return authentication.isSetup().then(function (result) {
|
return authentication.isSetup().then(function (result) {
|
||||||
var setup = result.setup[0].status;
|
var setup = result.setup[0].status;
|
||||||
|
|
||||||
|
@ -175,7 +214,7 @@ authentication = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
isSetup: function () {
|
isSetup: function isSetup() {
|
||||||
return dataProvider.User.query(function (qb) {
|
return dataProvider.User.query(function (qb) {
|
||||||
qb.whereIn('status', ['active', 'warn-1', 'warn-2', 'warn-3', 'warn-4', 'locked']);
|
qb.whereIn('status', ['active', 'warn-1', 'warn-2', 'warn-3', 'warn-4', 'locked']);
|
||||||
}).fetch().then(function (users) {
|
}).fetch().then(function (users) {
|
||||||
|
@ -187,9 +226,8 @@ authentication = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
setup: function (object) {
|
setup: function setup(object) {
|
||||||
var setupUser,
|
var setupUser;
|
||||||
internal = {context: {internal: true}};
|
|
||||||
|
|
||||||
return authentication.isSetup().then(function (result) {
|
return authentication.isSetup().then(function (result) {
|
||||||
var setup = result.setup[0].status;
|
var setup = result.setup[0].status;
|
||||||
|
@ -198,37 +236,10 @@ authentication = {
|
||||||
return Promise.reject(new errors.NoPermissionError('Setup has already been completed.'));
|
return Promise.reject(new errors.NoPermissionError('Setup has already been completed.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.checkObject(object, 'setup');
|
return setupTasks(object);
|
||||||
}).then(function (checkedSetupData) {
|
}).then(function (result) {
|
||||||
setupUser = {
|
setupUser = result;
|
||||||
name: checkedSetupData.setup[0].name,
|
|
||||||
email: checkedSetupData.setup[0].email,
|
|
||||||
password: checkedSetupData.setup[0].password,
|
|
||||||
blogTitle: checkedSetupData.setup[0].blogTitle,
|
|
||||||
status: 'active'
|
|
||||||
};
|
|
||||||
|
|
||||||
return dataProvider.User.findOne({role: 'Owner', status: 'all'});
|
|
||||||
}).then(function (ownerUser) {
|
|
||||||
if (ownerUser) {
|
|
||||||
return dataProvider.User.setup(setupUser, _.extend({id: ownerUser.id}, internal));
|
|
||||||
} else {
|
|
||||||
return dataProvider.Role.findOne({name: 'Owner'}).then(function (ownerRole) {
|
|
||||||
setupUser.roles = [ownerRole.id];
|
|
||||||
return dataProvider.User.add(setupUser, internal);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).then(function (user) {
|
|
||||||
var userSettings = [];
|
|
||||||
|
|
||||||
// Handles the additional values set by the setup screen.
|
|
||||||
if (!_.isEmpty(setupUser.blogTitle)) {
|
|
||||||
userSettings.push({key: 'title', value: setupUser.blogTitle});
|
|
||||||
userSettings.push({key: 'description', value: 'Thoughts, stories and ideas.'});
|
|
||||||
}
|
|
||||||
setupUser = user.toJSON(internal);
|
|
||||||
return settings.edit({settings: userSettings}, {context: {user: setupUser.id}});
|
|
||||||
}).then(function () {
|
|
||||||
var data = {
|
var data = {
|
||||||
ownerEmail: setupUser.email
|
ownerEmail: setupUser.email
|
||||||
};
|
};
|
||||||
|
@ -260,22 +271,21 @@ authentication = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
revoke: function (object) {
|
updateSetup: function updateSetup(object, options) {
|
||||||
var token;
|
if (!options.context || !options.context.user) {
|
||||||
|
return Promise.reject(new errors.NoPermissionError('You are not logged in.'));
|
||||||
if (object.token_type_hint && object.token_type_hint === 'access_token') {
|
|
||||||
token = dataProvider.Accesstoken;
|
|
||||||
} else if (object.token_type_hint && object.token_type_hint === 'refresh_token') {
|
|
||||||
token = dataProvider.Refreshtoken;
|
|
||||||
} else {
|
|
||||||
return errors.BadRequestError('Invalid token_type_hint given.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return token.destroyByToken({token: object.token}).then(function () {
|
return dataProvider.User.findOne({role: 'Owner', status: 'all'}).then(function (result) {
|
||||||
return Promise.resolve({token: object.token});
|
var user = result.toJSON();
|
||||||
}, function () {
|
|
||||||
// On error we still want a 200. See https://tools.ietf.org/html/rfc7009#page-5
|
if (user.id !== options.context.user) {
|
||||||
return Promise.resolve({token: object.token, error: 'Invalid token provided'});
|
return Promise.reject(new errors.NoPermissionError('You are not the blog owner.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return setupTasks(object);
|
||||||
|
}).then(function (result) {
|
||||||
|
return Promise.resolve({users: [result]});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -111,7 +111,8 @@ 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'))) {
|
||||||
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) {
|
||||||
|
|
|
@ -77,6 +77,7 @@ apiRoutes = function apiRoutes(middleware) {
|
||||||
router.post('/authentication/invitation', api.http(api.authentication.acceptInvitation));
|
router.post('/authentication/invitation', api.http(api.authentication.acceptInvitation));
|
||||||
router.get('/authentication/invitation', api.http(api.authentication.isInvitation));
|
router.get('/authentication/invitation', api.http(api.authentication.isInvitation));
|
||||||
router.post('/authentication/setup', api.http(api.authentication.setup));
|
router.post('/authentication/setup', api.http(api.authentication.setup));
|
||||||
|
router.put('/authentication/setup', api.http(api.authentication.updateSetup));
|
||||||
router.get('/authentication/setup', api.http(api.authentication.isSetup));
|
router.get('/authentication/setup', api.http(api.authentication.isSetup));
|
||||||
router.post('/authentication/token',
|
router.post('/authentication/token',
|
||||||
middleware.spamPrevention.signin,
|
middleware.spamPrevention.signin,
|
||||||
|
|
|
@ -7,7 +7,8 @@ var testUtils = require('../../utils'),
|
||||||
|
|
||||||
// Stuff we are testing
|
// Stuff we are testing
|
||||||
mail = rewire('../../../server/api/mail'),
|
mail = rewire('../../../server/api/mail'),
|
||||||
AuthAPI = require('../../../server/api/authentication');
|
AuthAPI = require('../../../server/api/authentication'),
|
||||||
|
context = testUtils.context;
|
||||||
|
|
||||||
describe('Authentication API', function () {
|
describe('Authentication API', function () {
|
||||||
// Keep the DB clean
|
// Keep the DB clean
|
||||||
|
@ -81,7 +82,7 @@ describe('Authentication API', function () {
|
||||||
name: 'test user',
|
name: 'test user',
|
||||||
email: 'test@example.com',
|
email: 'test@example.com',
|
||||||
password: 'areallygoodpassword',
|
password: 'areallygoodpassword',
|
||||||
title: 'a test blog'
|
blogTitle: 'a test blog'
|
||||||
};
|
};
|
||||||
|
|
||||||
AuthAPI.setup({setup: [setupData]}).then(function () {
|
AuthAPI.setup({setup: [setupData]}).then(function () {
|
||||||
|
@ -98,6 +99,112 @@ describe('Authentication API', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Setup Update', function () {
|
||||||
|
describe('Setup not complete', function () {
|
||||||
|
beforeEach(testUtils.setup('roles', 'owner:pre', 'settings', 'perms:setting', 'perms:init'));
|
||||||
|
|
||||||
|
it('should report that setup has not been completed', function (done) {
|
||||||
|
AuthAPI.isSetup().then(function (result) {
|
||||||
|
should.exist(result);
|
||||||
|
result.setup[0].status.should.be.false;
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not allow setup to be updated', function (done) {
|
||||||
|
var setupData = {
|
||||||
|
name: 'test user',
|
||||||
|
email: 'test@example.com',
|
||||||
|
password: 'areallygoodpassword',
|
||||||
|
blogTitle: 'a test blog'
|
||||||
|
};
|
||||||
|
|
||||||
|
AuthAPI.updateSetup({setup: [setupData]}, {}).then(function () {
|
||||||
|
done(new Error('Update was able to be run'));
|
||||||
|
}).catch(function (err) {
|
||||||
|
should.exist(err);
|
||||||
|
|
||||||
|
err.name.should.equal('NoPermissionError');
|
||||||
|
err.code.should.equal(403);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Not Owner', function () {
|
||||||
|
beforeEach(testUtils.setup('roles', 'users:roles', 'settings', 'perms:setting', 'perms:init', 'perms:user'));
|
||||||
|
|
||||||
|
it('should report that setup has been completed', function (done) {
|
||||||
|
AuthAPI.isSetup().then(function (result) {
|
||||||
|
should.exist(result);
|
||||||
|
result.setup[0].status.should.be.true;
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not allow setup to be updated', function (done) {
|
||||||
|
var setupData = {
|
||||||
|
name: 'test user',
|
||||||
|
email: 'test@example.com',
|
||||||
|
password: 'areallygoodpassword',
|
||||||
|
blogTitle: 'a test blog'
|
||||||
|
};
|
||||||
|
|
||||||
|
AuthAPI.updateSetup({setup: [setupData]}, context.author).then(function () {
|
||||||
|
done(new Error('Update was able to be run'));
|
||||||
|
}).catch(function (err) {
|
||||||
|
should.exist(err);
|
||||||
|
|
||||||
|
err.name.should.equal('NoPermissionError');
|
||||||
|
err.code.should.equal(403);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Owner', function () {
|
||||||
|
beforeEach(testUtils.setup('roles', 'users:roles', 'settings', 'perms:setting', 'perms:init'));
|
||||||
|
|
||||||
|
it('should report that setup has been completed', function (done) {
|
||||||
|
AuthAPI.isSetup().then(function (result) {
|
||||||
|
should.exist(result);
|
||||||
|
result.setup[0].status.should.be.true;
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow setup to be updated', function (done) {
|
||||||
|
var setupData = {
|
||||||
|
name: 'test user',
|
||||||
|
email: 'test@example.com',
|
||||||
|
password: 'areallygoodpassword',
|
||||||
|
blogTitle: 'a test blog'
|
||||||
|
};
|
||||||
|
|
||||||
|
AuthAPI.updateSetup({setup: [setupData]}, context.owner).then(function (result) {
|
||||||
|
should.exist(result);
|
||||||
|
should.exist(result.users);
|
||||||
|
should.not.exist(result.meta);
|
||||||
|
result.users.should.have.length(1);
|
||||||
|
testUtils.API.checkResponse(result.users[0], 'user');
|
||||||
|
|
||||||
|
var newUser = result.users[0];
|
||||||
|
|
||||||
|
newUser.id.should.equal(1);
|
||||||
|
newUser.name.should.equal(setupData.name);
|
||||||
|
newUser.email.should.equal(setupData.email);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// describe('Authentication', function () {
|
// describe('Authentication', function () {
|
||||||
|
|
||||||
// describe('Setup not completed', function () {
|
// describe('Setup not completed', function () {
|
||||||
|
|
Loading…
Add table
Reference in a new issue